Skip to main content

React 國際化完整指南

從零到多語言:在 React 應用程式中設定 i18n,再利用 AI 自動翻譯。

1

安裝套件

你需要三個套件:react-i18next(React 綁定)、i18next(核心庫),以及用於自動檢測語言的可選套件 i18next-browser-languagedetector。

react-i18next 提供 React hook 和元件;i18next 是負責載入譯文、插值和複數處理的核心引擎;語言檢測外掛程式則會自動讀取瀏覽器的語言偏好。
Terminal
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
2

設定 i18n 實例

建立 i18n 設定檔案,使用預設語言、翻譯資源和外掛程式鏈初始化 i18next。必須在任何元件渲染前,於應用程式入口點匯入此檔案。

src/i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)  // Must come before .init()
  .init({
    fallbackLng: 'en',
    debug: process.env.NODE_ENV === 'development',
    interpolation: {
      escapeValue: false,  // React already escapes
    },
    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json',
    },
  });

export default i18n;
"You will need to pass in an i18next instance by using initReactI18next"——此錯誤表示你忘記在 i18n.init() 前呼叫 i18n.use(initReactI18next)。.use() 呼叫必須位於 .init() 之前。
3

使用 I18nextProvider 包裝應用程式

在應用程式根目錄匯入 i18n 設定檔案,並使用 I18nextProvider 包裝元件樹。否則,useTranslation() 會傳回原始鍵而非譯文。

src/main.tsx
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';  // Import your config
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <Suspense fallback={<div>Loading...</div>}>
      <I18nextProvider i18n={i18n}>
        <App />
      </I18nextProvider>
    </Suspense>
  </React.StrictMode>
);
如果顯示的是 "welcome" 等原始鍵,而不是 「Welcome to our app」,最常見的原因是缺少 I18nextProvider 或未匯入 i18n 設定檔案。
4

建立翻譯檔案

為每種語言建立一個 JSON 檔案。使用嵌套鍵按功能或頁面組織字串,並將來源語言(通常是英語)作為單一可信源。

public/locales/en/translation.json
// public/locales/en/translation.json
{
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "greeting": "Hello, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} item",
    "itemCount_other": "{{count}} items"
  }
}

// public/locales/de/translation.json
{
  "nav": {
    "home": "Startseite",
    "about": "Über uns",
    "settings": "Einstellungen"
  },
  "greeting": "Hallo, {{name}}!",
  "cart": {
    "itemCount_one": "{{count}} Artikel",
    "itemCount_other": "{{count}} Artikel"
  }
}
按鍵所描述的內容而非顯示位置命名:"cart.itemCount" 優於 "homepageCartLabel"。即使重新設計 UI,鍵也應繼續有效。
5

在元件中使用譯文

在任何元件中呼叫 useTranslation() 取得 t() 函數。它可用於簡單字串、插值變數,以及通過 Trans 元件嵌入 JSX 的譯文。

Greeting.tsx
import { useTranslation } from 'react-i18next';

function Greeting({ userName }: { userName: string }) {
  const { t } = useTranslation();

  return (
    <div>
      <h1>{t('greeting', { name: userName })}</h1>
      <nav>
        <a href="/">{t('nav.home')}</a>
        <a href="/about">{t('nav.about')}</a>
      </nav>
    </div>
  );
}
Trans component for JSX
import { Trans, useTranslation } from 'react-i18next';

// For JSX inside translations:
// "terms": "By signing up, you agree to our <link>Terms</link>."

function SignUp() {
  const { t } = useTranslation();
  return (
    <Trans i18nKey="terms" components={{
      link: <a href="/terms" className="underline" />
    }} />
  );
}
像 t(`error.$'{code}'`) 這樣的動態鍵可在執行階段使用,但 i18next-scanner 等工具無法靜態提取。如果使用提取工具,請明確列出動態鍵或新增註解提示。
6

處理複數和變數

i18next 按 CLDR 規則而非簡單的單數/複數處理。阿拉伯語有 6 種形式(zero、one、two、few、many、other),日語只有 1 種(other)。請在翻譯檔案中定義所有必需形式,i18next 會自動選擇正確形式。

Plural forms by language
// English: 2 forms (one, other)
{
  "itemCount_one": "{{count}} item",
  "itemCount_other": "{{count}} items"
}

