在构建多语言网站或应用时,使用 gettext
工具链处理 .po
文件和 .pot
模板是标准流程。但随着项目规模扩大,你可能会发现 msgmerge
处理大文件非常慢,且翻译条目行为有些“诡异”:明明写了翻译,实际却显示原文。本文从开发者角度深入拆解这些坑,并提供一整套高效、可靠的处理方案。
典型工作流:
.pot
(通过 xgettext
).pot
与已有 .po
合并(通过 msgmerge
).po
.mo
文件供程序使用(msgfmt
)本文重点关注第 2 步:msgmerge 合并行为及其性能与正确性问题。
msgmerge
合并太慢,怎么办?当 .po
文件有成千上万个条目时,默认合并速度可能非常慢。原因在于:
msgid
做模糊比对;#, fuzzy
,需要人工审核。使用 --no-fuzzy-matching
可大幅提升速度,跳过所有模糊匹配逻辑,只保留精确匹配项:
msgmerge --no-fuzzy-matching old.po template.pot -o merged.po
fuzzy 是 gettext 系统的“翻译保守机制”:
"Save"
改为 "Save file"
),会尝试找到旧翻译;#, fuzzy
,表示 “可能对,但需要人类确认”。#, fuzzy
msgid "Save file"
msgstr "保存"
重点:fuzzy 条目不会在实际运行中生效,gettext 会忽略其 msgstr!
是的!特别适合以下场景:
推荐做法:
msgmerge --no-fuzzy-matching old.po template.pot -o merged.po
搭配清理工具:
msgattrib --no-obsolete merged.po -o clean.po
fuzzy 条目的运行行为再总结一下:
条目状态 | 实际显示内容 | 使用 msgstr 吗? |
---|---|---|
正常翻译 | 翻译内容 | ✅ 是 |
#, fuzzy 标记 | 原文(msgid) | ❌ 否 |
空的 msgstr | 原文(msgid) | ❌ 否 |
误解警告:我看有些文章,包括 AI 回复都是不对的。--previous
不会提升性能,反而略微拖慢。
实际作用是:
把旧的
msgid
作为注释保留下来,供翻译者参考。
例子:
#| msgid "Save"
msgid "Save file"
msgstr "保存文件"
适合在关闭 fuzzy 后仍保留一点上下文提示,但它会:
.po
文件体积仅建议用于人工翻译或 GUI 工具(如 Poedit)环境下。
msgid
会不会残留在 .po
文件里?是的,但是以“废弃条目”的形式存在:
#~ msgid "Save"
#~ msgstr "保存"
这些是 gettext 特有的 obsolete 条目,不会影响翻译,但会让 .po
文件臃肿。
可用 msgattrib
清理:
msgattrib --no-obsolete merged.po -o clean.po
msgattrib --no-obsolete merged.po -o merged.po # 是否可以?
不推荐!
虽然工具允许,但:
推荐更安全的做法:
msgattrib --no-obsolete merged.po -o tmp.po && mv tmp.po merged.po
或使用临时文件自动生成:
tmp=$(mktemp)
msgattrib --no-obsolete merged.po -o "$tmp" && mv "$tmp" merged.po
#!/bin/bash
set -e
OLD_PO=$1
POT=$2
OUT_PO=${3:-merged.po}
TMP_MERGED=$(mktemp)
TMP_CLEANED=$(mktemp)
# 合并并禁用 fuzzy
msgmerge --no-fuzzy-matching "$OLD_PO" "$POT" -o "$TMP_MERGED"
# 清理废弃条目
msgattrib --no-obsolete "$TMP_MERGED" -o "$TMP_CLEANED"
# 移动到目标文件
mv "$TMP_CLEANED" "$OUT_PO"
问题/目标 | 推荐做法 |
---|---|
合并过慢 | 使用 --no-fuzzy-matching |
想保留旧 msgid 提示信息 | 使用 --previous |
fuzzy 条目被显示为原文 | 清除 fuzzy 或人工确认后移除 fuzzy 标记 |
旧 msgid 仍留在文件中 | 使用 msgattrib --no-obsolete 清理 |
安全写入 .po 文件 | 输出到临时文件后 mv 覆盖 |
场景 | 是否关闭 fuzzy | 是否使用 previous | 是否清理 obsolete |
---|---|---|---|
个人项目 / 自动化 | ✅ 是 | ❌ 否 | ✅ 是 |
需要上下文提示 / GUI 翻译工具 | ❌ 否 | ✅ 是 | 可选 |
内容频繁变化 / 快速迭代项目 | ✅ 是 | 可选 | ✅ 是 |
专业翻译团队 / 翻译一致性要求 | ❌ 否 | ✅ 是 | 可选 |
如果你正在构建国际化支持的 CI/CD 流程、开发自动翻译工具链、或者维护一个翻译量大的项目,希望这篇文章能为你节省大量时间,并避免一些不易察觉的陷阱。