Cookiecutter Django 国际化实战:从 PO 文件生成到多语言站点上线
2026/9/15 2:28:15 网站建设 项目流程

Cookiecutter Django 国际化实战:从 PO 文件生成到多语言站点上线

【免费下载链接】cookiecutter-djangoCookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.项目地址: https://gitcode.com/GitHub_Trending/co/cookiecutter-django

本篇指南以 Cookiecutter Django 模板内置的 locale 翻译说明 为核心,系统讲解在模板生成的项目中如何配置语言、提取可翻译字符串(makemessages)、人工翻译(.po文件)、编译(compilemessages)以及在生产环境自动构建译文的完整工作流。读完本文,你将掌握从零为 Cookiecutter Django 项目添加一种新语言并让用户真正看到翻译效果的全套实操能力。

翻译工作流总览

Django 的国际化(i18n)机制围绕两类文件展开:

  • .po(Portable Object)文件:纯文本的人类可读翻译源文件,是翻译工作的人工编辑对象;
  • .mo(Machine Object)文件:由.po编译得到的二进制文件,是应用实际加载使用的对象。

在 Cookiecutter Django 生成的项目中,所有翻译文件统一存放在项目根目录下的locale/文件夹中,其内部按语言组织为<语言代码>/LC_MESSAGES/django.po的目录结构,例如模板预置的 en_US、fr_FR、pt_BR 三个示例语言包。

整体流程为:配置语言 → 提取字符串到.po→ 填写msgstr译文 → 编译为.mo→ 应用运行时加载。

第一步:配置 LANGUAGES 启用语言支持

打开项目的 config/settings/base.py 文件,在GENERAL配置段中可以看到默认的LANGUAGE_CODE = "en-us",以及一段被注释掉的LANGUAGES示例:

# https://docs.djangoproject.com/en/dev/ref/settings/#language-code LANGUAGE_CODE = "en-us" # https://docs.djangoproject.com/en/dev/ref/settings/#languages # from django.utils.translation import gettext_lazy as _ # LANGUAGES = [ # ('en', _('English')), # ('fr-fr', _('French')), # ('pt-br', _('Portuguese')), # ]

启用一种语言只需取消注释并保留所需语言即可,例如仅支持英语和法语:

from django.utils.translation import gettext_lazy as _ LANGUAGE_CODE = "en-us" LANGUAGES = [ ("en", _("English")), ("fr-fr", _("French")), ]

与翻译相关的配置还有两个关键点,均在 base.py 中已经就绪:

  • USE_I18N = True:开启 Django 国际化系统;
  • LOCALE_PATHS = [str(BASE_DIR / "locale")]:告诉 Django 从项目根目录的locale/目录加载翻译文件,这正是locale/README.md所述“翻译字符串将放置在本文件夹”的配置基础;
  • 中间件中的django.middleware.locale.LocaleMiddleware(位于MIDDLEWARE列表内SessionMiddleware之后)负责根据请求头、session 或 cookie 自动为每个请求激活对应语言,实现同一站点多语言内容切换。

第二步:用 makemessages 提取可翻译字符串

在模板中,每个可翻译字符串都有翻译标记,它们分布在代码与模板中:

  • 模板文件中使用{% translate "..." %}标签,例如 base.html 中的{% translate "My Profile" %}{% translate "Sign In" %}
  • Python 源码中使用gettext_lazy(常以_别名引入),例如 users/models.py 中的name = CharField(_("Name of User"), blank=True, max_length=255),以及 users/apps.py 中的 verbose_name 等。

Django 的makemessages命令会扫描整个代码库,把这些标记过的字符串收集进.po文件。在项目根目录运行(若项目使用 Docker 开发环境,需通过docker compose执行):

docker compose -f docker-compose.local.yml run --rm django python manage.py makemessages --all --no-location

不使用 Docker 时则直接执行:

python manage.py makemessages --all --no-location

命令参数说明:

  • --all:为LANGUAGES中配置的每一种语言(包括LANGUAGE_CODE)生成或更新对应的.po文件;
  • --no-location:不在.po文件中写入字符串出现的源码位置注释,减少每次生成的 diff 噪音,便于版本控制;
  • 若只更新特定语言,可用-l fr_FR之类的参数代替--all

运行后会在每个语言目录下生成django.po文件,即locale/<语言代码>/LC_MESSAGES/django.po。该命令也被模板的集成测试所验证,见 tests/test_docker.sh 中docker compose -f docker-compose.local.yml run --rm django python manage.py makemessages --all的调用。

第三步:理解并填写 PO 文件

生成的.po文件包含头部元信息与若干翻译条目,每个条目由msgid(源字符串)和msgstr(译文)组成。以模板预置的 fr_FR 翻译文件 为例:

#: {{cookiecutter.project_slug}}/users/models.py:15 msgid "Name of User" msgstr "Nom de l'utilisateur"

locale/README.md中给出的最小示例同样直观:

