# General Translation Knowledge Base: 如何翻译 JSX 中的条件文本？
URL: https://generaltranslation.com/zh/kb/translate-conditional-jsx.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 保持句子完整，并翻译它的每个版本。三元表达式会把句子拆成碎片，使其失去含义，也无法适应各语言的语序。General Translation 通过在 `<T>` 中使用 `<Branch>` 解决这一问题，将整个句子作为一个整体进行翻译。
Category: 国际化
Last updated: 2026-10-21
Authors: Ernest McCarter
Published: 2025-09-26

要翻译 JSX 中的条件文本 (即由三元表达式或其他条件选择的文案) ，应保持句子完整，并翻译它的每个版本。像 `I eat lunch at {atHome ? 'home' : 'work'}.` 这样的三元表达式会把一个句子拆成碎片。单独翻译时，&quot;home&quot; 和 &quot;work&quot; 脱离了赋予它们含义的句子，而代码仍把它们固定在英文句子的末尾。然而语序因语言而异：中文把地点放在动词之前，例如“我在家吃午餐” (&quot;I eat lunch at home&quot;) 。

| 方案                                                                                                                          | 优势                                                                                                                                           | 仍需你自行处理的部分                                                                                                                                                                                                              |
| --------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 仅使用国际化 (i18n) 库 (`i18next`、`react-intl`、`next-intl`)                                                                        | 每个版本对应一个上下文键 (`i18next`) ，或用一条 ICU (International Components for Unicode) `select` 消息 (`react-intl`、`next-intl`) 容纳句子的所有版本                   | 将句子从 JSX 移到键文件中，并为每种语言写出每个版本                                                                                                                                                                                            |
| Google Translate                                                                                                            | 快速、通用的文本翻译，每次处理一个字符串                                                                                                                         | 把每个版本写成完整句子，将结果放回代码中，并在文案变更时重复这两步                                                                                                                                                                                       |
| 直接调用 AI API (OpenAI API、Claude API)                                                                                         | 只要连同所有版本一起发送，就能流畅地翻译整个句子                                                                                                                     | 收集每个版本及其上下文、在各次发布间保持术语一致、审校，以及将结果加载到应用中                                                                                                                                                                                 |
| General Translation ([`<T>`](/docs/react/reference/components/t) 搭配 [`<Branch>`](/docs/react/reference/components/branch))  | [`<T>`](/docs/react/reference/components/t) 将句子作为一个整体翻译，所有版本都放在同一个 [`<Branch>`](/docs/react/reference/components/branch) 中，每个版本的完整措辞都可以按语言调整 | 用 [`<Branch>`](/docs/react/reference/components/branch) 替换三元表达式 (在 [`<T>`](/docs/react/reference/components/t) 内可通过 ESLint 自动修复完成) 、一次性的初始化设置，以及在文案变更时重新运行 [`npx gt translate`](/docs/cli/reference/commands/translate) |

如果应用只以一种语言发布，用普通三元表达式即可。如果文案已存放在由译者填写的键文件中，可以只用 i18n 库；只需翻译一次的句子，可以用 Google Translate 或直接调用 AI API。如果句子位于 JSX 中，且文案变更后仍需保持翻译同步，请在 [`<T>`](/docs/react/reference/components/t) 中使用 [`<Branch>`](/docs/react/reference/components/branch)。如果措辞取决于数字，请改用 [`<Plural>`](/docs/react/reference/components/plural)，因为各语言的复数规则不同：英语有 2 种形式，阿拉伯语有 6 种。

General Translation 的 `gt-react` 和 `gt-next` 库通过在 [`<T>`](/docs/react/reference/components/t) 中使用 [`<Branch>`](/docs/react/reference/components/branch) 组件来处理条件。将值作为 `branch` 传入 (字符串、数字或布尔值) ，为每个值添加一个属性，并将后备内容放在 `children` 中，没有属性匹配时就渲染它。如果条件影响的语法不止一个词，请在每个分支中放入完整的句子，方便译者调整整句措辞。[`<T>`](/docs/react/reference/components/t) 中的内联三元表达式可以改写为如下的 [`<Branch>`](/docs/react/reference/components/branch)：

```tsx
// 内联条件表达式
<T>{isActive ? 'Active' : 'Inactive'}</T>;

// 可翻译的分支
<T>
  <Branch branch={isActive} true="Active">
    Inactive
  </Branch>
</T>;
```

