如何在 Next.js 中實作國際化
範例
Next.js 自 v10.0.0
起內建支援國際化 (i18n) 路由功能。您可以提供語言環境清單、預設語言環境及網域專屬語言環境,Next.js 會自動處理路由轉換。
目前 i18n 路由功能旨在與現有 i18n 函式庫方案互補,例如 react-intl
、react-i18next
、lingui
、rosetta
、next-intl
、next-translate
、next-multilingual
、tolgee
、paraglide-next
、next-intlayer
等,透過簡化路由與語言環境解析來達成。
開始使用
首先,在您的 next.config.js
檔案中加入 i18n
設定。
語言環境採用 UTS 語言環境識別碼,這是定義語言環境的標準化格式。
通常語言環境識別碼由語言、地區和文字系統組成,以連字號分隔:語言-地區-文字系統
。地區和文字系統為可選項目。例如:
en-US
- 美國使用的英語nl-NL
- 荷蘭使用的荷蘭語nl
- 荷蘭語,未指定特定地區
若使用者語言環境為 nl-BE
但未在設定中列出,系統會將使用者重新導向至 nl
(如果有提供)或預設語言環境。因此,若不打算支援某國家的所有地區,包含國家語言環境作為備用是良好的做法。
語言環境策略
有兩種語言環境處理策略:子路徑路由與網域路由。
子路徑路由
子路徑路由將語言環境置於網址路徑中。
使用上述設定後,en-US
、fr
和 nl-NL
將可供路由使用,且 en-US
為預設語言環境。若有 pages/blog.js
頁面,以下網址將可用:
/blog
/fr/blog
/nl-nl/blog
預設語言環境沒有前綴。
網域路由
透過網域路由,您可以設定不同網域提供不同語言環境:
例如若有 pages/blog.js
頁面,以下網址將可用:
example.com/blog
www.example.com/blog
example.fr/blog
example.nl/blog
example.nl/nl-BE/blog
自動語言環境偵測
當使用者造訪應用程式根目錄(通常是 /
)時,Next.js 會嘗試根據 Accept-Language
標頭與當前網域自動偵測使用者偏好的語言環境。
若偵測到非預設語言環境,使用者將被重新導向至:
- 使用子路徑路由時: 帶有語言環境前綴的路徑
- 使用網域路由時: 指定該語言環境為預設值的網域
使用網域路由時,若帶有 Accept-Language
標頭 fr;q=0.9
的使用者造訪 example.com
,他們將被重新導向至 example.fr
,因為該網域預設處理 fr
語言環境。
使用子路徑路由時,使用者將被重新導向至 /fr
。
為預設語言環境添加前綴
在 Next.js 12 及 中介軟體 (Middleware) 中,我們可以透過 解決方案 為預設語言環境添加前綴。
例如,以下是支援幾種語言的 next.config.js
檔案。請注意,"default"
語言環境是刻意添加的。
接著,我們可以使用 中介軟體 (Middleware) 添加自訂路由規則:
此 中介軟體 (Middleware) 會跳過為 API 路由 和 公開檔案(如字型或圖片)添加預設前綴。若請求是針對預設語言環境,我們會重新導向至前綴 /en
。
停用自動語言環境偵測
可以透過以下方式停用自動語言環境偵測:
當 localeDetection
設為 false
時,Next.js 將不再根據使用者的偏好語言環境自動重新導向,僅提供從語言環境網域或語言環境路徑偵測到的資訊,如上所述。
存取語言環境資訊
您可以透過 Next.js 路由器存取語言環境資訊。例如,使用 useRouter()
鉤子時,以下屬性可供使用:
locale
包含當前使用的語言環境。locales
包含所有設定的語言環境。defaultLocale
包含設定的預設語言環境。
當使用 getStaticProps
或 getServerSideProps
預渲染 (pre-rendering) 頁面時,語言環境資訊會在提供給函式的 上下文 (context) 中提供。
使用 getStaticPaths
時,設定的語言環境會在函式的 locales
參數中提供,而設定的 defaultLocale
則在 defaultLocale
參數中提供。
語言環境間切換
您可以使用 next/link
或 next/router
在語言環境間切換。
對於 next/link
,可以透過 locale
屬性指定要切換至的不同語言環境。若未提供 locale
屬性,在客戶端轉換時會使用當前使用的 locale
。例如:
直接使用 next/router
方法時,可以透過轉換選項指定應使用的 locale
。例如:
請注意,若要僅切換 locale
同時保留所有路由資訊(例如 動態路由 (dynamic route) 查詢值或隱藏的 href 查詢值),可以將 href
參數作為物件提供:
有關 router.push
物件結構的更多資訊,請參閱 此處。
若您的 href
已包含語言環境,可以選擇停用自動處理語言環境前綴:
利用 NEXT_LOCALE
cookie
Next.js 允許設定 NEXT_LOCALE=the-locale
cookie,其優先順序高於 accept-language 標頭。此 cookie 可透過語言切換器設定,當使用者返回網站時,從 /
重新導向至正確語言環境位置時會使用 cookie 中指定的語言環境。
例如,若使用者的 accept-language 標頭偏好 fr
語言環境,但設定了 NEXT_LOCALE=en
cookie,則造訪 /
時使用者將被重新導向至 en
語言環境位置,直到 cookie 被移除或過期。
搜尋引擎優化
由於 Next.js 知道使用者正在造訪的語言,它會自動將 lang
屬性添加到 <html>
標籤。
Next.js 不知道頁面的變體,因此需由您使用 next/head
添加 hreflang
元標籤。您可以在 Google 網站管理員文件 中了解更多關於 hreflang
的資訊。
這如何與靜態生成 (Static Generation) 搭配使用?
請注意,國際化路由不與
output: 'export'
整合,因為它不利用 Next.js 路由層。不使用output: 'export'
的混合式 Next.js 應用程式完全支援。
動態路由與 getStaticProps
頁面
對於使用 getStaticProps
與 動態路由 (Dynamic Routes) 的頁面,所有需要預渲染的語言環境變體都需從 getStaticPaths
返回。除了為 paths
返回的 params
物件外,您還可以返回 locale
欄位指定要渲染的語言環境。例如:
對於 自動靜態優化 (Automatically Statically Optimized) 和非動態 getStaticProps
頁面,會為每個語言環境生成一個頁面版本。這點很重要,因為根據 getStaticProps
中設定的語言環境數量,可能會增加建置時間。
例如,若您設定了 50 個語言環境和 10 個使用 getStaticProps
的非動態頁面,這意味著 getStaticProps
將被呼叫 500 次。每次建置時會生成這 10 個頁面的 50 個版本。
若要減少使用 getStaticProps
的動態頁面建置時間,請使用 fallback
模式。這允許您從 getStaticPaths
僅返回最受歡迎的路徑和語言環境進行建置時預渲染。接著,Next.js 會在請求時於運行時建置其餘頁面。
自動靜態優化頁面
對於 自動靜態優化 (automatically statically optimized) 的頁面,會為每個語言環境生成一個頁面版本。
非動態 getStaticProps 頁面
對於非動態 getStaticProps
頁面,如上所述會為每個語言環境生成一個版本。getStaticProps
會針對正在渲染的每個 locale
被呼叫。若您希望選擇不預渲染某個語言環境,可以從 getStaticProps
返回 notFound: true
,該頁面變體將不會被生成。
i18n 設定的限制
locales
:總共 100 個語言環境domains
:總共 100 個語言環境網域項目
須知:這些限制最初是為了避免可能的 建置時效能問題 而添加的。在 Next.js 12 中,您可以使用 中介軟體 (Middleware) 透過自訂路由解決這些限制。