# General Translation Knowledge Base: General Translation 与 Symfony Translation：该选哪一个？
URL: https://generaltranslation.com/zh/kb/general-translation-vs-symfony-translation.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Symfony Translation 负责在 PHP 和 Twig 中渲染消息。General Translation 则在 CI 中翻译其 YAML 消息目录，随源内容的变化持续同步更新，并为审校人员提供可直接编辑译文的仪表板。保留 Symfony 的渲染机制，同时为你的发布工作流加入自动化翻译。
Category: 国际化
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

Symfony 应用正是借助 Symfony 的 Translation 组件，以读者的语言显示文本：PHP 中的 `trans()` 和 Twig 中的 `|trans` 过滤器会在当前区域设置对应的目录中查找键，并通过 ICU MessageFormat 处理复数形式和 select 选择。它负责组织和渲染译文，却不负责产出译文：每种语言的目录都要由你、你的译者，或与 Symfony 同步的翻译管理系统 (TMS) 来编写。General Translation 补上的正是这缺失的一环：由 General Translation 的 CLI 翻译你的 Symfony YAML 消息目录，Symfony 照常负责渲染。

## Symfony Translation 的优势

* **PHP 与 Twig 共用一套 API。** 可使用 `$translator->trans()`、[模板中的 `|trans` 过滤器和 `{% trans %}` 标签](https://symfony.com/doc/current/translation.html#translations-in-templates)，以及配合 `TranslatableMessage` 使用的 `t()`——后者适用于先创建、稍后再翻译的消息，例如闪存消息 (flash message) 。
* **支持域和多种文件格式。** 消息目录按 `domain.locale.format` 命名 (`messages.fr.yaml`、`validators.fr.yaml`) ，Symfony 可加载 YAML、XLIFF、PHP、JSON、PO 和 MO、CSV、INI、Qt 以及 ICU 资源包。[其文档建议简单项目使用 YAML](https://symfony.com/doc/current/translation.html#translation-resource-file-names-and-locations)，若译文由专业工具或团队产出，则建议使用 XLIFF。
* **ICU MessageFormat。** [在目录名称中加入 `+intl-icu`](https://symfony.com/doc/current/reference/formats/message_format.html) (`messages+intl-icu.en.yaml`) 后，其中的消息即可使用 ICU 语法处理复数形式、选择以及数字和日期格式。此功能依赖 PHP 的 `intl` 扩展；Symfony 的 polyfill 仅支持英语。
* **提取与检查。** [`translation:extract` 可从 Twig 模板、PHP 代码和验证约束中查找消息](https://symfony.com/doc/current/translation.html#extracting-translation-contents-and-updating-catalogs-automatically)，并将其添加到消息目录中；除非传入 `--format`，否则默认采用 XLIFF 1.2 格式。`debug:translation` 会列出缺失、未使用以及使用后备内容的消息，`lint:translations` 则用于检查目录内容。
* **后备内容。** 缺失的 `es_AR` 消息会[依次回退到 `es_419`、`es`，最后回退到你配置的回退区域设置](https://symfony.com/doc/current/translation.html#fallback-translation-locales)，同时记录该缺失。
* **翻译提供者。** [`translation:push` 和 `translation:pull` 借助官方桥接包，将消息目录与 Crowdin、Loco、Lokalise 和 Phrase 同步](https://symfony.com/doc/current/translation.html#translation-providers)，你也可以自行编写提供者。
* **内置框架消息。** Validator 组件自带的约束消息已翻译成 50 多种语言。

该组件[采用 MIT 许可证；8.1 版本要求 PHP 8.4.1 或更高版本](https://packagist.org/packages/symfony/translation)，7.4 为长期支持版本。

## Symfony Translation 没有替你处理的部分

下面是英文目录中的一条 ICU 复数消息：

```yaml title="translations/messages+intl-icu.en.yaml"
inbox:
  title: Inbox
  unread: >-
    {count, plural,
      =0 {You have no unread messages.}
      one {You have # unread message.}
      other {You have # unread messages.}
    }
```

另外，还有人手动编写了 `messages+intl-icu.es.yaml`，键保持不变，复数形式则用西班牙语重写。下面使用独立组件 (`symfony/translation` 8.1.5) 渲染这两种语言，外加德语：

```php title="render.php"
<?php
require __DIR__.'/vendor/autoload.php';

use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\Translator;

$translator = new Translator('en');
$translator->setFallbackLocales(['en']);
$translator->addLoader('yaml', new YamlFileLoader());

// +intl-icu 后缀会为 messages 域启用 ICU MessageFormat。
foreach (['en', 'es'] as $locale) {
    $file = __DIR__."/translations/messages+intl-icu.$locale.yaml";
    $translator->addResource('yaml', $file, $locale, 'messages+intl-icu');
}

foreach (['en', 'es', 'de'] as $locale) {
    echo $locale, ': ', $translator->trans('inbox.unread', ['count' => 3], 'messages', $locale), "\n";
}
```

```text title="Output"
en: You have 3 unread messages.
es: Tienes 3 mensajes sin leer.
de: You have 3 unread messages.
```

西班牙语之所以能正常显示，是因为有人翻译了它。德语没有目录，所以 Symfony 会悄无声息地回退到英语：在完整的应用中，这次缺失会被记录到日志，`debug:translation de` 也会将其列出，但没有任何机制会替你写出德语译文。每新增一个键，每种语言都要把这个流程重走一遍。`translation:extract --force` 会将该键添加到每个目录中，并加上 `__` 前缀 (使用 `--no-fill` 时则留空) ，然后由人来翻译——要么手动翻译，要么在 TMS 中完成，而提供者命令负责向 TMS 推送和拉取文件。提供者只负责搬运文件；翻译工作本身，以及它所依赖的 TMS 订阅方案，仍需另行解决。

## General Translation 如何融入 Symfony 应用

渲染工作仍交给 Symfony，消息目录则由 General Translation 的 CLI 负责填充。在配置中添加一个 `yaml` 条目，将其指向你的翻译目录，并在每个文件名中用 `[locale]` 占位表示区域设置：

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr", "de"],
  "files": {
    "yaml": {
      "include": ["translations/*.[locale].yaml"]
    }
  }
}
```

[`npx gt translate`](/docs/cli/reference/commands/translate) 会识别所有匹配的英文目录，例如 `messages+intl-icu.en.yaml` 和 `validators.en.yaml`，并为每个目标区域设置生成 `messages+intl-icu.es.yaml`、`validators.es.yaml` 等对应文件，同时保留原有的键和域名称。在 `translation:extract` 向英文目录添加新键后，即可在 CI 中运行该命令。未更改的条目会复用之前的译文，因此每次运行只翻译新增或修改的文本。

在 Symfony 中使用时，有几点需要注意：

* **ICU 消息。** 目录名称中应保留 `+intl-icu`，以便 Symfony 使用 ICU 格式化翻译后的消息。生成完成后运行 `lint:translations`，并分别以 0、1、3 作为计数预览收件箱消息。
* **区域设置代码。** 沿用应用现有的区域设置名称。以 `pt_BR` 为例，将其添加到 `locales`，并在 `gt.config.json` 中设置 `"customMapping": { "pt_BR": { "code": "pt-BR" } }`。这样 CLI 会按巴西葡萄牙语进行翻译，并按 Symfony 的命名方式写入 `messages.pt_BR.yaml` 文件。 (参见 [`customMapping`](/docs/cli/reference/config#custom-mapping)。) 
* **CI 中的 Node.js。** CLI 是一个 npm 包，因此 CI 任务需要安装 Node.js，并在密钥中配置 `GT_API_KEY` 和 `GT_PROJECT_ID`。 (参见[配置 CLI](/docs/cli/guides/configuring#credentials)。) 

General Translation 不仅能填充目录，还能保证目录的一致性：上下文分组中的词汇表和自定义提示词会为其分配到的每个项目统一术语和语气，你的团队还可以[在仪表板中审阅和编辑译文](/docs/platform/dashboard/guides/reviewing-translations)。为 Symfony 应用、文档和营销网站使用同一个上下文分组，即可确保产品术语在三者中保持一致。 (参见[为翻译定义上下文](/docs/platform/dashboard/guides/defining-context-for-translations)。)

## Symfony Translation 与 General Translation 速览

| 功能                | Symfony Translation                             | General Translation                                               |
| ----------------- | ----------------------------------------------- | ----------------------------------------------------------------- |
| 作用                | 在 PHP 和 Twig 中查找并渲染消息                           | 生成供 PHP 和 Twig 调用使用的消息目录                                          |
| 是否翻译内容            | 否；通过提供者将消息目录与 Crowdin、Loco、Lokalise 或 Phrase 同步 | 是，使用 [`npx gt translate`](/docs/cli/reference/commands/translate) |
| 目录格式              | YAML、XLIFF、PHP、JSON、PO 和 MO、CSV、INI、Qt、ICU 资源包  | 此目录工作流支持 YAML 和 JSON                                              |
| 发现新字符串            | `translation:extract` 扫描 Twig、PHP 和约束           | 翻译英文消息目录中的全部内容                                                    |
| ICU MessageFormat | 借助 `intl` 扩展使用 `+intl-icu` 消息目录                 | 翻译目录值，供 Symfony 的 ICU 渲染器使用                                       |
| 缺失的翻译             | 回退链、日志、`debug:translation`                      | 每次运行都会写入所有已配置的区域设置                                                |
| 费用                | 免费，采用 MIT 许可证；提供者单独计费                           | [按用量计费](https://generaltranslation.com/pricing)                   |

## 如何选择

在渲染层面，这并不是二选一的问题：Symfony 应用应继续使用 Symfony Translation。真正需要决定的是如何填充它的消息目录。如果译者在 TMS 中处理 XLIFF 文件、你需要采购专业的人工翻译，或者现有流程已经运转良好，请继续使用翻译提供者。 (参见 [为什么选择 General Translation 而不是 TMS？](/kb/general-translation-vs-tms)) 如果你希望每次变更时都在 CI 中自动翻译所有区域设置的 YAML 目录，在仪表板中共享术语并进行审校，而且无需发送文件、等待返回，请使用 General Translation。

## 同时使用两者

1. 从现有的 Symfony YAML 消息目录入手，并按上文所述添加 `gt.config.json`。
2. 如果已有译文，请先使用 [`npx gt upload`](/docs/cli/reference/commands/upload) 将其上传，再生成新的译文。
3. 在 Symfony 将新消息提取到英文目录后，在 CI 中运行 [`npx gt translate`](/docs/cli/reference/commands/translate)。
4. 在仪表板中审阅译文。如果你在本地编辑了下载的 YAML 文件，请在下一次运行生成之前，使用 [`npx gt save-local`](/docs/cli/reference/commands/save-local) 进行同步。

## 关键要点

* Symfony Translation 负责渲染消息、提取键，并与 TMS 提供者同步；生成译文则是另一个独立的步骤。
* General Translation 在 CI 中翻译 Symfony 的 YAML 消息目录，并保留原有的键和域，PHP 和 Twig 可以继续使用相同的消息。
* 如果需要 XLIFF 和专业译员，请继续使用 TMS 提供者；如果希望每次变更后都自动翻译消息目录，请使用 General Translation。

## Related questions

- [General Translation 与 i18next、react-intl 和 next-intl 对比：应该选择哪个国际化库？](https://generaltranslation.com/zh/kb/general-translation-vs-i18n-libraries.mdx): i18next、react-intl 和 next-intl 等开源库本身并不翻译任何内容。它们只负责显示你在各语言目录文件中提供的译文，这些译文由你、你的译者或其他服务编写。General Translation 的库同样开源，承担同样的工作，此外 General Translation 还会以你的代码为上下文完成翻译。
- [为什么选择 General Translation 而不是 TMS（Smartling、Lokalise、Phrase、Crowdin 或 Transifex）？](https://generaltranslation.com/zh/kb/general-translation-vs-tms.mdx): Smartling、Lokalise、Phrase、Crowdin 或 Transifex 等翻译管理系统（TMS）负责协调译员，但工程师仍需提取字符串、发送出去、等待译文，再把译文接回产品中。General Translation 结合上下文直接翻译代码中的内容，每次发布都同步交付所有语言，并基于开源库运行，不存在供应商锁定。
- [General Translation 与 GNU gettext：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-gettext.mdx): 继续用 GNU gettext 负责提取和渲染，再引入 General Translation 来生成和维护 PO 文件。General Translation 会把译者备注和消息上下文纳入生成过程，统一应用共享术语，并为审校人员提供 仪表板 编辑器。你现有的 gettext 调用和已编译的消息目录均保持原样。
- [General Translation 与 Rails I18n：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-rails-i18n.mdx): Rails I18n 负责查找消息并格式化日期和数字。General Translation 负责生成译文，在英文内容变更时让译文保持同步，并为团队提供用于审校的仪表板。两者搭配使用，即可在每次发布时交付已翻译的 Rails 目录。
- [General Translation 与 Django 翻译框架：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-django-i18n.mdx): 将 Django 的翻译框架与 General Translation 搭配使用。Django 负责消息提取、语言选择和渲染；General Translation 则基于你的产品术语和仪表板审阅，填充 Django 的 PO 文件（包括复数形式）。你的模板和 URL 模式无需改动，译文会随代码同步更新。

## Previous and next questions

- Previous question: [General Translation 与 Rails I18n：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-rails-i18n.mdx)
- Next question: [General Translation 与 Tolgee：该如何选择？](https://generaltranslation.com/zh/kb/general-translation-vs-tolgee.mdx)

## Sitemap

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