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_Hans、pt_BR),否则 Django 将无法匹配加载。模板预置目录 locale/fr_FR 即为正确命名的参考。
3. 运行makemessages生成 PO 文件
执行第二节中的提取命令,Django 会为新语言生成locale/<新语言>/LC_MESSAGES/django.po,然后按第三节填写译文、第四节编译,即可生效。
验证与排查要点
- 本地验证:修改翻译后务必依次执行
makemessages(新增字符串时)→ 填写msgstr→compilemessages→ 刷新页面查看效果; - 未见翻译:优先检查
.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),仅供参考