General Translation 的 ESLint 插件 `@generaltranslation/react-core-linter` 会标记出 [`<T>`](/docs/react/reference/components/t) 中的三元表达式，运行 `npx eslint . --fix` 即可将其自动转换为 [`<Branch>`](/docs/react/reference/components/branch)。之后，[`npx gt translate`](/docs/cli/reference/commands/translate) 会将每个 [`<T>`](/docs/react/reference/components/t) 翻译为 `gt.config.json` 中列出的所有区域设置。完整步骤请参阅[处理复数形式和分支](/docs/react/guides/handling-plurals-and-branches)，各框架的快速入门链接可在 [React 概览](/docs/react/overview#frameworks)中找到。

## Video

The video is narrated in English, with English captions.

[How do I translate conditional text in JSX?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-translate-conditional-jsx.mp4) (46秒)

General Translation lets you wrap whole sentences in `T` and express conditions with `Branch`. Run `npx gt init`, choose Japanese and Chinese and sign in, put the sentence in a `T` component with a `Branch` so the translator sees it whole, then run `npx gt translate` to write Japanese and Chinese with the place before the verb.

## 如何在 React 中翻译包含变量和链接的句子？

要翻译包含变量和链接的句子，请将句子、变量和链接文本放在同一个翻译条目中。这样每种语言都能拿到完整的句子，并按照自身语法把名字和链接放到合适的位置。如果把 `Hi {name}, read the terms of service before you continue.` 拆分成 &quot;Hi&quot;、&quot;read the&quot;、&quot;terms of service&quot; 和 &quot;before you continue&quot;，译者拿到的只是四个脱离上下文的片段，而代码仍会按英语语序拼接它们。

| 方案                                                                                                                    | 句子如何标记链接                                                  | 需要你自行处理的事项                                                                        |
| --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------- |
| 每个片段使用单独的字符串                                                                                                          | 链接文本单独作为一个字符串                                             | 脱离句子上下文、按英语语序排列的片段                                                                |
| react-i18next `<Trans>`                                                                                               | 编号标签，如 `<3>terms of service</3>`，或来自 `components` 属性的命名标签 | 为每种语言编写字符串，并在 JSX 变更时重新为标签编号                                                      |
| react-intl `<FormattedMessage>`                                                                                       | 命名标签，如 `<link>terms of service</link>`，由 `values` 中的函数渲染  | 为每种语言编写消息，并确保标签名与 `values` 保持对应                                                   |
| General Translation ([`<T>`](/docs/react/reference/components/t) 搭配 [`<Var>`](/docs/react/reference/components/var))  | 链接以 JSX 形式直接写在句子中                                         | 一次性初始化设置，并在文案变更时重新运行 [`npx gt translate`](/docs/cli/reference/commands/translate) |

单独的字符串只适用于不属于句子的文本，例如独立的按钮标签。如果文案已经存放在由译者填写的目录文件中，请使用 react-i18next 的 `<Trans>` 或 react-intl 的 `<FormattedMessage>`，并优先使用命名标签，因为周围的 JSX 变化时，命名标签不会随之改变。如果句子写在 JSX 中，并且需要在文案变更后始终保持翻译同步，请使用 General Translation 的 [`<T>`](/docs/react/reference/components/t) 搭配 [`<Var>`](/docs/react/reference/components/var)。

General Translation 的 `gt-react` 和 `gt-next` 库通过 [`<T>`](/docs/react/reference/components/t) 保持句子完整：用 [`<T>`](/docs/react/reference/components/t) 包裹句子，将动态值放入 [`<Var>`](/docs/react/reference/components/var)，并将链接作为普通 JSX 直接写在句子中。

```tsx
import { T, Var } from 'gt-react';

export function TermsNotice({ name }: { name: string }) {
  return (
    <T>
      <p>
        Hi <Var>{name}</Var>, read the <a href="/terms">terms of service</a> before you continue.
      </p>
    </T>
  );
}
```

General Translation 的 [`<T>`](/docs/react/reference/components/t) 会将整个段落 (包括链接文本) 作为一个整体翻译，并原样保留 `<a>` 元素及其 `href`。[`<Var>`](/docs/react/reference/components/var) 会原样渲染 `name`，绝不会将其发送到 General Translation API，并根据各区域设置的句子结构将其放到合适的位置。如果你直接写 `{name}` 而没有使用 [`<Var>`](/docs/react/reference/components/var)，General Translation 的 [`static-jsx`](/docs/react/reference/lint-rules#static-jsx) lint 规则会将其标记出来，运行 `npx eslint . --fix` 即可自动用 [`<Var>`](/docs/react/reference/components/var) 将其包裹。在 Next.js App Router 中，请从 General Translation 的 `gt-next` 导入 [`<T>`](/docs/react/reference/components/t) 和 [`<Var>`](/docs/react/reference/components/var)，并使用 [`gt-next/link` 中的 `Link`](/docs/react/nextjs/link) 编写链接。它会为内部 URL 自动添加区域设置前缀，例如对西班牙语访问者而言，`/terms` 会变为 `/es/terms`。

## react-i18next 的 Trans 与 General Translation 的 T 如何处理嵌套元素？

react-i18next 的 `<Trans>` 组件会为每种语言使用一个字符串来渲染包含 React 元素的句子，该字符串按各元素在 `<Trans>` 子元素中的位置来标记它们。在这个句子中，子元素依次为：名字前的文本、`name` 值、链接前的文本、链接，以及结尾文本。因此，从 0 开始计数，链接是第 3 个子节点：

```tsx
import { Trans } from 'react-i18next';

export function TermsNotice({ name }: { name: string }) {
  return (
    <Trans i18nKey="termsNotice">
      Hi {{ name }}, read the <a href="/terms">terms of service</a> before you continue.
    </Trans>
  );
}
```

```json title="locales/en/translation.json"
{
  "termsNotice": "Hi {{name}}, read the <3>terms of service</3> before you continue."
}
```

嵌套在另一个元素中的元素，会在其父元素的子元素中参与编号。属于一个简短默认列表 (`<br>`、`<strong>`、`<i>` 和 `<p>`) 且不带属性的元素，会在字符串中保留原有名称。`components` 属性用名称代替编号：使用 `components={{ termsLink: <a href="/terms" /> }}` 时，字符串为 `<termsLink>terms of service</termsLink>`。react-intl 的 `<FormattedMessage>` 同样使用名称：消息中包含 `<link>terms of service</link>`，而 `values` 将 `link` 映射到一个返回 `<a>` 元素的函数。

当嵌套元素在 `<Trans>` 中无法正常翻译时，通常是因为字符串与 JSX 不一致。在链接之前添加或删除一个子节点，会使其后的所有编号随之偏移，因此每种语言的字符串都得重新编号。编号指向错误的子节点时，会渲染出错误的内容或丢失链接；而命名标签若未在 `components` 中定义，则会被原样渲染为文本。

使用 General Translation 的 [`<T>`](/docs/react/reference/components/t)，你无需编写翻译字符串，也不必维护编号同步。[`<T>`](/docs/react/reference/components/t) 标签之间的 JSX 就是源内容，General Translation 根据其内容识别条目，并为每个嵌套元素记录其标签以及由 General Translation 分配的内部标识符。在 [`<T>`](/docs/react/reference/components/t) 标签之间编写的任何元素，无论嵌套多深，其中的文本都会与句子的其余部分一起翻译，如 General Translation [`<T>` 参考](/docs/react/reference/components/t#overview)中的这个示例所示：

```tsx
<T>
  Today, I went to
  <p>
    the <b>store</b> to buy some <i>groceries</i>.
  </p>
</T>
```

General Translation 的 [`<T>`](/docs/react/reference/components/t) 只翻译直接写在其标签之间的内容。因此，如果某个子组件 (例如 `<Footer />`) 在内部自行渲染文本，外层的 [`<T>`](/docs/react/reference/components/t) 不会翻译这些文本。应改为将该文本作为子元素传给组件，并避免在一个 [`<T>`](/docs/react/reference/components/t) 内再嵌套另一个。各框架的具体步骤请参阅[翻译 JSX](/docs/react/guides/translating-jsx)。

## Related questions

- [如何在 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 便会生成每种目标语言所需的形式。
- [不使用翻译文件能实现 i18n 吗？](https://generaltranslation.com/zh/kb/i18n-without-translation-files.mdx): 可以。借助 General Translation 的 gt-react 和 gt-next 库，你可以为 React 和 Next.js 实现 i18n，既无需翻译键，也不用为每种语言维护 JSON 文件。文案以内联方式写在 JSX 的 `<T>` 组件中，gt translate 命令会在构建时结合代码中的上下文，为每种语言生成译文。Locadex 还能通过拉取请求让译文保持最新。
- [如何翻译 Flask 或 FastAPI 应用？](https://generaltranslation.com/zh/kb/translate-python-app.mdx): 标记面向用户的字符串，为每个请求确定区域设置（通常依据 Accept-Language），然后加载该区域设置的译文。Flask 应用通常使用 Flask-Babel 搭配 gettext 消息目录，FastAPI 应用则通过中间件接入 Babel。General Translation 的 CLI 可以填充这些消息目录，而其实验性的 gt-flask 和 gt-fastapi SDK 无需消息目录，即可翻译内联的 t() 字符串。

## Previous and next questions

- Previous question: [如何在 React 中处理复数形式？](https://generaltranslation.com/zh/kb/how-to-handle-plurals-in-react.mdx)
- Next question: [如何为多语言 Next.js 应用设置 SEO？](https://generaltranslation.com/zh/kb/multilingual-nextjs-seo.mdx)

## Sitemap

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