React react-i18next 「1つの」 json file から各言語のテキストを展開する
map を使わず読み込む場合
en.json
{ "welcome": "Welcome to i18next", "hello": "Hello", "changeLang": "Change Language" }
ja.json
{ "welcome": "i18next へようこそ!", "hello": "こんにちわ", "changeLang": "言語を切り替える" }
App.js/import
import React, { useState, useEffect } from 'react'; import i18n from 'i18next' import { initReactI18next } from 'react-i18next' import { useTranslation } from 'react-i18next'
App.js/ヘッダー部分
i18n.use(initReactI18next).init({ resources: { en: { translation: enJson, }, ja: { translation: jaJson, }, }, lng: 'en', fallback: 'en', interpolation: {escapeValue: false}, });
App.js/ Function App 前半部分
function App() { const [t, i18n] = useTranslation(); const [lang, setLang] = useState('en'); useEffect( () => { i18n.changeLanguage(lang) } ,[lang, i18n]);
App.js/ Function App return 部分
return ( <div className="App"> <p>{t('welcome')}</p> <div> <button onClick={ () => setLang('en') }> English </button> <button onClick={ () => setLang('ja') }> Japanese </button> </div> </div> ); } export default App;
result
これで切り替えが動く
json ファイルからまとめて map する場合
locale.json
[ { "name": "en", "welcome": "Welcome to i18next", "hello": "Hello", "changeLang": "Change Language" }, { "name": "zh", "welcome": "欢迎光临 i18next", "hello": "你好", "changeLang": "用中文" }, { "name": "ja", "welcome": "i18next へようこそ!", "hello": "こんにちわ", "changeLang": "言語を切り替える" }, { "name": "ko", "welcome": "i18next에 오신 것을 환영합니다", "hello": "안녕하세요", "changeLang": "한국어 변경" }, { "name": "es", "welcome": "Bienvenida a i18next", "hello": "Hola", "changeLang": "usar español" } ]
App.js/ json の読み込み確認
import locales from './locales/lang.json' console.log('Locales read:') console.table(locales)
これで json ファイルの中に 一つの配列が入っていて、その中に
name: "en", welcome: "welcome to i..." と入っていることを読み取ることができた。
あとはこのデータをいかに react-i18next に渡すかになる。
init の失敗例
これで失敗して苦戦した。
i18n.use(initReactI18next).init({ resources: { locales.map( (locale) => { console.log(locale.name); {locale.name}:{ translation: {locale} } } ) }, lng: 'en', fallback: 'en', interpolation: {escapeValue: false}, });
これだと動かない。
i18n は object で受け取ることになってるのに、配列で渡しているからだ。
全体配列から1オブジェクト事に
object で json ファイル自体を書き直す手もあるが、ファイルはそのままでも、 取り出し方を工夫すれば object として渡せる。
array.reduce() を使って配列一つ一つに処理を施し、object として作る。
object はこれ { }
i18n.use(initReactI18next).init({ resources: locales.reduce( (stack, locale) => { stack[locale.name] = { translation: locale } return stack }, {}), lng: 'en', fallback: 'en', interpolation: { escapeValue: false } });
これで 前述の locale.json を当てる
[ { hoge: ua, }, { huu: gya, } , ]
の形ででかい配列にオブジェクトが5つ入ってるやつ。
stack[local.name] が en が入り
locale として今回使われている
配列の 0 こ目の object が当たる。
その object を i18next さんの translation に当ててひと言語分完了。
次に stack[local.name] に zh
locale として 1 こ目の json...
と当たっていき、全てが当てはめられる。
5 言語のボタンも map で書く
明日やる