1、安装node包
npm install i18next react-i18next i18next-browser-languagedetector -S //安装国际化插件
npm install i18next-scanner -D // 扫描文件依赖
npm install crc -S // 中文通过crc32转码获得唯一的key, 也避免中文作为索引导致性能不佳和索取不准确问题
2、根目录新建 i18next-scaner.config.js 文件
const fs = require('fs');
const { crc32 } = require('crc');
const systemLanguage = {
zh_CN: 'zh-CN',
zh_HK: 'zh-HK',
en_GB: 'en-GB'
};
// 读取已经存在在en.json文件的词条
const existJsonData = fs.readFileSync('./scan/en-GB.json');
let existData = {};
try {
existData = JSON.parse(existJsonData);
} catch {
existData = {};
}
const keyList = Object.keys(existData);
module.exports = {
input: [
'src/**/*.{js,jsx,tsx,ts}',
// 不需要扫描的文件加!
'!src/locales/**',
'!**/node_modules/**'
],
output: './scan', // 输出目录
options: {
debug: true,
func: false,
trans: false,
lngs: [systemLanguage.zh_CN, systemLanguage.zh_HK, systemLanguage.en_GB],
defaultLng: systemLanguage.zh_CN,
resource: {
loadPath: './newJson/{{lng}}.json', // 输入路径 (手动新建目录)
savePath: './newJson/{{lng}}.json', // 输出路径 (输出会根据输入路径内容自增, 不会覆盖已有的key)
jsonIndent: 2,
lineEnding: '\n'
},
removeUnusedKeys: true,
nsSeparator: false, // namespace separator
keySeparator: false, // key separator
interpolation: {
prefix: '{{',
suffix: '}}'
}
},
// 这里我们要实现将中文转换成crc格式, 通过crc格式key作为索引, 最终实现语言包的切换.
transform: function (file, enc, done) {
// 自己通过该函数来加工key或value
const { parser } = this;
const content = fs.readFileSync(file.path, enc);
parser.parseFuncFromString(content, { list: ['t'] }, (key, options) => {
options.defaultValue = key;
const hashKey = `K${crc32(key).toString(16)}`; // crc32转换格式
// 如果词条不存在,则写入
if (!keyList.includes(hashKey)) {
parser.set(hashKey, options);
}
});
done();
}
};
3、根目录package.json配置扫描的运行命令
4、执行 npm run scan 扫描自动生成翻译文档
5、这个文件根据业务自行存放, 当前放在src/locales/index.js
import i18n from 'i18next';
import { initReactI18next, useTranslation } from 'react-i18next';
// i18next-browser-languagedetector插件 这是一个 i18next 语言检测插件,用于检测浏览器中的用户语言,
import LanguageDetector from 'i18next-browser-languagedetector';
import crc32 from 'crc/crc32';
// 引入需要实现国际化的简体、繁体、英文三种数据的json文件
import zhCN from 'antd/locale/zh_CN';
import zhHK from 'antd/locale/zh_HK';
import enGB from 'antd/locale/en_GB';
import localZh_CN from 'scan/zh-CN.json'; // 本地翻译中文文件
import localZh_HK from 'scan/zh-HK.json'; // 本地翻译中文粤语文件
import localEn_GB from 'scan/en-GB.json'; // 本地翻译英文文件
import config from '@/config';
const resources = {
cn: {
translation: localZh_CN,
...zhCN
},
hk: {
translation: localZh_HK,
...zhHK
},
en: {
translation: localEn_GB,
...enGB
}
};
i18n
.use(LanguageDetector) // 嗅探当前浏览器语言 zh-CN
.use(initReactI18next) // 将 i18n 向下传递给 react-i18next
.init({
// 初始化
resources, // 本地多语言数据
fallbackLng: config.lang, // 默认当前环境的语言
detection: {
caches: ['localStorage', 'sessionStorage', 'cookie']
}
});
// --------这里是i18next-scanner新增的配置-------------
export const $t = (key: string, params?: any[]): string => {
const hashKey = `K${crc32(key).toString(16)}`; // 将中文转换成crc32格式去匹配对应的json语言包
let words = i18n.t(hashKey);
// const { t } = useTranslation(); // 通过hooks
// let words = t(hashKey);
if (words === hashKey) {
words = key;
}
// 配置传递参数的场景, 目前仅支持数组,可在此拓展
if (Array.isArray(params)) {
const reg = /\((\d)\)/g;
words = words.replace(reg, (a: string, b: number) => {
return params[b];
});
}
return words;
};
export default i18n;
6、App.tsx里配置
7、页面中使用
8、切换语言组件
import Icon from '@/components/Icons';
import { Dropdown, Row, Col } from 'antd';
import { setLanguage, selectLanguage } from '@/store/reducer/langSlice';
import i18n from '@/locales';
const LanguageSetting = () => {
const dispatch = useAppDispatch();
const items = [
{
key: 'cn',
label: $t('简体')
},
{
key: 'hk',
label: $t('繁体')
},
{
key: 'en',
label: $t('英文')
}
];
const lang = useAppSelector(selectLanguage);
const langLabel = items.find((item) => item?.key === lang)?.label;
return (
<Dropdown
trigger={['hover']}
menu={{
items,
style: { width: 110 },
onClick: (e) => {
const { key } = e;
dispatch(setLanguage(key));
i18n.changeLanguage(key);
}
}}
>
<Row
gutter={10}
style={{
cursor: 'pointer',
marginTop: -2,
userSelect: 'none',
padding: '0 10px'
}}
>
<Col>
<Icon type="TranslationOutlined" />
</Col>
<Col>{langLabel}</Col>
</Row>
</Dropdown>
);
};
export default memo(LanguageSetting);