# General Translation Knowledge Base: 如何翻译 JSX 之外的字符串？
URL: https://generaltranslation.com/zh/kb/translate-strings-outside-jsx.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 对于每个不属于 JSX 子节点的字符串（例如占位符或模块作用域常量），应在其渲染的位置通过翻译函数处理。General Translation 的 useGT 钩子会返回该函数，而 msg 搭配 useMessages 可以翻译在组件外部定义的常量。
Category: 国际化
Last updated: 2026-10-21
Authors: Kevin Liu, Kevin Wu
Published: 2026-10-21

JSX 之外的字符串是指不属于 JSX 子节点的文本，因此无法用翻译组件包裹，包括 `placeholder` 和 `aria-label` 等属性值、在代码中拼接的字符串，以及在模块作用域中定义的常量。这些字符串都需要交给钩子提供的翻译函数处理 (例如 `react-i18next` 中的 `useTranslation`) ，而 hooks 只能在组件内部运行。模块作用域常量只会在文件加载时求值一次，如果在那里翻译，就会锁定当时生效的语言 (在服务器上，则意味着所有用户看到的都是同一种语言) 。正确的做法是让常量只保存一个引用，等到字符串渲染时再进行翻译。

## Video

The video is narrated in English, with English captions.

[How do I translate strings outside JSX?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-translate-strings-outside-jsx.mp4) (49秒)

General Translation translates placeholders with `useGT` and constants with `msg` and `useMessages`. Call `useGT` and pass the placeholder to the function it returns, await `getGT` in async components, register each constant string with `msg` and resolve it with `useMessages`, then run `npx gt translate`.

## 在 JSX 之外翻译字符串的方法

