功能插件定价资源
更改语言
资源.po vs .mo vs .pot: WordPress 翻译文件详解

.po vs .mo vs .pot: WordPress 翻译文件详解

SimplePoTranslate Team2026年4月21日
.po vs .mo vs .pot: WordPress 翻译文件详解

当你打开一个 WordPress 主题的 languages 文件夹时,你会发现三个看起来几乎相同的文件:twentytwentyfour.pottwentytwentyfour-de_DE.potwentytwentyfour-de_DE.mo。同一个主题,同一种语言,却有三种不同的文件扩展名。你应该编辑哪一个?WordPress 实际加载的是哪一个?为什么编辑错误的文件会让你的翻译悄无声息地消失?

如果你曾问过在 .po 与 .mo 文件 的争论中哪个文件更重要,那么你并不孤单。这三种文件扩展名是每个翻译 WordPress 网站的支柱,然而它们之间的区别却让新手和经验丰富的开发者都感到困惑。编辑错误的文件,你的德国访客仍然会看到英文。即使编辑了正确的文件,但跳过了一个步骤,结果也同样没有任何改变。

本指南将详细解释 .pot.po.mo 文件分别是什么,它们在 GNU Gettext 工作流程中如何关联,它们在 WordPress 中的存放位置,以及为什么你永远不应该用文本编辑器打开 .mo 文件。读完本文,你将知道应该修改哪个文件,以及应该对哪个文件敬而远之。

什么是 .pot、.po 和 .mo 文件?

简而言之:.pot 文件是空白模板,.po 文件是可编辑的翻译文件,而 .mo 文件是 WordPress 在运行时读取的编译二进制文件。它们形成一个链条,每个环节都只有一个明确的任务。

这三种格式都源于 GNU Gettext,它是 WordPress、Drupal 以及数千个 PHP 和 C 项目所依赖的本地化系统。Gettext 将开发者编写的 源字符串 与翻译人员提供的 译文 分离,因此相同的代码库可以支持数十种语言,而无需修改一行 PHP 代码。

把它想象成一张菜谱卡。.pot 是带有配料槽但没有具体数量的空白卡片。.po 是为一道特定菜肴填写好的卡片。.mo 是厨房在服务期间实际使用的、经过层压处理、机器可扫描的副本。你在纸质卡片上书写;你绝不会在层压卡片上乱涂乱画。

.pot 文件:主模板

一个 .pot 文件(Portable Object Template)包含主题或插件中所有可翻译的字符串,但译文部分留空。它是开发者发布的主列表,以便翻译人员清楚地知道哪些内容需要翻译。msgstr 行是空白的,因为尚未选择任何语言。

#: includes/checkout.php:42
msgid "Add to Cart"
msgstr ""

#: includes/account.php:108
msgid "Your order has been shipped to %s"
msgstr ""

请注意空的 msgstr "".pot 是一个模板,而不是翻译。你需要为每种语言复制一份,然后填入空白。你很少会手动编辑 .pot 文件;每当字符串发生变化时,它都会从源代码重新生成。

.po 文件:您可人工编辑的翻译

一个 .po 文件(Portable Object)是 .pot 文件的副本,其中 msgstr 行已填充为一种语言的译文。这是翻译人员和开发者实际编辑的文件。它是纯文本,人类可读,并且对版本控制友好。

#: includes/checkout.php:42
msgid "Add to Cart"
msgstr "In den Warenkorb"

#: includes/account.php:108
msgid "Your order has been shipped to %s"
msgstr "Ihre Bestellung wurde an %s versandt"

msgid 是原始的英文源字符串,绝不能更改。msgstr 是你的译文。%s 是一个占位符,在翻译中必须保持原样——遗漏或重新排序它是导致布局损坏的最常见原因,我们将在如何翻译 PO 文件而不破坏代码变量中深入探讨。

.mo 文件:编译后的二进制文件

一个 .mo 文件(Machine Object)是你的 .po 文件编译后的二进制版本。WordPress 在运行时无法高效读取 .po 文件,因此它会加载预编译的 .mo 文件。在文本编辑器中打开 .mo 文件会显示不可读的字节——它设计用于机器,而非人类。

当 WordPress 调用 load_textdomain()load_theme_textdomain() 时,它会查找 .mo 文件,解析其二进制哈希表,并即时将每个 msgid 替换为匹配的 msgstr。这种二进制格式使得即使在拥有数千个字符串的网站上,查找也十分迅速。

这三种文件在 Gettext 工作流程中如何关联?

它们形成一个单向管道:源代码生成 .pot 文件,.pot 文件转换为每种语言的 .po 文件,然后每个 .po 文件编译成 .mo 文件。翻译总是沿着这个方向流动。

以下是完整的生命周期顺序:

  1. 开发者将面向用户的字符串用 Gettext 函数(如 __()_e())包装在 PHP 源代码中。
  2. 扫描工具读取源代码并生成包含所有包装字符串的 .pot 模板。
  3. 翻译人员将 .pot 文件复制到特定语言的 .po 文件中(例如 de_DE.po),并填入每个 msgstr
  4. 完成的 .po 文件被编译成二进制 .mo 文件。
  5. WordPress 在运行时加载 .mo 文件并显示翻译后的网站。

