探索 Next.js:用 next-i18next 完成多語言支援
網際網路沒有邊界,可是語言有。要讓網站打破語言的限制就必須支援多國語言,因此支援多國語言對現代網站來說是非常重要的功能。對於 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. 檔案結構會長這樣:
在根目錄下新增一個資料夾: i18n.js,這個檔案是用來讓我們配置 next-i18next 套件提供的函數。localePath 是存放語言文本的檔案路徑;defaultLanguage 是專案預設的語言;otherLanguages 就是專案其他的語言;localeSubpaths 則是各個語言的子路徑。
接著打開 _app.js 檔案,從 next-i18next 引入高階組件 (higher order component) appWithTranslation,然後用 appWithTranslation 包裝 MyApp 組件。
接著我們回到 locales 資料夾,在不同語言的資料夾下新增sample .json 檔案放置我們的文本,這裡的檔名就是之後要傳進 withTranslation 的 namespaces,結構如下:
完成配置後,就可以開始實作功能了。首先在 ./pages 目錄下新增一個 Sample 資料夾,我們的功能就會放在這個路徑底下。接著引入高階組件(higher order component) withTranslation,將文本的 namespaces 傳入 withTranslation,namespaces 就是我們替文本 .json 檔案取的名字,這樣專案才會渲染出正確的文本。然後再用 withTranslation 包裝 SamplePage 組件。
我們還需要用到 getInitialProps,namespacesRequired 就是文本 .json 檔的名稱,這是為了讓專案在伺服器端就能得到正確的文本。我們傳到 component 的 props {t} 就包含了文本,在 component 層我們就可以透過 {t} 控制文本的渲染。
注意,每一個 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。程式碼如下:
讓我們看看效果如何吧:
子路徑
剛剛完成的功能非常成功!
接下來我們要讓 url 動起來,也就是同一個頁面在切換語言時 url 也會改變,讓使用者可以從 url 辨識網頁的語言也是多語系支援很重要的功能之一。
這個步驟非常簡單,讓我們回到 i18n.js ,在 NextI18Next 下新增一個 localeSubpaths object,將 localeSubpaths 當作 key,我們要的子路徑當作 value。程式碼如下:
localeSubpaths:{
zhHant:'cn',
fr: 'fr',
es: 'es'
}
然後打開 next.config.js 檔,引入 nextI18NextRewriters並傳入 localeSubpaths,改變配置,程式碼如下:
看看效果如何吧:
有動態的 url 了!
恭喜!我們完成了這個多語系支援的實作,接下來把它應用到自己的專案吧!