翻译 JSX

如何对 JSX 组件进行国际化

概述

本指南将带您了解如何使用 <T> 组件 对 JSX 内容进行国际化。

在本指南结束时,您将了解如何正确使用 <T> 组件的语法以及需要避免的问题。

我们将涵盖以下内容:

如何使用 <T> 组件

其他选项

何时使用 <T> 组件

示例

生产环境注意事项

常见陷阱

如果您想了解如何使用 Variable ComponentsBranching Components,请参考各自的指南。


如何使用 <T> 组件

假设你有一些 HTML 内容需要翻译。

function Greeting() {
  return <p>Hello, world!</p>;
}

你只需要将内容包裹在 <T> 组件中即可。

import { T } from 'gt-react';

function Greeting() {
  return <T><p>Hello, world!</p></T>;
}

根据用户当前选择的语言,这将渲染相应的翻译内容。
更多关于如何让用户切换语言的信息,请参见切换语言


其他选项

上下文

在某些情况下,你可能希望为翻译提供额外的上下文信息。 这可以通过向 <T> 组件传递一个 context 属性来实现。

<T context="toast, as in a pop-up notification">
  Click on the toast to dismiss it.
</T>

当某些单词根据上下文可能有多重含义时,这非常有用。 例如,“toast”既可以指食物,也可以指弹出通知。

context 属性有助于 AI 理解翻译的意图。

id

你也可以向 <T> 组件传递一个 id 属性。 这对于调试很有帮助,并且可以让编辑翻译变得更容易。

<T id="toast">
  Click on the toast to dismiss it.
</T>

何时使用 <T> 组件

虽然 <T> 组件非常灵活,但并不总是最佳解决方案。

当你有任何静态 HTML 或 JSX 内容时,应始终尝试使用 <T> 组件。

何时不应使用 <T> 组件

不要在存在任何不安全的动态内容时使用 <T> 组件。

这里的动态内容指的是任何在运行时可能发生变化的内容。
如果你正在使用 Variable ComponentsBranching Components,此规则不适用。

注意:

Variable components 是一种特殊情况,内容虽然是动态的,但已经被包装并消毒,因此可以安全地使用 <T> 组件。

被 variable components 包裹的内容不会被 <T> 组件直接翻译。

以下示例展示了 <T> 组件的无效用法:

<T>
  <p>Your username is {username}</p>
</T>
<T>
  <p>Current date: {new Date().toLocaleDateString()}</p>
</T>
<T>
  <p>Logical Expressions: {username === 'admin' ? 'Yes' : 'No'}</p>
</T>
<T>
  <p>Conditional Rendering: {isAdmin ? 'Yes' : 'No'}</p>
</T>

在上述示例中,可以通过 variable componentsbranching components 安全地实现国际化。

const chatMessage = getChatMessageFromServer();
<T>
  <p>{chatMessage}</p>
</T>

在此示例中,内容是完全动态的,因此应在服务器端进行翻译后再传递给客户端。

有关如何通过我们的 API 动态翻译内容的更多信息,请参阅 core 库。


示例

以下是如何使用 <T> 组件的一些示例。这些都是正确的用法。

  1. HTML 内容
<T>
  <p>Hello, world!</p>
</T>
<p>Hello, world!</p>
  1. 简单 JSX 内容
<T>
  <Button>Click me!</Button>
</T>
<Button>Click me!</Button>
  1. 复杂 JSX 内容
<T>
  <Tooltip>
    <TooltipTrigger>
      <div className="flex items-center gap-2 rounded-full bg-destructive px-3 py-1.5 text-sm text-destructive-foreground">
        <AlertCircle className="h-4 w-4" />
        <span>Free Usage</span>
      </div>
    </TooltipTrigger>
    <TooltipContent>
      <p>
        You are nearing your free monthly limit. Please
        upgrade your plan to avoid any disruptions to your
        service.
      </p>
    </TooltipContent>
  </Tooltip>
</T>
<Tooltip>
  <TooltipTrigger>
    <div className="flex items-center gap-2 rounded-full bg-destructive px-3 py-1.5 text-sm text-destructive-foreground">
      <AlertCircle className="h-4 w-4" />
      <span>Free Usage</span>
    </div>
  </TooltipTrigger>
  <TooltipContent>
    <p>
      You are nearing your free monthly limit. Please
      upgrade your plan to avoid any disruptions to your
      service.
    </p>
  </TooltipContent>
