如何翻译PO文件而不影响应用程序运行

OpenL Team 2026/7/3
如何翻译PO文件而不影响应用程序运行

目录

PO 文件看起来像普通文本文件,但一旦翻译的 %s 出错、遗漏复数形式或修改了 msgid,你的应用就可能崩溃。请按照以下流程翻译面向用户的字符串,同时保持 gettext 结构不变。

不要把整个文件粘贴到普通文本翻译器里。PO 文件属于源码相关文件:其中的词语可以翻译,但文件结构、占位符、注释和复数索引必须保持不变。

方法一:使用 PO 文件翻译工具

如果你想要最快速且安全的初稿,并且不想手动编辑 msgid / msgstr 对,应选择此方法。

  1. 备份原始 .po 文件。 在发送给翻译人员之前,务必在你的代码库中保留一份干净的副本。如果翻译后的文件出现问题,你需要一个已知无误的版本进行比对。

  2. 打开支持 PO 的翻译工具。 使用专为 gettext 文件设计的工具,例如 OpenL PO Translator,这是一个按需付费的文档翻译工具。PO 文件专用工具会翻译目标字符串,同时保留源字符串、注释、占位符和文件结构。如果你还在选择工具,可以参考我们的 最佳 PO 文件翻译工具指南进行比较。

  3. 上传 .po 文件。 使用包含 msgid 和 msgstr 的语言文件。如果你只有 .pot 模板,先根据模板创建目标语言的 .po 文件,然后再上传该 .po 文件。

  4. 选择源语言和目标语言。 源语言要与 msgid 内的文本一致,而不是你的管理界面语言。例如,如果文件中的 msgid 是英文,而你需要西班牙语输出,则选择英文到西班牙语。

  5. 下载翻译后的文件。 按你的框架要求的本地化命名规范保存文件。WordPress 插件通常采用文本域加语言代码的命名方式,而 Django 通常将文件存放在 locale/<language>/LC_MESSAGES/ 目录下。

  6. 优先检查风险字符串。 在翻译文件中搜索 %、{、}、<、>、msgid_plural、msgctxt 和 #, fuzzy。这些条目最容易影响运行时行为。

  7. 在应用中测试翻译文件。 本地加载该语言,并逐一点击使用翻译字符串的界面。PO 文件并不是翻译完成就算结束;只有在应用依然能正确渲染时才算真正完成。

方法二:在 Poedit 中翻译 PO 文件

当你需要人工审核、WordPress 兼容性或逐条细致翻译流程时,选择此方法。

  1. 在 Poedit 中打开文件。 Poedit 是专为 PO 及其他本地化格式设计的翻译编辑器;基础编辑器免费,付费专业版适合更复杂的工作流程。对于 WordPress,官方 Polyglots 手册说明 Poedit 可以根据 POT 文件创建 .po 和 .mo 文件,并支持复数形式和 UTF-8 编码。

  2. 如果源文本有变,先用 POT 模板更新。 如果开发者修改了应用文本,在翻译前先用最新的 .pot 文件更新 .po 文件。这样可以让新增、删除和模糊字符串都可见,避免悄悄发布过时的界面文本。

  3. 只翻译 msgstr 字段。 msgid 是应用用于查找翻译的源字符串。在标准 gettext 工作流程中,译者只需编辑 msgstr,不要修改 msgid。

  4. 严格保持占位符不变。 不要翻译或更改变量如 %s、%d、%1$s、{name}、%(count)s、:name 或 HTML 标签。如果需要调整语序,请整体移动占位符。

  5. 复数形式需分别翻译。 复数条目包含 msgid、msgid_plural 和多个 msgstr[n] 值。请根据目标语言填写每个复数项,不要简单复制同一句话到所有位置。

  6. 保存并编译 .mo 文件(如果你的应用需要)。 有些技术栈在开发阶段会直接读取 .po 文件,但 WordPress 和许多 gettext 环境在运行时使用编译后的 .mo 文件。Poedit 可以在保存时自动编译 .mo 文件;Django 可以通过 django-admin compilemessages 命令编译消息文件。

  7. 在上传前解决所有警告。 在 Poedit 中,警告图标通常提示占位符损坏、变量缺失或复数形式不匹配。在将翻译导入 WordPress、Django、Drupal 或你的发布分支之前,务必修复这些问题。