当开发者稍后添加新字符串时,.pot 文件会重新生成,新条目会合并到每个现有的 .po 文件中(保留旧译文),翻译人员填补空白,然后 .po 文件会重新编译为 .mo 文件。这个循环在项目的整个生命周期中重复进行。

关键要点:你编辑 .po 文件,然后编译成 .mo 文件。 你绝不直接编辑 .mo 文件,也绝不在 .pot 文件中进行翻译。如果你想了解更深入的端到端全貌,WordPress 本地化终极指南将通过示例详细介绍整个流程。

命名约定和文件存放位置

WordPress 对文件名有严格要求。如果命名错误,你完美翻译的 .mo 文件将被简单地忽略,因为 WordPress 会根据 文本域 (text domain)语言环境 (locale) 查找精确匹配的文件。

主题和插件翻译的命名模式是:

# Pattern: textdomain-locale.po / .mo
twentytwentyfour-de_DE.po      # German (Germany) translation
twentytwentyfour-de_DE.mo      # compiled binary WordPress loads
twentytwentyfour-fr_FR.po      # French (France)
twentytwentyfour.pot           # template, no locale suffix

textdomain 与传递给 Gettext 函数(如 __( 'Add to Cart', 'twentytwentyfour' ))的第二个参数字符串匹配。locale 是一个 WordPress 语言环境代码,例如 de_DEfr_FRpt_BR.pot 模板没有语言环境后缀,因为它与语言无关。

文件位置与命名同样重要。WordPress 会搜索一些可预测的路径:

  • 主题翻译 位于主题自己的 wp-content/themes/your-theme/languages/ 文件夹中。
  • 插件翻译 位于 wp-content/plugins/your-plugin/languages/ 中。
  • 来自 translate.wordpress.org 的翻译 和用户自定义的覆盖文件会存放在全局的 wp-content/languages/themes/wp-content/languages/plugins/ 目录中,这些目录具有优先权并能在更新后保留。

将正确命名的 de_DE.mo 文件放入正确的文件夹,德国访客就会看到德语。如果将其放在错误的子文件夹中,或者拼错了文本域,WordPress 将静默地回退到英语,而不会显示任何错误消息。如果你的翻译没有显示,通常是命名或路径不匹配的问题,WordPress 翻译缺失故障排除指南涵盖了所有常见原因。

为什么您绝不应该直接编辑 .mo 文件

因为 .mo 文件是编译后的二进制文件,所以无法安全地手动编辑它——而且你强制进行的任何更改都将在下次 .po 文件重新编译时被覆盖。.po 文件是真相的来源;.mo 文件是可丢弃的构建产物。

这一条规则解释了很大一部分“我的翻译改了但网站没有更新”的工单。有人调整了一个字符串,保存了 .po 文件,却忘记重新编译 .mo 文件。WordPress 继续加载旧的二进制文件,因此新的措辞从未出现。解决方案总是:编辑 .po 文件,重新编译为 .mo 文件,然后重新加载。

这条规则重要的第二个原因是:.mo 文件在版本控制中不便于进行差异比较 (diff)。因为它们是二进制文件,即使是微小的措辞更改也会在你的 Git 历史中产生一个不透明的数据块,任何审阅者都无法阅读。将 .po 文件作为可跟踪的真实来源,并将 .mo 文件视为生成产物,可以使你的仓库可审阅,并使你的翻译可审计。

手动对几十种语言进行此操作既繁琐又容易出错。这就是云端工作流程节省时间的地方。像 SimplePoTranslate 这样的工具会翻译你的 .po 字符串,并返回一个包含匹配的 .po.mo 文件 的 ZIP 包——它们已经编译好,命名正确,可以直接放入 wp-content/languages/。无需手动编译,也避免了出现过时的 .mo 文件的可能性。

它还应用了 语法锁定 (Syntax Locking) 功能,在翻译之前冻结所有占位符,如 %s%1$s{name},以及 HTML 标签。你的变量将完好无损,因此你绝不会交付一个会破坏布局的 .mo 文件。而且由于它完全在云端运行,所以不会有额外的插件拖慢你的网站——你只需上传文件,即可下载完成的、编译好的翻译文件。

总结

一旦你理解了 .po 与 .mo 文件 之间的区别,整个 WordPress 翻译系统就不再神秘了。.pot 是开发者的模板,.po 是翻译人员可编辑的工作副本,而 .mo 则是 WordPress 实际提供给访客的编译二进制文件。翻译流向是单向的——从模板到 .po 再到 .mo——你只需要手动编辑中间的那个文件。

记住这三条可以避免百分之九十翻译难题的规则:绝不翻译 .pot 文件内部的内容,编辑 .po 文件后务必重新编译 .mo 文件,并精确匹配 textdomain-locale 的命名。遵循这些规则,你的翻译字符串每次都会正确显示。

准备好不再手动编译和命名翻译文件了吗?免费试用 SimplePoTranslate——无需信用卡。上传你的 .po.pot 文件,几分钟内即可在免费套餐中获得一个即用型的 .po + .mo 文件包。