vite-i18n-loader: 专注于大型项目的 i18n 管理工具
大型项目里的i18n文件往往很大,管理好,保证代码无冲突是个必须要解决的问题
项目主页: https://github.com/afeiship/i18n-packages/tree/main/packages/vite-i18n-loader
背景
在公司项目中,我使用
public/locales/*.json文件来管理项目的国际化,但项目变大,i18n文件会变得巨大,巨难维护
- 开发人员变多的时候,经常会有多个人要改同一个文件的情况,会经常有代码冲突产生
- 使用自己定义的时候,也很难找到对应的 key 来显示
i18n的值- 翻译部分,不需要借助翻译软件,而是由 AI 自动提示生成,这也是为什么下面的
locale.yml推荐写在一个文件里的原因
安装
yarn add --dev @jswork/vite-i18n-loader
yarn add i18next-http-backend react-i18next i18next
// 更方便的 react 组件封装
yarn add @jswork/react-i18n @jswork/i18n-language-detect
// 确认存在 next
yarn add @jswork/next配置
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import i18nLoader from '@jswork/vite-i18n-loader';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), i18nLoader()],
server: {
host: '0.0.0.0'
// host: true
}
});LocalProvider
__VERSION__: 这个值,可以考虑在版本变化的时候更新一下- 固定值:有可能有CDN之类的缓存
- 根据版本变化 - 推荐
- 如果不写:就是当前的
Date.now()的值,可能会有一定的流量开销
import { LocaleProvider } from "@jswork/react-i18n";
import LNGDetect from "@jswork/i18n-language-detect";
export default (props: any) => {
return (
<LocaleProvider
harmony
plugins={[LNGDetect]}
options={{ debug: false, publicURL: "/", version: "__VERSION__" }}
routerType="hash"
mode="backend"
>
{props.children}
</LocaleProvider>
);
};套在APP上
import AbcComponent from "./components/abc-component";
import LocaleProvider from "./locale-provider";
export default function App() {
return (
<LocaleProvider>
<div className="debug container mx-auto my-10 bg-gray-200 p-5" data-role="app-container">
<h1 className="text-3xl font-bold">Hello world!</h1>
<AbcComponent />
</div>
</LocaleProvider>
);
}样板文件
重点关心这个目录:
abc-component以及这个文件 locale.yml
.
├── App.tsx
├── assets
│ └── react.svg
├── components
│ ├── abc-component
│ │ ├── index.tsx
│ │ └── locale.yml定义一个 locale.yml
文件里的值最终会写到
zh-CN/en-US.json的components.abc-component这个 key 上。为什么这么拆分,因为这里, AI🤖 就可以帮你完成翻译啦 ~
languages:
zh-CN:
title: 组件名称
description: 第一个i18n示例组件
en-US:
title: Component Name
description: The first i18n example component组件中使用
/**
* @email: aric.zheng@alo7.com
* @description: A React component.
* @updated_at: 2024-09-21 08:49:49
*/
const Anonymous = () => {
const { t } = nx.useIntl();
return (
<div className="debug-red p-2">
<h1>{t('components.abc-component.title')}</h1>
<p>{t('components.abc-component.description')}</p>
</div>
);
};
export default Anonymous;优化版,useIntl
可以指定
scope(keyPrefix),即 local id
const Anonymous = () => {
const { t } = nx.useIntl('components.abc-component');
return (
<div className="debug-red p-2">
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
);
};
export default Anonymous;