导读:本期聚焦于小师妹创作的《如何在 Django 前端 JavaScript 中实现按钮文本的国际化翻译》,敬请观看详情。当 Django 项目的页面里出现由 JavaScript 动态生成的按钮文本时,很多朋友会发现后端的 i18n 机制管不到这些字符串。本文围绕这一痛点展开,介绍如何利用 Django 内置的 JavaScript 国际化目录(JavaScript Catalog),从配置 urls、加载翻译脚本,到在 JS 代码中调用 gettext、ngettext 等函数完成单复数处理,再到通过 makemessages 提取 js 文件中的待翻译字符串并编译为 mo 文件。文章还补充了动态切换语言、避免缓存陷阱以及常见报错的排查方法,帮助你把前后端的国际化体验统一起来,让按钮、提示语等界面元素都能根据用户语言正确显示。

Django 自带的国际化体系在后端模板中工作得很好,但一旦按钮文本、确认弹窗这类内容由前端 JavaScript 动态生成,{% trans %} 标签就无能为力了。要让 JS 里的字符串也能跟随用户语言变化,需要借助 Django 提供的 JavaScript 国际化目录机制。本文将完整讲解这套方案的配置与使用方法。

如何在 Django 前端 JavaScript 中实现按钮文本的国际化翻译

一、为什么后端 i18n 管不到 JavaScript

先理解问题的根源。Django 的翻译机制基于 GNU gettext,工作流程是:在模板中标记待翻译字符串,通过 makemessages 提取到 po 文件,翻译后编译成 mo 文件,请求到达时根据 LANGUAGE_CODE 或会话中的语言设置返回对应译文。这一切都发生在服务端渲染阶段。

而 JavaScript 是在浏览器中执行的。如果按钮文本写成 document.getElementById('btn').textContent = '确定',浏览器拿到的就是硬编码字符串,服务端根本不知道这个字符串需要翻译。即使你在模板里做了语言判断,JS 代码一旦缓存或复用,语言信息也会丢失。

Django 的解决方案是提供一个专门的视图,把 gettext 函数和当前语言对应的翻译字典打包成一份 JavaScript 文件,让前端代码可以像在 Python 中一样调用翻译函数。这就是所谓的 JavaScript Catalog(JS 翻译目录)。

二、配置 JavaScript 国际化目录

第一步是在项目的 urls.py 中挂载 i18n 视图。Django 提供了一个现成的 JavaScriptCatalog 视图,配置非常简单:

from django.urls import path
from django.views.i18n import JavaScriptCatalog

urlpatterns = [
    # packages 参数指定从哪些应用中收集翻译字符串
    path('jsi18n/', JavaScriptCatalog.as_view(packages=['myapp']), name='javascript-catalog'),
]

packages 参数非常重要,它告诉 Django 从哪些应用的 locale 目录中收集翻译条目。如果你希望全局可用,可以传入 settings 所在的包。需要注意的是,被列出的应用必须存在对应的 locale 目录,否则目录文件会是空的。

第二步是在基础模板中引入这份脚本,注意要放在你自己的 JS 代码之前:

<script src="{% url 'javascript-catalog' %}"></script>
<script src="{% static 'js/app.js' %}"></script>

同时确认 settings.py 中已完成国际化基础配置,包括 USE_I18N = TrueLOCALE_PATHS 指向 locale 目录,以及 django.middleware.locale.LocaleMiddleware 已加入中间件列表且位置在 SessionMiddleware 之后。

三、在 JavaScript 中调用翻译函数

引入目录脚本后,前端全局就可以使用若干翻译函数。最常用的是 gettext,它接收一个字符串并返回译文:

// 简单翻译
document.getElementById('submitBtn').textContent = gettext('确定');

// 带参数插值,使用 interpolate
var msg = interpolate(gettext('欢迎你,%s'), ['张三']);
alert(msg);

// 处理单复数
var count = 3;
var text = ngettext('%s 个文件待删除', '%s 个文件们待删除', count);
alert(interpolate(text, [count]));

ngettext 对中文场景用处不大,但如果你的站点同时支持英文、俄文等有单复数区分的语言,它是必不可少的。对于命名参数插值,interpolate 还支持对象形式:

var fmt = gettext('用户 %(name)s 于 %(time)s 提交了订单');
var text = interpolate(fmt, {name: '李四', time: '10:30'}, true);
// 第三个参数为 true 时启用命名插值

这些函数的翻译数据全部来自第二步加载的目录文件,因此切换语言后需要重新加载页面或重新请求该脚本,才能拿到新语言的译文。

四、提取并翻译 JS 中的字符串

JS 文件里的字符串同样要进入 po 文件才能被翻译。在项目根目录执行:

django-admin makemessages -l zh_Hans -d djangojs

注意这里使用了 -d djangojs 域,JS 相关的翻译会生成在 djangojs.po 中,与后端的 django.po 互不干扰。Django 会扫描所有 JS 文件(默认扩展名包括 .js,也支持 .jsx 等,可通过 xgettext 的参数调整),把 gettextngettext 调用中的字符串提取出来。

翻译完成后执行编译命令:

django-admin compilemessages

编译生成的 djangojs.mo 会被 JavaScriptCatalog 视图读取并打包成 JS 数据。一个小技巧是:目录脚本带有缓存,调试时如果修改了翻译却看不到变化,可以在浏览器中强制刷新,或者在开发环境给 URL 加时间戳参数绕过缓存。

五、动态切换语言与常见问题排查

如果站点支持用户在前端切换语言,标准做法是使用 Django 提供的 set_language 重定向视图,通过一个 POST 表单提交语言参数,随后整页刷新,目录脚本也会以新语言重新生成。切莫只改前端某个变量而不刷新,目录文件中的翻译数据在加载时就固定了。

排查问题时可以按以下顺序检查:第一,直接在浏览器访问 /jsi18n/ 路径,确认返回的脚本中包含你期望的翻译条目;第二,检查 po 文件中该字符串是否已翻译并编译成功;第三,确认字符串完全匹配,包括空格和标点,gettext 匹配是精确匹配;第四,确认 packages 参数覆盖了字符串所在的应用。

还有一点容易踩坑:如果多个应用之间存在同名翻译字符串但译文不同,目录会按应用顺序覆盖。建议把前端公共字符串统一放到一个专门的应用中管理,避免冲突。按照这套流程做下来,前端按钮、弹窗、提示文本就能和后端模板保持完全一致的多语言体验了。

Django国际化JavaScript i18n前端翻译修改时间:2026-09-01 06:54:59

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。