探索 Next.js:用 next-i18next 完成多語言支援

Weian Wang
6 min readApr 17, 2021
Photo by Kyle Glenn on Unsplash

網際網路沒有邊界,可是語言有。要讓網站打破語言的限制就必須支援多國語言,因此支援多國語言對現代網站來說是非常重要的功能。對於 React 社群來說,有許多的套件可以實現這個功能,但是如果你的專案使用 Next.js 作為框架,next-i18next 就是最好的選擇。這篇文章中我們將實作一個小範例,使用 next-i18next 來完成多語系支援。

建立專案

首先建立一個專案,然後完成 Next.js 開發環境的配置。詳細步驟可以參考這篇文章。接著安裝 next-i18next。

npm install — save next-i18next

yarn add next-i18next

詳細步驟可以參考這篇文章。然後安裝 next-i18next。在根目錄下的 public 資料夾建立一個 static 資料夾,然後在 static 資料夾下建立一個 locales 資料夾,這個資料夾是用來存放不同語言的文字內容,每新增一個語言就建立一個相對應的資料夾。我們在範例中會用到四種語言:中文、英文、法文和西班牙文,就在 locales 資料夾下新增4個資料夾,用語系的編碼來去命名,分別是 zhHant, en, fr, es. 檔案結構會長這樣:

project structure

在根目錄下新增一個資料夾: i18n.js,這個檔案是用來讓我們配置 next-i18next 套件提供的函數。localePath 是存放語言文本的檔案路徑;defaultLanguage 是專案預設的語言;otherLanguages 就是專案其他的語言;localeSubpaths 則是各個語言的子路徑。

i18n

接著打開 _app.js 檔案,從 next-i18next 引入高階組件 (higher order component) appWithTranslation,然後用 appWithTranslation 包裝 MyApp 組件。

_app.js

接著我們回到 locales 資料夾,在不同語言的資料夾下新增sample .json 檔案放置我們的文本,這裡的檔名就是之後要傳進 withTranslation 的 namespaces,結構如下:

en
zhHant

完成配置後,就可以開始實作功能了。首先在 ./pages 目錄下新增一個 Sample 資料夾,我們的功能就會放在這個路徑底下。接著引入高階組件(higher order component) withTranslation,將文本的 namespaces 傳入 withTranslation,namespaces 就是我們替文本 .json 檔案取的名字,這樣專案才會渲染出正確的文本。然後再用 withTranslation 包裝 SamplePage 組件。

我們還需要用到 getInitialProps,namespacesRequired 就是文本 .json 檔的名稱,這是為了讓專案在伺服器端就能得到正確的文本。我們傳到 component 的 props {t} 就包含了文本,在 component 層我們就可以透過 {t} 控制文本的渲染。

./Sample/index.js

注意,每一個 page 層的 index.js 檔都需要做同樣的配置。

接下來在 component 目錄下新增 Sample.js 檔,一樣要引入高階組件 withTranslation,傳入 namespaces 來包裝 component,然後引入從 page 層傳下來的 props,主要是 t function,我們需要它從 locales 資料夾取得文本,引入 t function 和其他 props 可以寫成這樣:

const Sample = ({t,...props}) => {}

簡單的說說這個功能的呈現方式,文本內容會隨著我們切換語言而改變,語言則由一個下拉式選單控制。

首先創造一個區塊呈現我們的文本內容,然後創造一個下拉式選單,這裡我用的是 Material UI 的 Select 套件,每次當 Select 狀態改變時我們就會根據 Select 的 value 去改變語言,用的是 i18n 的 changeLanguage function。程式碼如下:

Sample.js

讓我們看看效果如何吧:

子路徑

剛剛完成的功能非常成功!

接下來我們要讓 url 動起來,也就是同一個頁面在切換語言時 url 也會改變,讓使用者可以從 url 辨識網頁的語言也是多語系支援很重要的功能之一。

這個步驟非常簡單,讓我們回到 i18n.js ,在 NextI18Next 下新增一個 localeSubpaths object,將 localeSubpaths 當作 key,我們要的子路徑當作 value。程式碼如下:

localeSubpaths:{    
zhHant:'cn',
fr: 'fr',
es: 'es'
}

然後打開 next.config.js 檔,引入 nextI18NextRewriters並傳入 localeSubpaths,改變配置,程式碼如下:

next.config.js

看看效果如何吧:

有動態的 url 了!

恭喜!我們完成了這個多語系支援的實作,接下來把它應用到自己的專案吧!

--

--