設定完 Server Component 接著是 Client Component
安裝套件幫助找出使用者的預設語系。
pnpm add -D i18next-browser-languagedetector
升級 i18n/client 設定
// src/i18n/client
'use client';
import i18next from 'i18next';
import {
initReactI18next,
useTranslation as useTranslationOrg,
} from 'react-i18next';
import resourcesToBackend from 'i18next-resources-to-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { getOptions, locales, cookieName } from './settings';
const runsOnServerSide = typeof window === 'undefined';
i18next
.use(initReactI18next)
.use(LanguageDetector)
.use(
resourcesToBackend(
(language: string, namespace: string) =>
import(`./locales/${language}/${namespace}.json`),
),
)
.init({
...getOptions(),
lng: undefined,
preload: runsOnServerSide ? locales : [],
detection: {
order: ['path', 'cookie', 'htmlTag', 'navigator'],
lookupCookie: cookieName,
lookupFromPathIndex: 0,
},
});
export function useTranslation(
lng: string,
ns?: string | string[],
options = {} as { keyPrefix?: string },
) {
const translation = useTranslationOrg(ns, options);
if (runsOnServerSide && lng && translation.i18n.resolvedLanguage !== lng) {
translation.i18n.changeLanguage(lng);
}
return translation;
}
首先是利用 i18next-browser-languagedetector
的 LanguageDetector
來簡化確認使用者預設語系的步驟,指定從 path
開始確認是否語系設定,再來檢查指定 cookie 的設定。
然後因為若將 page 整個作為 Client Component ,Next 為了載入優化的關係還是會先跑一遍 Client Component 的 SSR ,這時候如果因為 LanguageDetector
的關係導致在 Server 端跟 Client 端的語系不同產生內容差異,就會報錯。
所以要在 Server 端多加一步跟前端語系同步動的動作。
if (runsOnServerSide && lng && translation.i18n.resolvedLanguage !== lng) {
translation.i18n.changeLanguage(lng);
}
這樣就能跟 Server Component 一樣偵測預設語系跟記憶語系了,另外關於不支援語系等的例外狀況Client Component 一樣是會經過 middleware 處理。