msgid "users" msgstr "utilisateurs"

在实际文件中可以看到更丰富的用法,例如带插值变量的条目(python-format标记表示字符串包含格式占位符,翻译时不得破坏):

#, python-format msgid "" "Please confirm that <a href=\"mailto:%(email)s\">%(email)s</a> is an e-mail " "address for user %(user_display)s." msgstr "" "Veuillez confirmer que <a href=\"mailto:%(email)s\">%(email)s</a> est un e-mail " "adresse de l'utilisateur %(user_display)s."

以及复数形式声明(文件头部)与需要跨行续写的长字符串。翻译注意事项:

  • 保留%(variable)s这类插值占位符的位置与拼写;
  • 保留<a href="...">等内联 HTML 标签;
  • 若存在复数形式,msgstr需按文件头部Plural-Forms声明的规则逐条填写(例如法语的nplurals=2)。

第四步:用 compilemessages 编译为 MO 文件

.po文件是给翻译人员编辑的源文件,应用运行时并不会直接读取它。必须先把翻译编译成.mo二进制文件,Django 才会真正加载译文。这就是locale/README.md特别强调的坑:即使.po文件是最新的,只要.mo文件过期,页面上也不会显示翻译内容

在项目根目录执行(Docker 环境同样先进入容器):

docker compose -f docker-compose.local.yml run --rm django python manage.py compilemessages

或:

python manage.py compilemessages

编译成功后,每个LC_MESSAGES目录下会出现与django.po同名的django.mo二进制文件。因此,修改任何.po文件后都必须重新运行compilemessages,这是本地开发中最容易遗漏的一步。

生产环境:构建时自动编译

在 Docker 生产环境中,翻译编译已被自动化,无需手工干预。查看 compose/production/django/Dockerfile 的收尾阶段:

# Translations dependencies gettext \ ... RUN DATABASE_URL="postgres://dummy" \ DJANGO_SETTINGS_MODULE="config.settings.test" \ python manage.py compilemessages

关键点:

  • 镜像基于python:3.14-slim-bookworm,并显式安装了gettext系统包——这是compilemessages编译.mo文件所依赖的底层 GNU gettext 工具链;
  • 镜像构建的最后阶段自动执行python manage.py compilemessages,同时用占位数据库地址和config.settings.test配置避免构建期连接真实数据库;
  • 这意味着生产部署时只需保证.po源文件是最新的并提交到仓库,镜像构建过程会自动完成编译,构建出的镜像即可直接提供翻译服务。

从 CHANGELOG.md 的早期记录可见,项目曾专门修复过“部署前缺少 compilemessages 步骤”的问题(#4363),这也印证了自动编译环节的重要性。对于非 Docker 部署场景(如 Heroku),模板在 bin/post_compile 中同样加入了python manage.py compilemessages -i site-packages的构建期编译步骤。

添加一种新语言

按照locale/README.md的指引,为项目增加全新语言只需三个步骤:

1. 更新LANGUAGES设置

在 config/settings/base.py 的LANGUAGES列表中加入目标语言,例如增加简体中文:

LANGUAGES = [ ("en", _("English")), ("fr-fr", _("French")), ("pt-br", _("Portuguese")), ("zh-hans", _("Simplified Chinese")), ]

2. 创建语言目录

locale/文件夹旁创建对应语言代码的目录,例如法语是fr_FR务必注意大小写:语言目录名必须与 Django 识别的 locale 名称完全一致(常见格式如zh_Hanspt_BR),否则 Django 将无法匹配加载。模板预置目录 locale/fr_FR 即为正确命名的参考。

3. 运行makemessages生成 PO 文件

执行第二节中的提取命令,Django 会为新语言生成locale/<新语言>/LC_MESSAGES/django.po,然后按第三节填写译文、第四节编译,即可生效。

验证与排查要点

  • 本地验证:修改翻译后务必依次执行makemessages(新增字符串时)→ 填写msgstrcompilemessages→ 刷新页面查看效果;
  • 未见翻译:优先检查.mo文件是否重新编译、LANGUAGE_CODE/LANGUAGES命名是否与locale/目录名一致、请求语言是否被LocaleMiddleware正确识别;
  • 编译报错:确认系统已安装gettext(Docker 生产镜像已内置);本地裸机环境在 Debian/Ubuntu 上可用sudo apt-get install gettext补齐;
  • 自动化保障:模板的 CI 测试会在 Docker 容器内运行makemessages(见 tests/test_docker.sh),确保每次生成的 PO 文件与代码库中的可翻译字符串保持同步。

通过以上流程,你可以基于 Cookiecutter Django 模板快速搭建支持多语言的生产级 Django 站点:本地用makemessages+compilemessages迭代翻译,生产环境交由 Docker 构建期自动编译,整个国际化链条清晰、可重复、可自动化。

【免费下载链接】cookiecutter-djangoCookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.项目地址: https://gitcode.com/GitHub_Trending/co/cookiecutter-django

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询