在前兩篇文章中,我們已經學會了 i18next 基礎設定與 URL 同步。但你有沒有想過,如果你的網站支援 10 國語言,每個語言有 5 個 Namespace(如:navbar, footer, home, product, admin...),使用者進入首頁時,真的需要一次下載完所有國家的翻譯嗎?
今天這篇文章要分享如何透過 Dynamic Loading,讓翻譯檔變成「非同步載入」,有效縮減 JS 打包體積、加快網頁載入速度!
如果你還沒看過第一篇,建議先閱讀! 【React i18n 實戰 1】專案中實現多語系功能
為何需要動態載入?
當我們的網站規模增加,翻譯檔的數量也會越來越大,但並非所有內容都需要立刻載入拿出來用,一次載入其實並非好事,動態載入的優點大概可以分為以下三個:
- 減少 Bundle Size:避免把所有 JSON 內容都打包進
main.js。 - 按需讀取:使用者選中文,瀏覽器就只抓中文包;進入首頁,就只抓首頁需要的文字。
- 維護方便:新增語言時,只需在資料夾丟入新 JSON,不必改動
i18n.js的import程式碼。
實作步驟
1. 安裝套件
我們需要一個能處理 HTTP 請求的插件:
npm install i18next-http-backend
2. 移動翻譯檔案位置(重要!)
原本我們的 JSON 放在 src/locales,但因為現在要讓瀏覽器透過 URL 去抓檔案,必須把翻譯檔移到 public 資料夾下:
(因為 vite 會把 src/ 下的檔案打包進 JS bundle,原本在 src/locales 下的內容是抓不到的)
public/
└── locales/
├── en/
│ ├── translation.json
│ └── navbar.json
└── zh/
├── translation.json
└── navbar.json
3. 重新設定 i18n.js
現在我們不需要手動 import 任何 JSON 了,改由 Backend 來處理:
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend"; // 引入 Backend
import LanguageDetector from "i18next-browser-languagedetector";
i18n
.use(Backend) // 使用插件
.use(LanguageDetector)
.use(initReactI18next)
.init({
// 設定翻譯檔的抓取路徑
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json",
},
fallbackLng: "en",
// 定義有用到的 Namespace
ns: ["translation", "navbar"],
defaultNS: "translation",
interpolation: {
escapeValue: false,
},
});
export default i18n;
4. 使用 React Suspense 處理載入狀態
由於翻譯檔現在是透過網路「非同步」載入,當 React 渲染元件但翻譯還沒被抓到時,程式會暫停渲染,必須用 Suspense 來包住應用程式,否則會報錯。
// main.jsx 或 App.jsx
import React, { Suspense } from "react";
import "./i18n";
function App() {
return (
// 當語言包還在下載時,顯示 fallback 的內容
<Suspense fallback={<div>Loading Translations...</div>}>
<Header />
<Home />
</Suspense>
);
}
指定 Namespace 載入
在元件中,可以指定只載入當前元件需要的翻譯,可以更進一步優化效能:
// 只會觸發 navbar.json 的載入
const { t } = useTranslation(["navbar"]);
return <nav>{t("nav_title")}</nav>;
總結
這三篇文章我們從最基礎的 i18next 設定,到 URL 路由同步,最後完成了 動態載入優化。
實作完動態載入後,打開瀏覽器的 DevTools 的 Network ,在切換語言時可以發現瀏覽器發送了新的 XHR 請求去抓取 .json 檔。這代表網站已經具備了「按需讀取」的專業規格~
希望這系列的文章能幫你在面試或實際開發中更加從從容容游刃有餘。如果你有任何關於多語系實作的坑,或是更讚的方法,也歡迎留言討論~
















