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

或点击选择文件

目标语言

无需注册即时估价

常见问题