(React + TypeScript)UseContextとi18nextを使ってi18n対応してみるの続きみたいな感じです。
i18nextを使ったi18n対応で、コンポーネントごとにファイルを分けたいので名前空間を導入します。
名前空間の導入
import { useTranslation, initReactI18next } from 'react-i18next';
import i18n from 'i18next';
import enCommon from './locales/en/common.json';
import jaCommon from './locales/ja/common.json';
import jaNamespace1 from './locales/ja/namespace1.json';
import enNamespace1 from './locales/en/namespace1.json'
i18n.use(initReactI18next).init({
debug: true,
resources: {
en: { common: enCommon },
ja: { common: jaCommon },
},
lng: 'ja',
fallbackLng: false,
returnEmptyString: false,
});
// 名前空間の追加
i18n.addResources('ja', 'namespace1', jaNamespace1);
i18n.addResources('en', 'namespace1', enNamespace1);
export const App: FC = () => {
const { i18n } = useTranslation();
// ...以下省略
}
初期化時にはcommonという名前空間しかありませんでしたが、addResources('locale名', '名前空間(ファイル名)', importしたファイル)
という関数を使って別の名前空間を追加できます。
名前空間の使用
import { useTranslation } from 'react-i18next';
export const Component = () => {
const { t } = useTranslation('namespace1');
return(
<p>{t('テスト1')}</p>
<p>{t('テスト2')}</p>
);
}
useTranslation()
の引数に名前空間の名前をいれることで、このコンポーネント内ではデフォルトの名前空間として、namespace1.json内で定義されてる単語、文章を出力します。(この例ではテスト1とテスト2がキーになります)
辞書ファイルの自動生成
こちらの記事で紹介されている自動で辞書を生成するbabel-plugin-i18next-extract
というライブラリですが、名前空間を自動で検出してくれます(助かるー)。
上記の章のテスト1、テスト2というキーが存在しない場合、自動でテスト1、テスト2というキーを作成してくれます。
"scripts": {
"i18next-extract": "NODE_ENV=development babel './src/**/*.{js,jsx,ts,tsx}'"
},
"babel": {
"presets": [
"react-app"
],
"plugins": [
[
"i18next-extract",
{
"locales": [
"ja",
"en"
],
"outputPath": "./src/locales/{{locale}}/{{ns}}.json"
}
]
]
},
"dependencies": {
...以下省略
ここでoutputPath
が出力するjsonファイルになります。
そのため日本語の辞書は、src/locales/ja/namespace1.json
へ、英語の辞書はsrc/locales/en/namespace1.json
へ自動的に出力されます。
あとは、yarn i18next-extract
するだけです。
疑問
本当は名前空間を導入して、各ページごとに読み込むファイルを分けたかったんですが、うまくいきませんでした。。。
ページごとにi18nを初期化すればできそうだけど、なんか違う様な。。。
詳しい方いらっしゃたら教えてください。
(2020.02.5追記)
一晩寝かせておいたらなんかできました。
useEffect(() => {
i18n.addResources('ja', 'namespace2', jaNamespace2);
i18n.addResources('en', 'namespace2', enNamespace2);
},[])
こんな感じでuseEffectで囲うだけ。
参考文献
https://www.i18next.com/overview/api#addresourcebundle
https://i18next-extract.netlify.com/#/configuration