# General Translation Knowledge Base: 如何从 react-i18next 迁移到 gt-react？
URL: https://generaltranslation.com/zh/kb/migrate-from-react-i18next.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 在 react-i18next 旁安装 gt-react，共用同一个区域设置 cookie，然后逐个组件地将 t() 键和 `<Trans>` 替换为写在 `<T>` 和 useGT 中的内联文案。General Translation 会以 JSX 作为上下文翻译迁移后的文案，你的团队可以在仪表板中修正译文。尚未迁移的组件将继续使用已审校的 react-i18next 译文。
Category: 国际化
Last updated: 2026-11-11
Authors: Kevin Wu
Published: 2026-11-11

react-i18next 渲染的是你按语言和命名空间写入各个 JSON 文件的译文。gt-react 则渲染直接内联在组件中的文案，并由 General Translation 通过 [`npx gt translate`](/docs/cli/reference/commands/translate) 生成译文。迁移时，两个库可以并行运行，你只需逐个组件地将每个 `t('key')` 查找替换为它所指向的源文本。

使用 General Translation 并不一定要迁移。`gt` CLI 会检测 `package.json` 中的 `i18next`，并在保留 i18next `{{variable}}` 语法的前提下翻译其 JSON 文件。如果你希望文案紧挨着渲染它的 JSX，不必再为键命名，也不必手动保持各语言文件同步，就可以考虑迁移。

## react-i18next 的 API 如何对应到 gt-react？

