第二十三章 翻译与国际化
篇别:第三篇 数据库与数据管理
本章学习目标
- 能在 Python/XML 中正确使用
_()与 导出/导入 .po。 - 理解 可翻译字段(
translate=True)在 数据库中的存储(含 JSONB 演进)。 - 能通过
context切换语言 读取与生成 多语言内容。 - 能规划 网站、报表、邮件 的多语言策略。
导读:国际化不是「事后翻译」
从第一天起:用户可见字符串 应 可提取;动态用户内容 不应包进 _()。字段 translate=True 使 同一记录 在不同 lang 下显示不同 name/description,存储形态随版本演进。
23.1 _() 函数
23.1.1 知识要点
from odoo import _
- 静态英文(或源语言) 作为 msgid;
.po提供各语言 msgstr。 - 格式化:
_('最多 %s 天') % n或 Python 3.14 前 注意 % 与 gettext 的交互;亦可用.format(注意翻译语序)。 - 勿翻译:用户昵称、SKU、日志中的原始 JSON。
23.1.2 案例
raise UserError(_('借阅天数不能超过 %s 天') % max_days)
selection = [
('draft', _('草稿')),
('done', _('完成')),
]
23.1.3 截图占位

23.1.4 本节练习
- 改错:
_(partner.name)是否合理? - 实操:新增一条 中文 界面可见字符串,导出
zh_CN.po并填译。 - 简答:f-string 与
_()组合时的常见陷阱?
参考答案提示:1. 不合理,name 是数据不是 UI 源文。3. 翻译无法提取静态句柄。
23.2 .po 文件
23.2.1 知识要点
- 路径:
i18n/zh_CN.po、i18n/de.po等。 - 条目:
msgid/msgstr、fuzzy标记。 - 合并:升级后
msgmerge或 Odoo 重新导出。
23.2.3 截图占位

23.2.4 本节练习
- 实操:用 Poedit 打开
zh_CN.po,保存并 导入 到数据库。 - 简答:
fuzzy条目的含义?
23.3 翻译导入导出与 CI
23.3.1 知识要点
- CLI / 界面:加载翻译、覆盖模式。
- CI:检测 未翻译(
msgstr "")、过时fuzzy。
23.3.2 本节练习
- 简答:如何在 GitHub Actions 中跑一条 gettext 检查(思路即可)?
23.4 JSONB 翻译存储(新增)
23.4.1 知识要点
自较新版本起,部分 translate=True 字段在 PostgreSQL 中以 JSONB 存多语言 键值(en_US、zh_CN 等)。
SQL 报表 需 ->> 取指定语言或 回退逻辑。
23.4.3 截图占位

23.4.4 本节练习
- 简答:ORM
read返回的 可翻译 Char 与 DB 原始列差异? - 实操:
psql中SELECT name FROM ... LIMIT 1观察 JSON 形态(测试库)。
23.5 Environment 翻译 API(新增)
23.5.1 知识要点
使用 with_context(lang='xx_XX') 切换:
for lang in ['en_US', 'zh_CN']:
name = book.with_context(lang=lang).name
env._ 等环境级翻译(以 19.0 文档为准)。
23.5.3 截图占位

23.5.4 本节练习
- 实操:同一图书在 中英文 下
name字段 显示不同(需translate=True与两条翻译)。 - 简答:报表 PDF 固定为 公司账套语言 的实现思路?
本章综合练习
- 方案:报表 PDF 语言 = 用户偏好 vs 公司默认,列表 利弊。
- SEO:网站
hreflang与 Odoo 多网站/多语言 关系(拓展阅读笔记)。 - 质量:建立团队 「禁止硬编码中文在 Python」 的 review 规则一条。
- 数据库:写出 SQL 从 JSONB
name取zh_CN的伪代码。
本章对应白皮书目录:第二十三章 翻译与国际化。