</Tooltip>

<T> 组件可以在同一个组件中处理任何嵌套内容。


生产环境注意事项

部署到生产环境

在部署到生产环境之前,请确保运行 translate 命令,以便所有翻译内容在运行时都可用。 我们建议将其添加到您的 CD 流水线或作为构建脚本的一部分。

package.json
{
  "scripts": {
    "build": "npx gtx-cli translate && <YOUR_BUILD_COMMAND>",
  }
}

如需更详细的应用部署指南,请参阅 Deployment 教程。 有关该命令的更多信息,请参阅 CLI Tool 参考指南。

行为:开发环境与生产环境

在开发环境中,<T> 组件会按需翻译内容。 这意味着当组件被渲染时,会立即执行翻译操作。 该库这样设计是为了方便多语言开发。

要启用此行为,只需在环境中添加 Dev API 密钥。

在生产环境中,<T> 组件使用的所有翻译内容都会在构建时完成。 这意味着您必须在部署应用之前运行翻译命令。

提示: 如果您想在开发环境中模拟生产环境的行为,只需在开发构建中使用生产 API 密钥即可。

隐私问题

除少数例外,所有包裹在 <T> 组件中的内容都会被发送到 General Translation API 进行翻译。 对于渲染敏感数据(如用户名、账号等),这可能并不理想。

为避免此问题,请使用 Variable Components 来处理私密信息。 这样可以确保不会将任何敏感数据发送到 General Translation API 进行翻译。 任何包裹在变量组件中的内容的本地化都将在本地完成。


常见陷阱

仅限直接子元素

<T> 组件只会翻译直接作为子元素传递的文本。 这意味着,如果你在一个组件内部有内容,但这些内容没有直接传递给 <T>,它们将不会被翻译。

让我们用一个例子来说明:

function UntranslatedContent() {
  return (
    <p>This content is not translated</p>
  );
}

export default function DisplayGreetings() {
  return (
    <T>
      <h1>Hello, this text will be translated</h1>
      <UntranslatedContent />
    </T>
  );
}

在这个例子中,<UntranslatedContent> 内部的内容不会被翻译。 只有直接在 <T> 内部的内容会被翻译,比如 <h1> 标签及其子元素。

注意: 一个简单的经验法则是,任何字面上位于文件中两个 <T> 标签之间的内容都会被翻译。 你始终可以再添加一个 <T> 来翻译未被翻译的内容,尽管不推荐嵌套 <T> 组件。

如何修复?

直接将文本包裹在 <T> 组件中,如下所示:

function TranslatedContent() {
  return (
    <T>
      <p>This content <b>IS</b> translated</p>
    </T>
  );
}

export default function DisplayGreetings() {
  return (
    <>
      <T>
        <h1>Hello, this text will be translated</h1>
      </T>
      <TranslatedContent />
    </>
  );
}

嵌套 <T> 组件

不允许嵌套 <T> 组件。 由于 React 的渲染机制,这样做可能会导致意外行为和性能问题。

下面是不要这样做的例子:

function SomeComponent() {
  return (
    <T>
      Hello, friend!
    </T>
  );
}

export default function NestedTranslation() {
  return (
    <T>
      <T> {/* 不要这样做! */} 
        Hello, world! 
      </T>
      <SomeComponent /> {/* 这也算嵌套。不要这样做! */}
    </T>
  );
}

这里的解决方法是移除最外层的 <T> 组件。

翻译动态内容

如果你尝试用 <T> 组件包裹动态内容,CLI 工具会报错。

例如,下面的写法会报错:

const username = 'John Doe';
<T>
  <p>Your username is {username}</p>
</T>

要解决这个问题,请尝试使用 Variable ComponentsBranching Components 来包裹动态内容。


摘要

  • <T> 组件用于对任意 JSX 内容进行国际化。
  • <T> 组件不应在没有使用变量组件或分支组件的情况下用于动态内容。
  • 在开发环境中,<T> 组件会按需翻译内容。
  • 在生产环境中,<T> 组件使用的所有翻译都会在构建时完成。

后续步骤

这份指南怎么样?