# General Translation Knowledge Base: General Translation 与 Django 翻译框架：两者都需要吗？
URL: https://generaltranslation.com/zh/kb/general-translation-vs-django-i18n.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 将 Django 的翻译框架与 General Translation 搭配使用。Django 负责消息提取、语言选择和渲染；General Translation 则基于你的产品术语和仪表板审阅，填充 Django 的 PO 文件（包括复数形式）。你的模板和 URL 模式无需改动，译文会随代码同步更新。
Category: 国际化
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

Django 自带一套完整的国际化 (i18n) 框架：你用 `gettext` 和 `{% translate %}` 标记字符串，`makemessages` 将其提取到各语言对应的 PO 文件中，`compilemessages` 构建供 Django 加载的 `.mo` 文件，`LocaleMiddleware` 则为每个请求选择语言。General Translation 补上了提取与编译之间的翻译环节：它的 CLI 读取你的英文目录，并写出供 Django 加载的已翻译 PO 文件。

## Video

The video is narrated in English, with English captions.

[General Translation vs. Django's translation framework: do you need both?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-general-translation-vs-django-i18n.mp4) (46秒)

Use both: Django extracts messages, selects the language, and renders, and General Translation fills its PO files, plural forms included, with your terminology and Dashboard review. To set it up, keep running makemessages, point `gt.config.json` at your locale folders, and run `npx gt translate` before compilemessages in CI. A Glossary keeps terms consistent, and reviewers edit entries in the Dashboard.

## Django 翻译框架的优势

* **随处标记字符串。** `gettext` 和 `ngettext` [用于 Python 代码](https://docs.djangoproject.com/en/5.2/topics/i18n/translation/#internationalization-in-python-code)，`gettext_lazy` 用于在导入时定义的字符串 (例如模型字段和表单标签) ，`pgettext` 可为有歧义的词语添加上下文，`{% translate %}` 和 `{% blocktranslate %}` (配合 `count` 处理复数形式) 则用于模板。
* **内置提取与编译。** `makemessages` 会对你的 Python 文件和模板运行 GNU gettext 的 `xgettext`，并[将新字符串合并到每种语言各自的 `django.po` 文件中](https://docs.djangoproject.com/en/5.2/topics/i18n/translation/#message-files)，文件位于 `locale/<locale>/LC_MESSAGES/`。写在字符串上方的 `# Translators:` 注释会被带入 PO 文件，供译者参考。
* **按请求选择语言。** `LocaleMiddleware` 会依次[检查由 `i18n_patterns` 添加的 URL 前缀](https://docs.djangoproject.com/en/5.2/topics/i18n/translation/#how-django-discovers-language-preference)、语言 cookie、`Accept-Language` 请求头，最后是 `LANGUAGE_CODE`。它只会选择 `LANGUAGES` 中列出的语言，并支持从 `de-at` 回退到 `de`。
* **不止于字符串。** 日期和数字会[按当前区域设置进行格式化](https://docs.djangoproject.com/en/5.2/topics/i18n/formatting/)，`JavaScriptCatalog` 还会向浏览器提供一个独立的 `djangojs` 目录。
* **Django 自身已完成翻译。** 管理后台和内置应用[自带约一百种语言的目录](https://github.com/django/django/tree/stable/5.2.x/django/contrib/admin/locale)，而且该框架基于 BSD 许可证免费使用。

## Django 留给你的工作

[Django 官方文档](https://docs.djangoproject.com/en/5.2/topics/i18n/translation/#compiling-message-files)介绍了它自身不负责的那一步：译者填好消息文件后，需要由你来编译。下面是一个包含复数形式的模板：

```html title="shop/templates/shop/inbox.html"
{% load i18n %}
<p>{% blocktranslate count counter=count %}{{ counter }} file{% plural %}{{ counter }} files{% endblocktranslate %}</p>
```

在 Django 5.2 中，`python manage.py makemessages -l ru` 会把 Django 自带目录中俄语的四种形式复数规则复制到文件头中，但只为该条目写入两个空槽位：

```text title="locale/ru/LC_MESSAGES/django.po"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
"(n%100>=11 && n%100<=14)? 2 : 3);\n"

#: shop/templates/shop/inbox.html:2
#, python-format
msgid "%(counter)s file"
msgid_plural "%(counter)s files"
msgstr[0] ""
msgstr[1] ""
```

在一次测试中，只填写这两个槽位生成的目录能够通过 `compilemessages` 构建且不报错，页面也渲染出了 &quot;1 файл&quot; 和 &quot;3 файла&quot;，但数量为 5 时却以英文显示为 &quot;5 files&quot;，因为复数规则为 5 选中的那个槽位从未填写。空目录同样会悄无声息地失效：`pt_BR` 中没有任何内容时，`/pt-br/` 页面会完全以英文渲染。每标记一个新字符串，这一流程都要在每种语言中重来一遍。

此外，Django 只处理代码中的字符串。存储在数据库中的内容 (例如产品名称或页面) 需要借助第三方包：django-modeltranslation 会在您注册的模型上[为每种语言添加一个字段](https://django-modeltranslation.readthedocs.io/en/latest/registration.html)，django-parler 则将翻译保存在单独的表中。两者都只是为翻译提供了存放的位置，翻译本身仍需您自己来写。

## 使用 General Translation 翻译 Django 的 PO 文件

General Translation 的 CLI 会读取 Django 已在维护的英文目录，逐条翻译其中的条目，并为每种目标语言生成 PO 文件，写入 Django 查找翻译的位置。请使用 `makemessages` 让英文目录保持最新：

```bash
python manage.py makemessages -l en
```

然后在 `gt.config.json` 中指向它。此配置已基于 `gt` 2.26.5 验证：

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "pl", "pt_BR"],
  "customMapping": {
    "pt_BR": { "code": "pt-BR" }
  },
  "files": {
    "pot": {
      "include": ["locale/[locale]/LC_MESSAGES/*.po"],
      "transformationFormat": "PO"
    }
  }
}
```

这里有几个需要注意的细节，均在 [PO / POT 格式参考](/docs/cli/reference/formats/po-pot-files)中有详细说明：

* **PO 和 POT 文件都使用 `pot` 这个键。** `transformationFormat` 必须设为 `PO`；否则输出仍是未翻译的模板。
* **区域设置目录沿用 Django 的命名。** CLI 会按你书写的原样，将 `[locale]` 替换为每个区域设置。[`customMapping`](/docs/cli/reference/config#custom-mapping) 可将 Django 的 `pt_BR` 目录映射到标准区域设置代码 `pt-BR`。
* **`*.po` 会匹配所有域**；如果你还运行了 `makemessages -d djangojs -l en`，`djangojs.po` 也会包含在内。

设置好 CLI 后 (参见 [CLI 快速入门](/docs/cli/quickstart)) ，运行 [`npx gt translate`](/docs/cli/reference/commands/translate)，然后运行 `python manage.py compilemessages`。General Translation 会将 PO 文件中与每个条目相关的信息作为上下文一并发送：`msgctxt`、`# Translators:` 注释、源文件引用，以及 `python-format` 等标记。对于复数条目，它会写入目标语言的 `Plural-Forms` 头，按该头的要求填充每个 `msgstr[n]` 槽位，并检查 `%(counter)s` 等占位符是否完整保留。以俄语为例，这里采用的是标准的 gettext 三种形式规则；由于 Django 会分别读取每个目录的规则，因此不会与 Django 自带俄语目录中的四种形式规则冲突。

未更改的条目会复用之前的译文，因此下次运行只翻译有变化的内容；使用 `--force` 则会重新翻译全部内容。如果你的 PO 文件中已有译文，请在生成新译文之前运行 [`npx gt upload`](/docs/cli/reference/commands/upload)。如需保留之后的本地修改，请在下一次翻译运行前使用 [`npx gt save-local`](/docs/cli/reference/commands/save-local) 进行同步。

这正是完整技术栈的优势所在。借助[上下文分组](/docs/platform/dashboard/guides/defining-context-for-translations)中的词汇表和自定义提示词，你的 Django 目录与分配到该组的其他项目都能保持一致的产品术语和语气。审阅者可以在仪表板中[编辑每个 PO 条目](/docs/platform/dashboard/guides/reviewing-translations)，包括其复数形式。在 CI 中运行 `makemessages`、[`gt translate`](/docs/cli/reference/commands/translate) 和 `compilemessages`，即可在每次发布时同步更新译文。

对于数据库内容以及其他仅在运行时才存在的文本，可通过 General Translation 的 API 按需翻译字符串 ([`POST /v2/translate`](/docs/platform/openapi/reference/translation/translate-content)) ；结果需由你自行存储，例如存入 django-modeltranslation 中按语言划分的字段。

请在运行 CLI 的机器上安装 Node.js。Django 仍通过现有的 Python 运行时提供已编译的目录。

## Django 翻译框架与 General Translation 速览

| 功能              | Django 翻译框架                                                                               | General Translation                                                |
| --------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| 在代码和模板中标记字符串    | 支持：`gettext`、`{% translate %}` 等                                                          | 沿用现有的 Django 消息调用                                                  |
| 将字符串提取到 PO 文件   | 支持，通过 `makemessages`                                                                      | 读取 `makemessages` 生成的文件                                            |
| 生成译文            | 不支持                                                                                       | 支持，通过 [`npx gt translate`](/docs/cli/reference/commands/translate) |
| 复数形式            | 文件头来自 Django 的目录；每个槽位需手动填写                                                                | 写入目标语言的文件头并填写所有槽位                                                  |
| 翻译上下文           | PO 文件中的 `# Translators:` 注释和 `msgctxt`                                                    | 同上，另支持词汇表和自定义提示词                                                   |
| 按请求切换语言及 URL 前缀 | 支持，通过 `LocaleMiddleware` 和 `i18n_patterns`                                                | 保留 Django 的路由和语言选择机制                                               |
| 数据库内容           | 依赖第三方包，例如 django-modeltranslation                                                         | 运行时 API 翻译；结果需自行存储                                                 |
| 费用              | 免费、开源 ([BSD](https://docs.djangoproject.com/en/5.2/faq/general/#how-is-django-licensed))  | [按用量计费](https://generaltranslation.com/pricing)                    |

## 如何选择

如果你已有译者或翻译管理系统负责填充 PO 文件，或者产品只发布一两种语言、可以手动翻译，又或者每条译文都必须由人工撰写，那么单独使用 Django 框架即可。如果你希望每次变更后，所有语言的 PO 文件都能自动填充完整，复数形式齐全、术语前后一致，并且在合并与发布之间无需再走一轮翻译流程，那就可以引入 General Translation。

两者并不冲突：Django 负责标记、提取、编译和语言选择，General Translation 负责翻译。你也无需进行任何迁移，模板、中间件和 URL 模式都保持不变。

## 要点总结

* Django 的翻译框架只负责渲染译文，不负责生成译文。如果缺少复数槽位或目录为空，会直接回退为英文，且不会报任何构建错误。
* General Translation 会将 `makemessages` 生成的英文目录翻译成各语言对应的 PO 文件。你的模板、中间件和 URL 模式都无需改动。
* 对于每个复数条目，General Translation 会写入目标语言的 `Plural-Forms` 头信息及所有 `msgstr[n]` 槽位，并将 `msgctxt` 和译者注释作为上下文一并传入。

## Related questions

- [General Translation 与 GNU gettext：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-gettext.mdx): 继续用 GNU gettext 负责提取和渲染，再引入 General Translation 来生成和维护 PO 文件。General Translation 会把译者备注和消息上下文纳入生成过程，统一应用共享术语，并为审校人员提供 仪表板 编辑器。你现有的 gettext 调用和已编译的消息目录均保持原样。
- [General Translation 与 Babel、Flask-Babel 对比：该选哪一个？](https://generaltranslation.com/zh/kb/general-translation-vs-flask-babel.mdx): Babel 可以为任意区域设置格式化日期、数字和货币，并管理 gettext 消息目录；Flask-Babel 则负责将其集成到 Flask 中，但两者都不会翻译你的字符串。General Translation 的 CLI 会为每种语言填充 Babel 的 PO 文件（包括复数形式），因此你可以继续使用 Flask-Babel，不必再手动翻译消息目录。
- [General Translation 与 Rails I18n：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-rails-i18n.mdx): Rails I18n 负责查找消息并格式化日期和数字。General Translation 负责生成译文，在英文内容变更时让译文保持同步，并为团队提供用于审校的仪表板。两者搭配使用，即可在每次发布时交付已翻译的 Rails 目录。
- [General Translation 与 TMS（Crowdin、Lokalise、Phrase）对比](https://generaltranslation.com/zh/kb/general-translation-vs-tms.mdx): 如果开发者希望译文生成、源自代码的上下文以及审校流程都与产品发布紧密衔接，请选择 General Translation。你可以保留现有的消息目录和渲染库，也可以直接编写内联 JSX，无需翻译键。TMS 适合以语言供应商、CAT 编辑器和 XLIFF 交换为核心的翻译项目，其集成可以自动完成文件传输。
- [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 还会以你的代码为上下文完成翻译。

## Previous and next questions

- Previous question: [General Translation 与 Babel、Flask-Babel 对比：该选哪一个？](https://generaltranslation.com/zh/kb/general-translation-vs-flask-babel.mdx)
- Next question: [General Translation 与 GNU gettext：两者都需要吗？](https://generaltranslation.com/zh/kb/general-translation-vs-gettext.mdx)

## Sitemap

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