| 方案                                                                              | 优势                                                                                      | 代码中的用法                                                                                                                                                                                                                                    | 需要你自行处理的部分                                                                                       |
| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| [`i18next`](/kb/general-translation-vs-i18next) (`react-i18next`) 或 `next-intl` | 成熟的运行时，提供可翻译任意字符串的翻译函数                                                                  | [`useTranslation`](https://react.i18next.com/latest/usetranslation-hook) 或 [`useTranslations`](https://next-intl.dev/docs/environments/server-client-components) 返回的 [`t`](https://www.i18next.com/overview/api#t) 接收一个键；常量中存放键，在渲染时再进行翻译 | 为每个字符串起一个键，为每种语言各写一个文件，并在文案变动时保持所有文件同步                                                           |
| [`react-intl`](/kb/general-translation-vs-react-intl)                           | 消息描述符包含 ID、默认消息以及供译者参考的说明                                                               | `defineMessages` 在常量中声明描述符，[`useIntl`](https://formatjs.github.io/docs/react-intl/api#useintl-hook) 返回的 [`formatMessage`](https://formatjs.github.io/docs/react-intl/api#formatmessage) 在渲染时翻译单条消息                                        | 为每条消息分配 ID，将消息提取到各语言对应的文件中，并完成所有翻译                                                               |
| [Lingui](/kb/general-translation-vs-lingui)                                     | 源文本本身就是消息，无需另起键名                                                                        | [`msg`](https://lingui.dev/ref/macro#definemessage) 宏在常量中定义消息，[`useLingui`](https://lingui.dev/ref/react) 返回的 `_` 在渲染时进行翻译                                                                                                                | 运行 `lingui extract` 和 `lingui compile`，并翻译每个目录                                                   |
| General Translation (`gt-react` 和 `gt-next`)                                    | [`npx gt translate`](/docs/cli/reference/commands/translate) 会找出代码中的每个字符串，并在生产环境构建前完成翻译 | [`useGT`](/docs/react/reference/hooks/use-gt) 返回一个函数，直接传入源字符串即可调用 (无需键) ；[`msg`](/docs/react/reference/functions/msg) 在常量中注册每个字符串，[`useMessages`](/docs/react/reference/hooks/use-messages) 在渲染时进行翻译                                      | 以字面量形式传入每个字符串，以便 CLI 识别，并在文案变动时重新运行 [`npx gt translate`](/docs/cli/reference/commands/translate) |

如果你的应用已有键文件，且由译者持续维护，请选择 `i18next` 或 `next-intl`。如果译者基于提取出的消息目录工作，且每条消息都需要附带说明或源文本，请选择 `react-intl` 或 Lingui。如果字符串分散在各个组件和共享常量中，且每次发布都会变动，请选择 General Translation。如果某个常量只在一个组件中使用，直接将其移入该组件即可：每个值都会变成普通的翻译调用。

## 使用 General Translation 翻译 JSX 之外的字符串

在 General Translation 的 `gt-react` 和 `gt-next` 中，组件内的字符串通过 [`useGT`](/docs/react/reference/hooks/use-gt) 钩子翻译，常量则通过 [`msg`](/docs/react/reference/functions/msg) 和 [`useMessages`](/docs/react/reference/hooks/use-messages) 翻译。

1. 对于组件中的字符串，调用 `const gt = useGT()` (它直接返回翻译函数本身) ，然后传入字符串字面量，并将变量写成命名占位符：`gt('Welcome back, {name}!', { name: user.name })`。可添加 `$context`，确保有歧义的词被译为正确的含义。

2. 对于常量，先用 [`msg`](/docs/react/reference/functions/msg) 注册每个字符串，再在渲染处用 [`useMessages`](/docs/react/reference/hooks/use-messages) 解析：

   ```tsx
   import { msg, useMessages } from 'gt-react';

   const STATUS = { active: msg('Active'), paused: msg('Paused') };

   function Badge({ status }: { status: 'active' | 'paused' }) {
     const m = useMessages();
     return <span>{m(STATUS[status])}</span>;
   }
   ```

3. 在生产环境构建之前运行 [`npx gt translate`](/docs/cli/reference/commands/translate)。

## 服务端组件与模块作用域

异步的 Next.js App Router 组件无法调用 hooks，因此需要从 `gt-next/server` 中 await [`getGT`](/docs/react/nextjs/reference/functions/get-gt) 和 [`getMessages`](/docs/react/nextjs/reference/functions/get-messages)。在通过 [`initializeGTSPA`](/docs/react/reference/config#initialize-spa) 配置的客户端 `gt-react` 应用中，[`t`](/docs/react/reference/functions/t-function) 函数也能在模块作用域中进行翻译，但切换语言后需要完整刷新页面。各框架的完整步骤请参阅[翻译字符串](/docs/react/guides/translating-strings)指南。

## Related questions

- [如何翻译 JSX 中的条件文本？](https://generaltranslation.com/zh/kb/translate-conditional-jsx.mdx): 保持句子完整，并翻译它的每个版本。三元表达式会把句子拆成碎片，使其失去含义，也无法适应各语言的语序。General Translation 通过在 `<T>` 中使用 `<Branch>` 解决这一问题，将整个句子作为一个整体进行翻译。
- [如何按区域设置格式化数字、日期和货币？](https://generaltranslation.com/zh/kb/format-numbers-dates-currencies.mdx): 在页面渲染时，使用读者的区域设置和 JavaScript 的 Intl API 格式化每个值，并将值放在待翻译的句子之外。General Translation 的 `<Num>`、`<Currency>`、`<DateTime>` 和 `<RelativeTime>` 组件可在 `<T>` 内同时做到这两点，因此一份翻译即可适用于任意值。
- [如何翻译 React 应用？](https://generaltranslation.com/zh/kb/translate-react-app.mdx): 翻译 React 应用，需要先对组件进行国际化，使其以用户的语言渲染，再将每个字符串翻译成你支持的各种语言。General Translation 的 gt-react 在 `<T>` 组件中原地翻译 JSX，npx gt translate 则会为每种语言生成一个文件。
- [不使用翻译文件能实现 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 还能通过拉取请求让译文保持最新。

## Previous and next questions

- Previous question: [如何翻译 Google Slides？](https://generaltranslation.com/zh/kb/translate-google-slides.mdx)
- Next question: [如何翻译 Mintlify 文档站点？](https://generaltranslation.com/zh/kb/translate-mintlify-docs.mdx)

## Sitemap

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