方法三:使用本地化平台

当有多位译者、审校人员或发布经理需要协作处理同一个 PO 文件时,建议选择这种方式。

  1. 将 PO 文件导入支持 gettext 的平台。 Weblate 等本地化平台支持 PO 文件工作流。团队本地化平台通常是付费产品,不过 Weblate 也提供开源自托管选项。它们对注释、头部信息、模糊字符串和占位符的处理方式各有不同,上传生产文件前请先检查格式设置。

  2. 设置占位符和标签检查。 启用针对 printf 风格占位符、命名变量、HTML/XML 标签和复数形式的 QA 规则。这些检查能发现普通拼写检查无法检测的错误。

  3. 保持开发者注释可见。 PO 文件中的注释可以包含上下文信息,如源代码引用、开发者提取的备注、标记和之前的源字符串。当遇到像“Open”这样简短的界面标签时,译者需要这些备注来判断它是动词、形容词还是菜单命令。

  4. 结合审校使用翻译记忆库。 翻译记忆库对于重复的界面字符串很有用,但它可能会将旧翻译复制到新的上下文中。当 msgctxt、源引用或周边界面发生变化时,要审查复用的字符串。

  5. 导出 PO 文件并进行本地检查。 不要盲目相信导出的文件。将翻译文件重新放回应用中,必要时编译,并在合并前测试界面。

PO 文件绝对不能违反的规则

PO 项目是否翻译?安全示例为什么重要
msgid否msgid "Save changes"应用程序在许多 gettext 工作流程中使用此源字符串作为查找键。
msgstr是msgstr "Guardar cambios"这是用户看到的目标语言文本。
msgctxt否msgctxt "button"上下文用于区分相同的源字符串。
%s, %d, %1$s否Hello, %s -> Hola, %s运行时代码会用实际值替换这些占位符。
{name}, %(count)s, :name否Welcome, {name}命名变量必须与应用代码保持一致。
HTML 标签通常不翻译<strong>Warning</strong>只翻译文本,不要改动标签语法。
msgid_plural否msgid_plural "%d files"源复数属于原始代码路径。
msgstr[0], msgstr[1]是,但需谨慎msgstr[0] "%d file"每种目标语言都有自己的复数规则。
#, fuzzy需先审核#, fuzzyfuzzy 表示翻译可能已过时或未确认。
#. 开发者注释通常不翻译#. Button label这些注释帮助译者理解上下文。

快速示例:安全与错误的 PO 翻译

以下是一个常规的 gettext 条目:

#. %s 是用户的显示名称。
#, c-format
msgid "Welcome back, %s"
msgstr ""

安全的西班牙语翻译会保持 %s 不变:

#. %s 是用户的显示名称。
#, c-format
msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, %s"

错误的翻译则改动了占位符:

msgid "Welcome back, %s"
msgstr "Bienvenido de nuevo, % s"

这个微小的空格可能会造成问题。GNU msgfmt --check-format 就是用来检测格式字符串不匹配,比如错误的 % 占位符,Poedit 也会提醒常见的占位符问题。想了解更多需要保持不变的字符串,请参考我们的 不可翻译内容指南。

如何检查已翻译的 PO 文件

  1. 如果你已安装 gettext,请运行 gettext 校验。
msgfmt --check --check-format -o /tmp/messages.mo path/to/messages.po

此命令会检查语法、头部信息和格式字符串,并在文件有效时生成一个临时编译目录。

  1. 按照你的框架要求编译文件。
