第20讲、Odoo 18 翻译机制与 PO 文件详解
Odoo 18 作为全球领先的企业管理平台,其国际化(i18n)和本地化(l10n)能力尤为突出。本文结合官方文档、社区经验和实操案例,系统梳理 Odoo 18 的翻译架构、PO 文件格式、自动与手动提取机制、翻译加载与切换原理、AI 辅助翻译、常见问题与最佳实践,帮助开发者和实施顾问全面掌握 Odoo 的多语言支持能力。
1. Odoo 翻译机制整体架构
Odoo 的翻译机制以 GNU gettext 标准为核心,采用 PO(Portable Object)文件系统来管理多语言内容。每个模块通常在 yourmodule/i18n/ 目录下维护自己的翻译模板(POT 文件)和各语言翻译文件(PO 文件)。
- POT 文件:模板文件,包含所有可翻译字符串,无实际翻译内容。
- PO 文件:特定语言的翻译文件,如
zh_CN.po,包含原文(msgid)与翻译(msgstr)。
Odoo 支持自动和手动两种方式提取可翻译字符串,并在用户切换语言或模块安装/更新时自动加载对应翻译。
1.1 多语言切换与加载原理
- 用户偏好:每个用户可设置界面语言,Odoo 会根据用户设置自动切换界面语言。
- 网站多语言:支持多语言 URL、前端语言切换器,网站内容可独立翻译。
- 上下文切换:通过 context['lang'] 控制,代码层面可动态切换语言环境。
- 按需延迟加载与缓存:提升性能,避免重复加载。
2. PO 文件结构与常见翻译类型
PO 文件是 Odoo 翻译的核心载体,结构清晰,便于维护和协作。其基本组成包括:
- 文件头信息:项目、语言、版本等元数据。
- 翻译条目:每条包含注释(#)、原文(msgid)、译文(msgstr)。
2.1 字段级别翻译
用于模型字段名称、帮助文本等:
#. module: account
#: model:ir.model.fields,field_description:account.field_account_payment__reconciled_bills_count
msgid "# Reconciled Bills"
msgstr "# 已核对账单"
2.2 菜单与模型名称翻译
用于界面菜单项、模型名称:
#. module: account
#: model:ir.ui.menu,name:account.account_account_menu
msgid "Account"
msgstr "科目"
#. module: account
#: model:ir.model,name:account.model_account_merge_wizard
msgid "Account merge wizard"
msgstr "账户合并向导"
2.3 按钮、标题与 HTML 内容翻译
通常通过 model_terms:ir.ui.view 标记,支持 HTML 标签:
#. module: account
#: model_terms:ir.ui.view,arch_db:account.view_account_payment_form
msgid "<span class=\"o_stat_text\">Transaction</span>"
msgstr "<span class=\"o_stat_text\">交易</span>"
2.4 变量占位符与代码来源
PO 文件支持变量占位符(如 %(amount)s),并可标记来源于 Python 或 JavaScript 代码:
#. module: account
#. odoo-python
#: code:addons/account/models/account_move.py:0
msgid "% (amount)s due % (date)s"
msgstr "% (amount)s到期日期 % (date)s"
2.5 PO 文件结构细节
- 注释:
#.表示模块,#:表示具体位置,#. odoo-python/#. odoo-javascript表示代码来源。 - 多条 msgid:同一翻译可对应多个位置。
- HTML 标签:保留标签,仅翻译内容。
- 变量:保留变量格式,避免破坏运行时替换。
3. 翻译提取机制:自动与手动
3.1 自动提取(隐式导出)
Odoo 能自动从以下内容中提取可翻译字符串:
- 视图定义:所有文本节点及 string、help、sum、confirm、placeholder 属性。
- QWeb 模板:除
t-translation="off"外的所有文本节点及常用属性(title、alt、label、placeholder)。 - 模型字段:未被
_translate = False标记的字段的 string、help、selection。 - 约束与错误消息:如
_constraints、_sql_constraints。
3.2 手动标记(显式导出)
对于 Python/JS 代码中的动态字符串,需用特定函数包裹:
- Python:
_("Bank Accounts")或self.env._("Bank Accounts") - JavaScript:
_t("Bank Accounts") - 懒加载:Python 用
LazyTranslate,JS 用_lt,延迟到渲染时查找翻译。
3.2.1 变量与格式化
- 正确:
_("Scheduled meeting with %s", invitee.name) - 错误:
_("Scheduled meeting with %s" % invitee.name)
3.2.2 语句块与上下文
- 保持完整语句,避免拆分翻译块,便于译者理解上下文。
3.2.3 复数处理
- 正确:根据 count 选择不同 msgid,避免简单拼接 s。
3.2.4 运行时查找
- 避免:在服务启动时查找翻译(无用户语言环境)。
- 推荐:在实际渲染或抛出错误时查找翻译。
4. 翻译文件的导出、导入与批量管理
4.1 导出翻译模板
- 后台:设置 > 翻译 > 导入/导出 > 导出翻译
- 选择 PO 文件格式、目标模块,导出
.pot模板 - 用 POEdit、msginit 或文本编辑器编辑,生成目标语言
.po文件 - 放入模块
i18n/目录,Odoo 自动加载
4.2 导入与批量翻译
- 导入:设置 > 翻译 > 加载翻译,选择语言和模块,支持覆盖已有翻译
- 批量管理:可通过后台"翻译条目"界面批量编辑和审核
- AI 辅助:Odoo 18 支持 AI 自动翻译建议,提升效率,支持批量处理和人工校对
4.3 定制模块翻译
- 自定义模块:需手动导出模板、编辑 PO 文件、放入 i18n 目录
- 新增语言:可通过
res.lang.csv文件注册新语言 - 无需在 manifest 中声明,Odoo 自动识别 i18n 下的 PO 文件
5. 前后端翻译与多端一致性
5.1 前端(JS/QWeb)翻译
- QWeb 模板:自动提取文本节点,支持多语言切换
- JS 代码:用
_t包裹字符串,注意只支持字面量 - 前端可见性:模块需以
website_前缀或通过ir.http注册,前端 JS 才能访问翻译
5.2 后端(Python/视图)翻译
- 模型、视图、字段、帮助、约束等均可自动提取
- 动态内容:用
self.env._()或LazyTranslate实现运行时翻译
6. AI 辅助翻译与智能校对
Odoo 18 引入 AI 辅助翻译:
- 自动建议:基于上下文智能生成翻译,支持一键应用
- 批量翻译:大批量内容可自动处理,人工审核提升质量
- 术语一致性:AI 保持专业术语统一,减少人工维护成本
- 上下文感知:结合字段、模块、业务场景,提升准确率
7. 常见问题与排查技巧
7.1 翻译未生效
- 检查 PO 文件是否放在正确的
i18n/目录 - 文件名是否为标准语言代码(如
zh_CN.po) - 是否已通过"加载翻译"导入/覆盖
- 模块是否已升级或重启服务
- 字段/视图是否设置
translate=True
7.2 PO 文件格式错误
- 检查文件编码为 UTF-8
- 检查 msgid/msgstr 是否成对出现,避免缺失
- 避免多余空格、换行、特殊字符破坏格式
7.3 复数与变量问题
- 遵循 PO 复数规则,避免简单拼接
- 保留变量格式,避免破坏运行时替换
7.4 前端翻译不显示
- 检查模块是否注册为前端可见
- JS 代码是否用
_t包裹字面量 - QWeb 模板是否未被
t-translation="off"屏蔽
8. 最佳实践与实用建议
- 保持翻译文件组织:所有翻译文件应放在正确的
i18n/目录,遵循命名规范。 - 定期更新翻译:模块更新后及时补充新字符串的翻译。
- 格式化字符串注意:始终标记原始格式字符串。
- 避免硬编码:代码中显示文本应可翻译。
- 上下文注释:为复杂或多义字符串添加注释,便于翻译者理解。
- 多语言测试:发布前测试不同语言下的界面和功能。
- UI 适配:注意不同语言下文本长度变化对界面的影响。
- AI 辅助+人工审核:大批量内容可用 AI 辅助,但需人工校对。
- 社区协作:善用 Odoo 官方翻译平台和社区资源,提升翻译质量。
- 自动化工具:结合 POEdit、msginit、脚本等工具批量处理翻译。
9. Jinja2 模板的翻译支持
在 Odoo 中,除了 QWeb 视图外,Jinja2 也常用于邮件模板、报表模板、甚至自定义 HTML 文件。Odoo 对 Jinja2 模板的多语言支持同样完善。
9.1 Jinja2 模板中的翻译用法
- 推荐用法:在 Jinja2 模板中,使用
_()或{% trans %}包裹需要翻译的字符串。 - Odoo 会自动扫描这些标记,提取到 PO 文件,翻译后自动加载。
代码示例:
<p>{{ _('Hello') }} {{ object.partner_id.name }},</p>
<p>{{ _('Your order has been confirmed.') }}</p>
{% trans %}This is a translatable string{% endtrans %}
9.2 翻译提取与加载流程
- Odoo 的翻译工具会自动扫描 Jinja2 模板中的
_()和{% trans %}标记。 - 这些字符串会被导出到 PO 文件,翻译后导入,Odoo 渲染时会根据当前用户语言自动替换。
9.3 注意事项
- 模板文件需放在 Odoo 识别的目录(如
views/、report/、mail/等)。 - 不要硬编码字符串,应始终用
_()或{% trans %}包裹。 - 自定义 Jinja2 渲染时,需确保渲染上下文中包含
_函数,并且当前语言已设置到上下文(Odoo 默认已处理)。 - QWeb 和 Jinja2 模板的翻译提取机制略有不同,但都统一到 Odoo 的 PO 文件体系。
9.4 参考资料
结论:只要在 Jinja2 模板中用 Odoo 推荐方式标记可翻译字符串,Odoo 就能自动提取、管理和渲染翻译内容,适用于网站、报表、邮件等多种场景。
10. 字段内容的快速翻译方法
Odoo 支持对模型字段(如名称、描述、帮助等)内容进行高效的多语言翻译,常见方法如下:
10.1 自动提取与 PO 文件翻译
- 自动提取:Odoo 会自动扫描所有设置了
string、help、selection等属性的字段(未设置_translate = False),并将其内容导出到 PO 文件。 - 操作步骤:
- 后台:设置 > 翻译 > 导入/导出 > 导出翻译,选择目标模块和语言,导出 PO 文件。
- 用 POEdit 或文本编辑器填写
msgstr,保存后放回模块i18n/目录。 - 重新加载翻译或升级模块,字段内容即可多语言切换。
代码示例(模型定义):
class Product(models.Model):
_name = 'my.product'
name = fields.Char(string='Product Name', translate=True)
description = fields.Text(string='Description', translate=True)
10.2 后台批量翻译
- 进入 设置 > 技术 > 用户界面 > 翻译 > 翻译条目
- 搜索目标字段(如模型、字段名),可直接批量编辑多语言内容
- 支持导入/导出、批量审核和 AI 翻译建议
10.3 AI 辅助翻译
- Odoo 18 支持 AI 自动翻译建议,批量处理字段内容,提升效率
- 可在翻译条目界面一键应用 AI 建议,再人工校对
10.4 手动标记与动态翻译
- 对于代码中动态生成的字段内容,可用
_(...)包裹字符串,确保被提取 - 例如:
from odoo.tools.translate import _
field_label = _('Special Offer')
10.5 常见技巧与注意事项
- 字段定义时加
translate=True,确保内容可被提取和翻译 - selection 字段的选项列表也支持多语言
- 帮助文本(help)同样支持自动翻译
- 避免硬编码,始终用可翻译字符串
- 多语言测试:切换用户语言,检查字段内容是否正确切换


通过理解和正确应用 Odoo 18 的翻译机制,开发者和管理员可以打造真正国际化的应用和网站,为全球用户提供本地化、专业的体验。

浙公网安备 33010602011771号