// Arabic: 6 forms (zero, one, two, few, many, other)
{
  "itemCount_zero": "لا عناصر",
  "itemCount_one": "عنصر واحد",
  "itemCount_two": "عنصران",
  "itemCount_few": "{{count}} عناصر",
  "itemCount_many": "{{count}} عنصرًا",
  "itemCount_other": "{{count}} عنصر"
}

// Japanese: 1 form (other)
{
  "itemCount_other": "{{count}}個のアイテム"
}
切勿硬編碼 count === 1 來檢測單數。法語會把 0 視為單數,俄語、阿拉伯語和波蘭語還有英語中不存在的形式。應讓 i18next 處理複數規則。
7

新增語言切換與檢測

構建呼叫 i18n.changeLanguage() 的語言選擇器,並結合瀏覽器語言檢測器,在首次訪問時自動檢測用戶的首選語言,隨後儲存用戶的明確選擇。

LanguageSwitcher.tsx
import { useTranslation } from 'react-i18next';

const LANGUAGES = [
  { code: 'en', label: 'English' },
  { code: 'de', label: 'Deutsch' },
  { code: 'ja', label: '日本語' },
  { code: 'es', label: 'Español' },
];

function LanguageSwitcher() {
  const { i18n } = useTranslation();

  return (
    <select
      value={i18n.language}
      onChange={(e) => i18n.changeLanguage(e.target.value)}
    >
      {LANGUAGES.map(({ code, label }) => (
        <option key={code} value={code}>{label}</option>
      ))}
    </select>
  );
}
使用 SSR(Next.js、Remix)時,伺服器檢測到的語言可能與客戶端不同,因為伺服器沒有瀏覽器偏好。這會導致水合不匹配。解決方法:通過屬性或 Cookie 將伺服器檢測到的語言傳給客戶端,讓雙方渲染相同語言。
8

自動翻譯

完成 i18n 設定後,使用 AI 翻譯本地化檔案。在 IDE 中讓 AI 助手翻譯來源檔案,或在 CI/CD 管線中使用 i18n Agent CLI。

Terminal
# In your IDE, ask your AI assistant:
> Translate public/locales/en/translation.json to German, Japanese, and Spanish

✓ de/translation.json created (1.2s)
✓ ja/translation.json created (1.5s)
✓ es/translation.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate public/locales/en/translation.json --lang de,ja,es
採用增量翻譯:向來源檔案新增新鍵時,只翻譯差異,不要重新產生所有檔案。這樣可以保留經人工審核的譯文。

自動保證翻譯質素

使用 i18n-validate 在發佈前發現缺失鍵和損壞的預留位置。真實譯文完成前,可使用 i18n-pseudo 產生偽譯文來測試 UI。

常見問題

譯文顯示原始鍵

可能原因:缺少 I18nextProvider、應用程式根目錄未匯入 i18n 設定、命名空間未載入,或譯文仍在非同步載入。請在瀏覽器控制台中使用 debug: true 查找線索。

缺少回退時發生 Suspense 錯誤

「A component suspended while responding to synchronous input」——請在應用程式外新增 '&lt;Suspense&gt;' 邊界,或在 i18next 的 init 設定中設定 useSuspense: false。

SSR 水合不匹配

伺服器以一種語言渲染,客戶端卻以另一種語言水合。請確保雙方使用同一語言來源:從伺服器以屬性傳入,不要只依賴瀏覽器檢測。

翻譯鍵沒有自動補全

使用資源類型擴展 i18next 模組:declare module 'i18next' '{ interface CustomTypeOptions { resources: typeof resources } }'。這樣呼叫 t() 時就能獲得類型安全的自動補全。

推薦的檔案結構

Project Structure
my-react-app/
├── public/
│   └── locales/
│       ├── en/
│       │   ├── translation.json    # Default namespace
│       │   ├── common.json         # Shared strings
│       │   └── dashboard.json      # Feature namespace
│       ├── de/
│       │   ├── translation.json
│       │   ├── common.json
│       │   └── dashboard.json
│       └── ja/
│           └── ...
├── src/
│   ├── i18n.ts                     # i18n configuration
│   ├── main.tsx                    # App entry with Provider
│   ├── App.tsx
│   └── components/
│       └── LanguageSwitcher.tsx
└── package.json

立即試用 i18n Agent

將翻譯檔案拖放到此處

JSON, YAML, PO, XML, CSV, Markdown, Properties

或點擊選擇檔案

目標語言

無需註冊即時估價

常見問題