django-admin compilemessages

对于 Django 项目,compilemessages 会将由 makemessages 创建的 .po 文件编译成 .mo 文件,以支持 gettext。

  1. 查找空翻译项。
grep -n 'msgstr ""' path/to/messages.po

空的 msgstr 字段可能是故意保留未翻译,但在发布时不应让你感到意外。

  1. 查找模糊翻译。
grep -n '#, fuzzy' path/to/messages.po

模糊翻译在发布前应由人工审核。默认情况下,msgfmt 不会使用模糊翻译,除非你编译时加上 --use-fuzzy,因此模糊项在最终目录中会表现为未翻译字符串。

  1. 测试真实界面。 打开包含表单、复数计数、错误信息、账户菜单和支付流程的页面。PO 文件校验能发现文件问题,只有界面测试才能发现措辞不自然、内容溢出和上下文缺失等问题。

应该使用哪种方法?

情况最佳方法原因
你需要为单个 PO 文件快速生成初稿PO 文件翻译器保持结构的最快路径
你维护 WordPress 插件或主题Poedit熟悉的 WordPress 工作流程,支持 .mo 编译
你维护 Django 应用PO 翻译器或 Poedit,然后运行 compilemessages翻译可以很快完成,但框架编译仍然必需
你有多种语言和多个审核人员本地化平台更好的分配、历史记录、质量控制和审核管理
你在翻译面向开发者的字符串机器翻译后人工审核代码术语、占位符和上下文更为重要
你还要本地化 JSON 或前端 i18n 文件使用针对格式的工作流程PO 规则并不总适用于 JSON、YAML 或 ICU 消息

如果你的项目同时使用 gettext PO 文件和 JSON 语言文件,请分别用能理解其结构的工具进行翻译。PO 文件以 msgid 和 msgstr 为核心;JSON 本地化则围绕键和值展开。相关工作流程请参考我们的2026 年最佳 JSON 翻译工具指南。

常见问题

我可以用 Google Translate 翻译 PO 文件吗?

你可以将单个 msgstr 内容复制到通用翻译器中,但将整个 PO 文件上传或粘贴到纯文本翻译器存在风险。通用翻译器可能会修改 msgid、注释、引号转义、复数索引或占位符。建议使用支持 PO 格式的翻译器、Poedit 或本地化平台。

.po、.pot 和 .mo 有什么区别?

.pot 是从源代码提取的模板,通常只包含原始字符串,不含翻译内容。.po 是针对某种目标语言的可编辑翻译文件。.mo 是编译后的二进制目录,许多基于 gettext 的应用在运行时加载它。

我应该翻译 msgid 吗?

不,正常的工作流程中不会这样做。请翻译 msgstr。GNU gettext 手册将 msgid 描述为原始未翻译字符串,而 msgstr 是翻译内容;msgid 字符串由 gettext 工具生成和管理。

如何检查 PO 文件是否有效?

如果你安装了 gettext,可以运行 msgfmt --check --check-format,也可以用 Poedit 打开文件,或者使用你的本地化平台的 QA 检查功能。之后,将文件编译并在应用内测试。校验是必要的,但不能替代 UI 测试。

如果我破坏了占位符会发生什么?

最好的情况是应用显示一个奇怪的字符串。更糟糕的是,运行时格式化器会抛出错误,因为翻译后的字符串不再与代码传入的变量匹配。占位符只能作为完整的标记移动,绝不能翻译或部分编辑。

OpenL 能翻译 PO 文件吗?

可以。OpenL PO Translator 专为 gettext .po 文件设计,并声明在翻译超过 100 种语言时会保持占位符和变量不变。它采用按需付费的文档翻译流程,因此当你更看重保留 PO 结构而不是手动处理时,可以用它快速生成初稿。如果你只有 .pot 模板,请先创建目标语言的 .po 文件再使用 OpenL。

参考资料