最近公司有React專案有多語系切換的需求,在整合的過程中,有一些心得感想跟大家分享。
在這個需求出來之後,我搜尋了React的i18n相關套件,發現了 React-i18next,我整合的過程大概如下
1.先準備好你預先翻譯好的語系檔並且放進專案的目錄中,我是在 src 中新建 asset 資料夾以便放置一些靜態的檔案(不一定要照我的,可以放到自己喜歡的地方)
// src/asset/i18n/zh-TW.json
{
"quickAdd": {
"title": "快速新增",
"listTitle": {
"customer": "客戶",
"company": "公司",
"work": "工作",
"meeting": "會議",
"event": "事件/活動",
"business": "商機",
"consumption": "消費",
"coupon": "點券",
"message": "行銷簡訊",
"mail": "行銷郵件",
"contact": "聯繫腳本",
"note": "記事本",
"announcement": "佈告欄",
"tag": "標籤"
}
},
}
語系檔範例
檔案結構範例
2.新建 i18n.js
,引入語系檔與設定參數
// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './assets/i18n/en.json';
import jp from './assets/i18n/ja-JP.json';
import tw from './assets/i18n/zh-TW.json';
const resources = {
en: {
translation: en,
},
'ja-JP': {
translation: jp,
},
'zh-TW': {
translation: tw,
},
};
i18n.use(initReactI18next).init({
resources,
lng: 'zh-TW', //預設語言
fallbackLng: 'zh-TW', //如果當前切換的語言沒有對應的翻譯則使用這個語言,
interpolation: {
escapeValue: false,
},
});
export default i18n;
如果語系檔中有巢狀的結構,則 escapeValue 要設為 false,這樣就可以透過物件的方式來取得巢狀內的翻譯
3.在入口檔案 import 剛剛的 i18n
// src/index.js
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Root from './Root';
import registerServiceWorker from './registerServiceWorker';
import './i18n';
const root = document.getElementById('root') as HTMLElement;
ReactDOM.render(<Root />, root);
registerServiceWorker();
4.接下來就可以透過 Translation(hoc) 或是 useTranslation (hook) 來達成多語系切換的功能
// path/to/yourComponent.js
/* Class Components */
import { Translation } from 'react-i18next';
class Hello extends React.Component{
render() {
return (
<Translation>
{t => (
<World>{t('quickAdd.title')}<World>
)}
</Translation>
);
}
}
Class Components 可以使用 Translation 完成我們的目的
// path/to/yourComponent.js
/* Functional Components */
import { useTranslation } from 'react-i18next';
// es5
function Hello() {
const { t } = useTranslation();
return (
<World>{t('quickAdd.title')}<World>
);
}
// es6
const Hello = ()=>{
const { t } = useTranslation();
return (
<World>{t('quickAdd.title')}<World>
);
}
如果是 functional component 則可以使用 useTranslation
5.接著透過解構拿出 i18n ,使用 i18n.changeLanguage 函數來切換當前語系檔,這邊我有使用 useEffect 使我 state 中的 lang 一改變就直接觸發修改語系
// path/to/yourComponent.js
/* 切換語系 */
const { i18n } = useTranslation();
//React hook
const [lang, setLang] = useState<Lang>(null);
useEffect(() => {
if (lang !== null) i18n.changeLanguage(lang.value);
}, [lang]);
setLang('zh-TW');
setLang('en');
setLang('ja-JP');
心得有點倉促 我有機會會再來修改這一篇文章
參考資料: react-i18next:https://www.i18next.com/