返回博客

Django i18n:自动化 .po 文件翻译完全指南

2026-01-28 4 分钟阅读
Django i18n:自动化 .po 文件翻译完全指南

如果你曾经发布过多语言的 Django 应用,你一定知道这个流程。你用 gettext() 包装字符串,运行 makemessages,打开一个包含数百条记录的 .po 文件,然后逐行翻译。对于两种语言和五十个字符串,这还可以忍受。但如果是六种语言和五百个字符串,那就是一整天再也找不回来的工作时间。

本指南从头到尾介绍 Django 的国际化(i18n)流程,解释它在哪些环节会出问题,并展示如何使用 AI 驱动的翻译来自动化最痛苦的部分。

标准的 Django i18n 工作流程

Django 内置的 i18n 系统设计得很好。核心流程如下:

步骤 1:在代码中标记需要翻译的字符串,包括 Python 代码和模板:

from django.utils.translation import gettext as _

def dashboard(request):
    welcome = _("Welcome back, %(name)s!") % {"name": request.user.first_name}
    return render(request, "dashboard.html", {"welcome": welcome})
{% load i18n %}
<h1>{% trans "Account Settings" %}</h1>
<p>{% blocktrans %}You have {{ count }} unread messages.{% endblocktrans %}</p>

步骤 2:将字符串提取.po 文件中:

python manage.py makemessages -l de -l fr -l nl

这会扫描整个代码库,为每种语言生成一个 .po 文件,包含每个可翻译的字符串:

#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""

#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""

步骤 3:手动翻译每个空的 msgstr

步骤 4:编译完成的 .po 文件为二进制 .mo 文件:

python manage.py compilemessages

步骤 1、2 和 4 很快。步骤 3 是流程崩溃的地方。

为什么手动翻译无法扩展

一个典型的 Django 应用大约有 200 到 2,000 个可翻译的字符串。乘以目标语言的数量,你面对的就是一项巨大的时间投入。

这不是空谈。在一个知名的 Django 论坛帖子中,一位开发者报告称每个 .po 文件的手动翻译花费了 8 个小时以上。一位 Django 核心贡献者描述了花费 10 多个小时将社区提交的翻译整合到一个版本中,主要是审查、格式修正和修复损坏的占位符。

问题会随着时间不断累积:

根本原因是翻译被当作一次性事件,而不是一个增量的、可重复的过程。

使用 AI 自动化翻译

想法很简单:不再由人工打开每个 .po 文件填写 msgstr 值,而是由工具读取文件,将未翻译的字符串发送到 AI 模型或翻译 API,将结果写回,并保留其他所有内容(注释、文件结构、占位符、复数形式)。

TranslateBot Django 是一个开源包,正是做这件事的。它集成到 Django 的管理命令系统中,因此适合你已有的工作流程。

分步设置

1. 安装包

pip install translatebot-django

或者,如果你使用 uv(推荐):

uv add --dev translatebot-django

将其作为开发依赖安装是有意为之的。你只在生成翻译时需要 TranslateBot,生产环境运行时不需要。

2. 添加到 INSTALLED_APPS

# settings.py
INSTALLED_APPS = [
    # ...
    "translatebot_django",
]

3. 配置你的 AI 提供商

# settings.py
import os

TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"

TranslateBot 底层使用 LiteLLM,这意味着你可以通过更改一个字符串来切换 100 多个模型中的任何一个:

提供商 TRANSLATEBOT_MODEL
OpenAI gpt-4o-mini, gpt-4o
Anthropic claude-sonnet-4-5-20250929
Google gemini/gemini-2.5-flash
Azure OpenAI azure/gpt-4o-mini
DeepL 改用 TRANSLATEBOT_PROVIDER = "deepl"

对于 DeepL,安装额外依赖:pip install translatebot-django[deepl]。DeepL 的免费套餐每月提供 500,000 个字符的免费额度,对大多数中小型项目来说足够了。

4. 定义你的语言

# settings.py
LANGUAGES = [
    ("en", "English"),
    ("de", "German"),
    ("fr", "French"),
    ("nl", "Dutch"),
    ("ja", "Japanese"),
]

5. 运行翻译

python manage.py translate

就这样。TranslateBot 扫描你的项目中的 .po 文件,识别未翻译的条目,以优化的批次将它们发送到配置的 AI 模型,并将结果写回。已有的翻译保持不变。

翻译单一语言:

python manage.py translate --target-lang nl

输出如下:

Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings

6. 照常编译

python manage.py compilemessages

你的完整工作流程现在是:

python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages

三条命令。每种语言。每次迭代。

增量设计

对于可重复工作流来说,最重要的功能是增量翻译。TranslateBot 只翻译 msgstr 为空的条目。如果你有 500 个字符串,本次迭代新增了 15 个,只有这 15 个会被发送到 API。

这在实际中很重要:

  1. 成本。 你只为新字符串付费,而不是整个文件。
  2. 速度。 翻译 15 个字符串只需几秒,而不是几分钟。
  3. 稳定性。 你已经审查和批准的翻译永远不会被覆盖(除非你明确传递 --overwrite)。

占位符安全

Django 使用多种占位符格式:%(name)s%s%d{0}{name},以及内联 HTML 标签如 <strong><a href="...">。如果其中任何一个在翻译中被破坏,你就会遇到运行时错误或损坏的标记。

TranslateBot 指示 AI 模型保留所有占位符格式并验证输出。像这样的字符串:

Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.

