使用 react-i18next 來打造多國語言網站(i18n)

Louis Liao
7 min readAug 22, 2020

--

網際網路無遠弗屆,來自世界各個角落的人都有可能造訪你的網站,因此讓網站支持多種語言是非常普及的需求。最近研究了一下如何用 React 來打造一個支援多國語言的 i18n 網站,想來分享一下基本的使用方式與心得。但 i18n 是什麼呢?所謂的 i18n 是 Internationalization 這個英文的簡寫,國際化的意思,因為 Internationalization 去掉頭尾的 i 和 n 剛好還剩下18個字。

今天要使用的是 react-i18next,一個基於 React / React Native 的 i18n 框架,核心的概念為 ”Learn once — translate everywhere.” 。並且內建支援 SSR,使用方式非常的直接易懂。話不多說,我們開始吧!

react-i18next

建立專案

本篇文章範例會使用 create-react-app 來實作:

npx create-react-app react-i18n
cd react-i18n
npm start

建立好專案後,接下來依序用 npm 安裝相關套件:

npm install react-i18next i18next i18next-http-backend --save

react-i18next 與 i18next 為必備的核心套件。i18next-http-backend 則是能夠讓語言檔透過 XMLHttpRequest 或 the fetch API 來載入,非常推薦使用。

專案架構

此次範例專案架構如下:

├─public
│ └─locales //字典檔
│ ├─en
│ │ └─translation.json
│ ├─es
│ │ └─translation.json
│ └─zh-tw
│ └─translation.json
└─src
├─App.js
├─App.css
├─index.js //import i18n.js
├─index.css
├─package.json
└─i18n.js //i18n設定檔

i18n 設定檔

i18n.js 是專案的 i18n 設定檔,會在此實例化 i18n 並在 index.js 內 import 讓 webpack 打包。本次範例做的只是基本設定,詳細可至官方文件查看。這裡

語言檔

語言檔會放在 public/locales 內,並以語言再次分類到不同資料夾。語言檔是以 json 格式撰寫。本次範例專案的字典檔如下:

//en
{
"hello": "hello!",
"link": "Let's learn React <1>here</1>"
}
//zh-tw
{
"hello": "你好!",
"link": "一起來 <1>這裡</1> 學習 React 吧"
}
//es
{
"hello": "Hola!",
"link": "Aprendamos React<1>aquí</1>"
}

翻譯元件的內容

做好上面的設定後就可以在元件內使用 react-i18next 提供的多種不同的方式來取得對應對應的語言文檔囉。

使用 useTranslation hook

react-i18next 內建的 useTranslation hook 讓我們能直接在 functional components 中用 `t(‘xxx’)` 的語法取得語言資料。如下,在 zh-tw 環境下的 `t(‘hello’)` 就會顯示成 "你好!"。

import React from 'react';// the hook
import { useTranslation } from 'react-i18next';
function MyComponent () {
const { t, i18n } = useTranslation();
return <h1>{t('hello')}</h1> //你好!
}

withTranslation 使用高階組件 (HOC)

若是 Class components 的話可以使用高階組件 withTranslation 來取得對應語言內容。

import React from 'react';// the hoc
import { withTranslation } from 'react-i18next';
function MyComponent ({ t }) {
return <h1>{t('hello')}</h1>
}
export default withTranslation()(MyComponent);

使用 render prop

也可以用 render prop 並透過 t 來取得內容。

import React from 'react';// the render prop
import { Translation } from 'react-i18next';
export default function MyComponent () {
return (
<Translation>
{
t => <h1>{t('hello')}</h1>
}
</Translation>
)
}

使用 Trans 元件

若要翻譯的內容結構較為複雜(比如包含其他的 jsx tag),可以使用 react-i18next 提供的 Trans 元件。如下,i18nKey 用來對應語言檔的 key,在 es 環境下的 `t(‘link’)` 就會顯示成 “Aprendamos React<a>aquí</a>”。Trans 能做的事非常多,像是 props 傳入 count 來使用複數形式的翻譯。可見這裡

import React from 'react';
import { Trans } from 'react-i18next';
export default function MyComponent () {
return (
<Trans i18nKey="link">
一起來
<a>這裡</a>
學習 React 吧
</Trans>
)
}

切換語言

與上面的能夠取得語言文檔 t 一樣,我們能用同樣方式取得 i18n 的實例(如下) 並用它的 changeLanguage 方法來切換語言,下面的範例能用點擊按鈕來切換西中英三中語言:

const { t, i18n } = useTranslation();const changeLanguage = (lng) => {
i18n.changeLanguage(lng);
};
<div>
<button onClick={() => changeLanguage("zh-tw")}>中文</button>
<button onClick={() => changeLanguage("en")}>English</button>
<button onClick={() => changeLanguage("es")}>Español</button>
</div>

總結

做到這裡,已經算能完成基本的多國語言支持網站。當然如果是要實際應用到專案上,還得需要做一些進階的配置。比方說支援 SSR 或是將語言檔案模組化作更詳細的分類等等。今日只是拋磚引玉,以後若有機會也會再分享更詳細的心得。

最後附上本次範例的原始碼與 demo: https://github.com/a401120174/react-i18n-example

參考資料

--

--