第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 导出翻译模板

  1. 后台:设置 > 翻译 > 导入/导出 > 导出翻译
  2. 选择 PO 文件格式、目标模块,导出 .pot 模板
  3. 用 POEdit、msginit 或文本编辑器编辑,生成目标语言 .po 文件
  4. 放入模块 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. 最佳实践与实用建议

  1. 保持翻译文件组织:所有翻译文件应放在正确的 i18n/ 目录,遵循命名规范。
  2. 定期更新翻译:模块更新后及时补充新字符串的翻译。
  3. 格式化字符串注意:始终标记原始格式字符串。
  4. 避免硬编码:代码中显示文本应可翻译。
  5. 上下文注释:为复杂或多义字符串添加注释,便于翻译者理解。
  6. 多语言测试:发布前测试不同语言下的界面和功能。
  7. UI 适配:注意不同语言下文本长度变化对界面的影响。
  8. AI 辅助+人工审核:大批量内容可用 AI 辅助,但需人工校对。
  9. 社区协作:善用 Odoo 官方翻译平台和社区资源,提升翻译质量。
  10. 自动化工具:结合 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 注意事项

  1. 模板文件需放在 Odoo 识别的目录(如 views/report/mail/ 等)。
  2. 不要硬编码字符串,应始终用 _(){% trans %} 包裹。
  3. 自定义 Jinja2 渲染时,需确保渲染上下文中包含 _ 函数,并且当前语言已设置到上下文(Odoo 默认已处理)。
  4. QWeb 和 Jinja2 模板的翻译提取机制略有不同,但都统一到 Odoo 的 PO 文件体系。

9.4 参考资料

结论:只要在 Jinja2 模板中用 Odoo 推荐方式标记可翻译字符串,Odoo 就能自动提取、管理和渲染翻译内容,适用于网站、报表、邮件等多种场景。


10. 字段内容的快速翻译方法

Odoo 支持对模型字段(如名称、描述、帮助等)内容进行高效的多语言翻译,常见方法如下:

10.1 自动提取与 PO 文件翻译

  • 自动提取:Odoo 会自动扫描所有设置了 stringhelpselection 等属性的字段(未设置 _translate = False),并将其内容导出到 PO 文件。
  • 操作步骤
    1. 后台:设置 > 翻译 > 导入/导出 > 导出翻译,选择目标模块和语言,导出 PO 文件。
    2. 用 POEdit 或文本编辑器填写 msgstr,保存后放回模块 i18n/ 目录。
    3. 重新加载翻译或升级模块,字段内容即可多语言切换。

代码示例(模型定义):

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 的翻译机制,开发者和管理员可以打造真正国际化的应用和网站,为全球用户提供本地化、专业的体验。

posted @ 2025-06-05 13:57  何双新  阅读(396)  评论(0)    收藏  举报