在React中忽略i18n的JSON导出设置
应用场合
用create-react-app创建的项目,当使用i18n-next进行多语言化时,手动编写*.json的翻译数据很麻烦。希望能自动找到*.tsx或*.js中需要翻译的部分,并追加至*.json中!
这次介绍的例子是一个只涉及前端部分的非常简单的SPA。
i18n-next是一个很实用的工具,它可以引入locize,也可以用于后端开发,了解一下会很划算。
迷上瘾的点
我先解释一下陷阱点。
最近似乎很流行babel-plugin-i18next-extract插件。然而,必须更改webpack的配置。如果你正在使用create-react-app创建应用程序,可以通过使用命令npm eject来实现更改webpack配置,但这是一个不可逆的操作,也不是一个可行的解决方案。因此,最好不要继续使用babel-plugin-i18next-extract。相反,推荐的是官方文档中提到的i18next-parser。
在提取工具中我们也提到了i18next-parser。
首先,公式文件中提到的是i18next-parser。
npm install -g i18next-parser
设定
参考公式文档,写下i18next-parser的配置。
module.exports = {
locales: ['en', 'ja', 'cn'],
output: 'src/locales/$LOCALE/$NAMESPACE.json',
}
-
- locale: 欲しい分だけ言語を追記
- output: 位置がsrcの中でないと、tsxからimport出来ないので、デフォルト設定を上書き
设置npm的脚本。
"scripts": {
"i18next-extract": "i18next 'src/**/*.{tsx,ts}'"
}
现在设置完成了,我会将翻译文件输出为JSON格式。
npm run i18next-extract
然后,应该以以下的结构进行输出。
./
┃
┣━ src
┃ ┣━ locales
┃ ┃ ┣━ cn
┃ ┃ ┃ ┗━ translation.json
┃ ┃ ┣━ en
┃ ┃ ┃ ┗━ translation.json
┃ ┃ ┗━ jp
┃ ┃ ┗━ translation.json
代码更改 ̂
以下是一种可能的中文翻译:
从这里开始,我们会在源代码中添加用于翻译的配置。
首先,在顶层的React文件中编写i18n的初始化设置。
同时,将之前输出的translation.json文件进行配置。
import React from 'react';
import ReactDOM from 'react-dom';
import './index.sass';
import reportWebVitals from './reportWebVitals';
import App from "./components/App";
import { createBrowserHistory } from "history"
import { Router } from 'react-router';
import HeaderApp from './components/header';
// i18n
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import jaCommon from './locales/ja/translation.json'
import enCommon from './locales/en/translation.json'
import cnCommon from './locales/cn/translation.json'
i18next.use(initReactI18next).init({
debug: true,
resources : {
ja:{common:jaCommon},
en:{common:enCommon},
cn:{common:cnCommon},
},
lng: 'ja',
fallbackLng: 'ja',
keySeparator: false,
interpolation: { escapeValue: false },
});
const history = createBrowserHistory({ basename: '/' });
ReactDOM.render(
<React.StrictMode>
<Router history={history}>
<HeaderApp/>
<App></App>
</Router>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals(console.log);
的定义如下。
import React from 'react';
import i18next from 'i18next';
import { useTranslation } from 'react-i18next';
import { useEffect } from 'react'
import ja_Trans from '../locales/ja/maincontent.json'
import en_Trans from '../locales/en/maincontent.json'
import cn_Trans from '../locales/cn/maincontent.json'
export function Translate() {
const { t } = useTranslation('maincontent');
useEffect(() => {
i18next.addResources('ja', 'maincontent', ja_Trans);
i18next.addResources('en', 'maincontent', en_Trans);
i18next.addResources('cn', 'maincontent', cn_Trans);
}, [])
return (
<React.StrictMode>
<p>{t('message')}</p>
</React.StrictMode>
);
}
class App extends React.Component {
render() {
return <Translate/>;
}
}
export default App;
只有这样还无法切换语言。接下来,我将详细介绍在之前的index.tsx中写的的细节。
import React from 'react';
import { FunctionComponent } from "react";
import { LanugageSelector } from "./LanguageSelector";
import { useTranslation } from 'react-i18next'
import { useState } from 'react';
import { useEffect } from 'react';
const HeaderApp: FunctionComponent = () => {
const [t, i18n] = useTranslation();
const languages = [{ code: "ja", name: "JAPANESE" }, { code: "en", name: "ENGLISH" }, { code: "cn", name: "CHINESE" }];
const [currentLang, setCurrentLang] = useState("ja");
// Change language of i18n
useEffect(() => {
i18n.changeLanguage(currentLang);
}, [currentLang, i18n])
// Handler
const handleLanguageSelectionChange = (lang: string) => {
setCurrentLang(lang);
}
return (
<React.StrictMode>
<header>
<div>
<ul>
<LanugageSelector languages={languages} selectedLanguage={currentLang} onLanguageSelectionChange={handleLanguageSelectionChange} />
</ul>
</div>
</header>
</React.StrictMode>
);
}
export default HeaderApp;
的定义如下。
import React, { FunctionComponent } from "react";
export type LanguageSelectorProps = {
languages: { code: string, name: string }[],
selectedLanguage: string,
onLanguageSelectionChange: (lang: string) => void,
}
export const LanugageSelector: FunctionComponent<LanguageSelectorProps> = (props) => {
const langs = props.languages.map((lang) => {
return (lang.code === props.selectedLanguage) ? '' : <li><p onClick={() => props.onLanguageSelectionChange(lang.code)}>{lang.name}</p></li>
});
return (
<div className="i18n">
{langs}
</div>
);
}
通过,显示英语、日语和中文。点击它将切换显示。使用三元运算符,消去了当前显示的语言。
再次提取
如果能写到这个地方,那就再次执行之前的命令试试看吧。
npm run i18next-extract
./
┃
┣━ src
┃ ┣━ locales
┃ ┃ ┣━ cn
┃ ┃ ┃ ┣━ maincontent.json
┃ ┃ ┃ ┗━ translation.json
┃ ┃ ┣━ en
┃ ┃ ┃ ┣━ maincontent.json
┃ ┃ ┃ ┗━ translation.json
┃ ┃ ┗━ jp
┃ ┃ ┃ ┣━ maincontent.json
┃ ┃ ┗━ translation.json
只要你能走到这一步,恭喜你!接下来只需要不断地写翻译就可以了。
总结
在npm start的过程中,如何运行npm run i18next-extract呢?
胜利者!