| react-i18next                                  | gt-react                                                                                                                                                                                         |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `i18n.init({ lng, supportedLngs, resources })` | `gt.config.json` (`defaultLocale`、`locales`) ，以及入口文件中的 [`initializeGTSPA`](/docs/react/reference/config#initialize-spa)                                                                          |
| `I18nextProvider` / `initReactI18next`         | 单页应用 (SPA) 中无需提供者；服务器端渲染的应用使用 [`initializeGT`](/docs/react/reference/config#initialize) 搭配 [`GTProvider`](/docs/react/reference/components/gt-provider)                                          |
| `<Trans i18nKey="..." components={...}>`       | 用 [`<T>`](/docs/react/reference/components/t) 直接包裹实际的 JSX，链接和标记以内联方式编写                                                                                                                           |
| 用于字符串的 `t('key')`                              | 使用 [`useGT`](/docs/react/reference/hooks/use-gt) 并直接传入源字符串，或使用 [`useTranslations`](/docs/react/reference/hooks/use-translations) 继续沿用键                                                           |
| `{{name}}` 插值                                  | JSX 中使用 [`<Var>`](/docs/react/reference/components/var)；字符串中使用 `{name}`                                                                                                                          |
| 带 `count` 的 `key_one` / `key_other`            | JSX 中使用 [`<Plural>`](/docs/react/reference/components/plural)；字符串中使用 ICU `{n, plural, ...}`                                                                                                      |
| `useTranslation('ns')` 或 `keyPrefix`           | `useTranslations('ns')` 将查找范围限定在指定前缀下                                                                                                                                                            |
| `{{val, number}}` 及其他格式化器                      | [`<Num>`](/docs/react/reference/components/num)、[`<Currency>`](/docs/react/reference/components/currency) 和 [`<DateTime>`](/docs/react/reference/components/datetime)                            |
| `i18n.changeLanguage()` / `i18n.language`      | [`useSetLocale`](/docs/react/reference/hooks/use-set-locale) / [`useLocale`](/docs/react/reference/hooks/use-locale)，或 [`<LocaleSelector>`](/docs/react/reference/components/locale-selector) 组件 |
| `i18next-browser-languagedetector`             | 内置支持：优先读取 `generaltranslation.locale` cookie，其次使用浏览器的语言设置                                                                                                                                        |
| `fallbackLng`                                  | 缺少译文时直接渲染源文本                                                                                                                                                                                     |

## 第 1 步：在保留 react-i18next 的同时安装 gt-react

如果是 Vite 或 webpack 应用，请参考 [React SPA 快速入门](/docs/react/react-spa-quickstart)；如果是服务器端渲染的应用，请参考 [React 快速入门](/docs/react/react-quickstart)。在 SPA 中，初始化设置步骤如下：

1. 安装 `gt-react`，并将 `gt` CLI 安装为开发依赖。
2. 创建 `gt.config.json`，并使用与 i18next 配置相同的源区域设置和目标区域设置。
3. 添加一个 [`loadTranslations`](/docs/react/reference/functions/load-translations) 函数，并在入口文件中调用 [`initializeGTSPA`](/docs/react/reference/config#initialize-spa)；该入口文件须等译文加载完成后，再导入应用的其余部分。
4. 运行 [`npx gt login`](/docs/cli/reference/commands/login) 登录，并设置你的项目 ID。

`i18n.init` 和现有的 JSON 文件原地保留即可。在你迁移组件之前，用户不会察觉到任何变化。如果 `gt.config.json` 的 `files` 中列出了你的 i18next 文件，请删除该条目，确保每个字符串只由一方负责翻译：未迁移的组件继续使用 JSON 中的译文，新增或修改的文案则以内联方式写在 gt-react 中。

## 第 2 步：统一当前区域设置

两个库对用户语言的判断可能不一致。请使用 gt-react 作为语言切换器，并让 i18next 读取同一个 cookie：

```ts title="src/i18n.ts"
import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    // ...现有的其他选项
    detection: {
      order: ['cookie', 'navigator'],
      lookupCookie: 'generaltranslation.locale', // gt-react 写入的 cookie
      caches: [],
    },
  });
```

将旧的语言菜单替换为 gt-react 的 [`<LocaleSelector>`](/docs/react/reference/components/locale-selector)，或替换为调用 [`useSetLocale`](/docs/react/reference/hooks/use-set-locale) 的控件。在 SPA 中，切换语言时会写入 cookie 并重新加载页面，这样两个库都会以新语言启动。继续下一步之前，请先测试已迁移页面与未迁移页面之间的跳转。

## 第 3 步：逐个迁移组件

将 JSON 中的 source-language 文本复制到组件中，变量仍保持为变量。迁移前：

```json title="public/locales/en/translation.json"
{
  "inbox": "Hi {{name}}, <link>open your inbox</link>.",
  "messages_one": "You have {{count}} message",
  "messages_other": "You have {{count}} messages"
}
```

```tsx title="src/Inbox.tsx"
import { Trans, useTranslation } from 'react-i18next';

export function Inbox({ name, count }: { name: string; count: number }) {
  const { t } = useTranslation();
  return (
    <>
      <Trans i18nKey="inbox" values={{ name }} components={{ link: <a href="/inbox" /> }} />
      <p>{t('messages', { count })}</p>
    </>
  );
}
```

修改后：

```tsx title="src/Inbox.tsx"
import { T, Var, Plural, Num } from 'gt-react';

export function Inbox({ name, count }: { name: string; count: number }) {
  return (
    <T>
      Hi <Var>{name}</Var>, <a href="/inbox">open your inbox</a>.
      <p>
        <Plural
          n={count}
          singular={<>You have <Num>{count}</Num> message</>}
          plural={<>You have <Num>{count}</Num> messages</>}
        />
      </p>
    </T>
  );
}
```

链接仍是真正的 `<a>` 元素，不会变成编号占位符。General Translation 会把整段内容连同其结构作为上下文一起翻译，并根据你编写的 `singular` 和 `plural` 生成各目标语言所需的形式，例如波兰语的 `few` 和 `many` 形式。之后，[`<Plural>`](/docs/react/reference/components/plural) 会根据每个数量选出正确的形式。

对于 JSX 之外的字符串 (例如占位符和 toast 提示) ，请使用 [`useGT`](/docs/react/reference/hooks/use-gt)。变量使用单花括号，对于有歧义的词，你还可以添加上下文：

```tsx
import { useGT } from 'gt-react';

function Search({ count }: { count: number }) {
  const gt = useGT();
  return <input placeholder={gt('Search {count} projects', { count })} />;
}

// 在事件处理函数中使用，并为译者提供提示：
toast(gt('Saved {fileName}', { fileName, $context: 'toast after saving a file' }));
```

第一个参数必须是静态字符串，不能是模板字面量或字符串拼接。每处理完一批组件，就运行 [`npx gt translate`](/docs/cli/reference/commands/translate)，并逐一检查每个区域设置。

## 能否保留现有的翻译键？

可以。将你的键全部迁移到同一个 gt-react [字典](/docs/react/guides/translating-with-dictionaries)中，并把 `useTranslation` 替换为 [`useTranslations`](/docs/react/reference/hooks/use-translations)。查找调用的写法无需改动：

```tsx
// 迁移前
import { useTranslation } from 'react-i18next';
const { t } = useTranslation();

// 迁移后
import { useTranslations } from 'gt-react';
const t = useTranslations();

return <h1>{t('home.welcome', { name })}</h1>;
```

词典条目使用 ICU MessageFormat，因此 JSON 需要做三处修改：

* `{{name}}` 改为 `{name}`。
* 复数键合并为一个条目：`"messages": "You have {count, plural, one {# message} other {# messages}}"`。
* 各命名空间文件合并为一个 `dictionary.json`，每个命名空间作为一个顶级键。`useTranslation('settings')` 改为 `useTranslations('settings')`。

[`npx gt validate`](/docs/cli/reference/commands/validate) 会对不符合 ICU 语法的条目发出警告。i18next 在条目缺失时会返回键，而 [`useTranslations`](/docs/react/reference/hooks/use-translations) 则会抛出异常，因此请确保 id 与条目保持同步。

## 现有译文会怎样？

尚未迁移的组件会继续渲染已审校的 react-i18next 译文，因此分阶段迁移只会影响你改动过的页面。迁移到 [`<T>`](/docs/react/reference/components/t)、[`useGT`](/docs/react/reference/hooks/use-gt) 或 gt-react 字典中的文案，会由 [`npx gt translate`](/docs/cli/reference/commands/translate) 生成新的译文，生成时会参考 [`<T>`](/docs/react/reference/components/t) 的 JSX 结构以及你添加的上下文。借助[上下文分组](/docs/platform/dashboard/guides/defining-context-for-translations)中的词汇表和自定义提示词，可以保持术语和语气的一致。之后，审校人员还可以在[仪表板](/docs/platform/dashboard/guides/reviewing-translations)中修正任何措辞。

如果所有已审校的译文都必须原样保留，请继续使用 react-i18next，改由 General Translation 翻译其 JSON 文件。 (参见 [General Translation 与 i18next 对比](/kb/general-translation-vs-i18next)。)

## 第 4 步：移除 react-i18next

如果在代码中搜索 `useTranslation`、`<Trans` 和 `i18next` 都已找不到任何结果，就可以删除 `i18n.init` 文件、JSON 文件和语言检测器，并移除 `i18next` 与 `react-i18next` 依赖项。然后将 [`npx gt translate`](/docs/cli/reference/commands/translate) 加入你的构建流程或 [CI](/kb/translations-in-ci)，确保每次发布时新增文案都已翻译完毕。

## 常见问题

### 必须一次性全部迁移吗？

不必。只要两个库读取的是同一个区域设置，就可以在同一页面上同时渲染。你可以逐个路由或功能进行迁移，等 i18next 的最后一处使用被移除后，再将其移除。

### gt-react 是否支持服务器端渲染？

支持。服务端渲染的 React 应用应搭配使用 [`initializeGT`](/docs/react/reference/config#initialize) 和 [`GTProvider`](/docs/react/reference/components/gt-provider)，而非 [`initializeGTSPA`](/docs/react/reference/config#initialize-spa)。请参阅 [React 快速入门](/docs/react/react-quickstart)；如果你使用的是 `gt-next`，请参阅 [Next.js 快速入门](/docs/react/nextjs-quickstart)。

### gt-react 是免费的吗？

gt-react 采用 MIT 许可证，无需注册账户即可渲染随应用打包的译文。使用 General Translation 生成译文则[按用量计费](https://generaltranslation.com/pricing)。

## 要点总结

* 让 gt-react 与 react-i18next 并行运行，将 i18next 的语言检测器指向 `generaltranslation.locale` cookie，并通过 gt-react 切换语言。
* 将 `<Trans>` 和键查找替换为写在 [`<T>`](/docs/react/reference/components/t) 和 [`useGT`](/docs/react/reference/hooks/use-gt) 中的内联文案；`{{var}}` 改为 [`<Var>`](/docs/react/reference/components/var) 或 `{var}`，复数键改为带 `singular` 和 `plural` 的 [`<Plural>`](/docs/react/reference/components/plural)。
* 未迁移的组件会保留已审校的译文；已迁移的文案会以其所在的 JSX 作为上下文进行翻译，并可在仪表板中审校。
* 如需保留键，请将 JSON 转换为单个 ICU 字典，并使用 [`useTranslations`](/docs/react/reference/hooks/use-translations)。
* 确认没有任何代码再读取 i18next 后再将其移除，然后在 CI 中运行 [`npx gt translate`](/docs/cli/reference/commands/translate)。

## Related questions

- [i18next 替代方案：General Translation 与 i18next 对比](https://generaltranslation.com/zh/kb/general-translation-vs-i18next.mdx): 如果你希望将文案内联在 React 组件中，并借助其 JSX 结构和产品上下文生成译文，请选择 General Translation。你也可以继续使用 i18next，并用 General Translation 翻译现有的消息目录。i18next 负责消息渲染和复数形式选择，译文则需要由单独的服务生成。
- [如何翻译 React 应用？](https://generaltranslation.com/zh/kb/translate-react-app.mdx): 翻译 React 应用，需要先对组件进行国际化，使其以用户的语言渲染，再将每个字符串翻译成你支持的各种语言。General Translation 的 gt-react 在 `<T>` 组件中原地翻译 JSX，npx gt translate 则会为每种语言生成一个文件。
- [如何翻译 JSX 之外的字符串？](https://generaltranslation.com/zh/kb/translate-strings-outside-jsx.mdx): 对于每个不属于 JSX 子节点的字符串（例如占位符或模块作用域常量），应在其渲染的位置通过翻译函数处理。General Translation 的 useGT 钩子会返回该函数，而 msg 搭配 useMessages 可以翻译在组件外部定义的常量。
- [如何在 React 中处理复数形式？](https://generaltranslation.com/zh/kb/how-to-handle-plurals-in-react.mdx): 在 React 中处理复数形式时，应为每种语言的每个复数形式各准备一个句子，并按该语言的复数规则选出对应句子——英语有 2 种形式，俄语有 4 种，阿拉伯语有 6 种。gt-react 和 gt-next 提供的 General Translation `<Plural>` 组件只需接收你的源语言形式，General Translation 便会生成每种目标语言所需的形式。
- [如何在每次部署时保持译文同步更新？](https://generaltranslation.com/zh/kb/translations-in-ci.mdx): 在每次生产环境构建之前，将翻译作为流水线中的一个步骤运行，这样新增文案就会在引入它的那次部署中以翻译好的形式一同上线。General Translation 的 gt CLI 通过 npx gt translate 实现这一点，所需的项目 API 密钥和项目 ID 以 CI 密钥的形式存储。

## Previous and next questions

- Previous question: [如何从 next-intl 迁移到 gt-next？](https://generaltranslation.com/zh/kb/migrate-from-next-intl.mdx)
- Next question: [如何从 vue-i18n 迁移到 gt-vue？](https://generaltranslation.com/zh/kb/migrate-from-vue-i18n.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/zh/kb/sitemap.md) for every article.