翻译成荷兰语为:

Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.

每个占位符都完好无损地保留下来。

使用 TRANSLATING.md 控制质量

AI 模型在理解上下文时翻译得更好。TranslateBot 会在你的项目根目录中查找 TRANSLATING.md 文件,并将其内容包含在每个翻译请求中。

# Translation Context

## About This Project
A B2B project management tool for construction companies.

## Terminology
- "project" means a construction project, not a software project
- "plan" means a building plan/blueprint, not a subscription plan
- Keep "Gantt chart" as-is in all languages

## Tone
- German: use formal "Sie" form (business context)
- French: use formal "vous" form
- Dutch: use informal "je" form

## Do Not Translate
- Brand name: "BuildFlow"
- Feature names: "SmartSchedule", "CostTracker"

这个文件与你的代码一起进行版本控制,因此整个团队共享相同的翻译上下文。你也可以为具有专业术语的应用放置各自的 TRANSLATING.md 文件。医疗记录模块和计费模块可以各有自己的术语表。

提交前预览

--dry-run 标志可以准确显示将要翻译的内容,而不会进行任何 API 调用或修改文件:

python manage.py translate --target-lang fr --dry-run
Found 15 untranslated entries
Dry run mode: skipping LLM translation

Would translate 'Welcome to our site'
Would translate 'Hello, %(name)s!'
...

Dry run complete: 15 entries would be translated

这在进行大规模翻译运行之前,或者在新团队成员想要在承担 API 费用之前了解命令的功能时非常有用。

CI/CD 集成

如果不加以强制,翻译变得过时是不可避免的。TranslateBot 包含一个专为 CI 流水线设计的 check_translations 管理命令:

# .github/workflows/ci.yml
jobs:
  translations:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v4
        with:
          enable-cache: true
      - run: uv python install
      - run: uv sync --frozen
      - name: Install gettext
        run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gettext
      - name: Check translations
        run: uv run python manage.py check_translations --makemessages

--makemessages 标志会先运行 makemessages -a --no-obsolete,确保 .po 文件反映当前源代码后再进行检查。如果有任何未翻译或模糊的条目,命令将以退出码 1 退出并使构建失败:

locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed

典型的开发者工作流程变为:

  1. 在功能分支中添加新的可翻译字符串。
  2. CI 因为这些字符串未翻译而失败。
  3. 在本地运行 python manage.py translate
  4. 提交更新后的 .po 文件。
  5. CI 通过。

翻译永远不会悄悄地失去同步。

翻译数据库内容

如果你的应用在数据库中存储可翻译的内容(产品名称、博客文章标题、分类标签),TranslateBot 也可以与 django-modeltranslation 集成:

pip install translatebot-django[modeltranslation]
# Translate all registered model fields
python manage.py translate --target-lang de --models

# Translate specific models only
python manage.py translate --target-lang de --models Product Category

同样的增量逻辑适用:只有目标语言值为空的字段才会被翻译。

成本比较

最常见的问题之一是 AI 翻译与其他方案相比是否具有成本效益。以下是一个拥有 500 个可翻译字符串、5 种语言的项目的粗略比较:

方案 预估成本 时间投入
手动(开发者时间) 零直接费用,20-40+ 小时 非常高
专业翻译服务 $500-2,000+ 低(但周转慢)
SaaS 本地化平台 $50-200/月 中等
TranslateBot + GPT-4o-mini ~$0.05(一次性) 几分钟
TranslateBot + DeepL Free $0(每月最多 500k 字符) 几分钟
TranslateBot + Claude/GPT-4o ~$0.30(一次性) 几分钟

数字会随字符串数量和目标语言的不同而变化,但数量级的差异是一致的。对于持续维护(翻译每次迭代新增的 20-50 个字符串),AI 成本基本为零。

最佳实践

--dry-run 开始。在你第一次真正翻译运行之前,预览将会发生什么。这能建立信心并尽早发现配置问题。

翻译前提交 .po 文件。如果出了问题,git checkout 可以立即回到干净的状态。

从第一天就编写 TRANSLATING.md。即使是一个简短的文件,包含你的项目描述和一些术语规则,也能显著提高翻译质量。

check_translations 添加到 CI。这一个步骤就能防止最常见的 i18n 失败模式:标记为翻译但从未实际翻译的字符串。

使用 gpt-4o-mini 或 DeepL 以提高成本效率。将 GPT-4o 或 Claude 等高级模型留给精度要求更高的项目,如营销文案、法律文本或领域特定术语。

审查关键字符串。AI 翻译对大多数 UI 文本来说已经足够好,但对于任何具有法律约束力的、安全关键的或在高风险场景中面向客户的内容,请让母语人士进行审查。

从数小时到数秒

Django 的 i18n 框架在提取和编译翻译方面表现出色。差距一直在翻译步骤本身——跨多种语言填写数百个 msgstr 值这一繁琐且容易出错的工作。

TranslateBot 弥补了这个差距。安装它,指向一个 AI 提供商,运行一条命令。新字符串被翻译。已有字符串保持不变。占位符完好无损。CI 捕获任何遗漏。

你的 .po 文件不再是一件苦差事,而只是构建的另一个部分。

pip install translatebot-django

translatebot.dev 开始使用。

停止手动编辑 .po 文件

TranslateBot 使用 AI 自动化 Django 翻译。一条命令,覆盖所有语言,每次翻译仅需几分钱。