跳转至

面向翻译者

本页写给编辑目录的人,而不是编写代码的人。它刻意保持简短,也适合直接链接或 复制进某个项目自己的翻译者说明。

这里的内容不要求你会读 Python。全部内容只围绕一件事:消息中被花括号包住的 那些片段。

什么是占位符

目录中的消息里可能包含被花括号包住的名称:

msgid "Hello {name}"
msgstr ""

{name} 就是一个占位符。程序显示这条消息时,会把 {name} 替换成它提供的 某个值——人名、文件名或数字。占位符不是需要翻译的词,而是一个空位。

你的译文写在 msgstr 里,并且必须保留那个空位:

msgid "Hello {name}"
msgstr "こんにちは {name}"

哪些可以改,哪些不能改

可以

  • 移动占位符,放到目标语言语法需要的任何位置,包括句首。
  • 重复占位符,如果该语言需要用到这个值两次。
  • 改写其余每一个词,包括标点、空格和句子顺序。

不可以

  • 翻译花括号里的名称。 {name} 始终是 {name},即使在其余部分完全不使用 拉丁字母的语言里也是如此。
  • 删掉花括号,或者不加花括号直接写这个名称。
  • 把 ASCII 花括号 { } 换成全角的 很多输入法产生的是全角 形式;它们看起来几乎一模一样,却无法工作。
  • 添加格式,例如 {name!r}{amount:.2f}。值如何显示由程序决定, 而不是由目录决定。
  • 凭空造一个 msgid 中没有的占位符。

如果某条消息需要一个原文并未提供的值,那就是开发者需要修改的消息。请直接提出 来,而不要想办法绕过去。

复数形式

带计数的消息会为你的语言的每一种复数形式提供一个 msgstr 空位,而空位的数量 由你的语言决定——日语一个,德语两个,俄语三个,阿拉伯语六个。目录给出多少个 空位,就把它们全部填满。

有两条规则常常让人栽跟头:

  • 这些空位不是“单数、复数、更多的复数”。 每个下标的含义由你的语言的复数 规则决定。拉脱维亚语的第三种形式专用于零;斯洛文尼亚语的第二种形式专用于 恰好两个;威尔士语把一般情形放在下标 0,把单数放在下标 1。
  • 两个空位里放同样的文本是合理的。 在土耳其语、匈牙利语、波斯语和孟加拉语 中,名词跟在数词之后仍保持单数,因此带计数消息的两种形式就是同一个字符串。 那是正确的,不是复制粘贴出的疏漏。

上面的占位符规则对每一种形式分别生效。

fuzzy 条目

标记为 fuzzy 的条目是机器的猜测:开发者修改了原消息,工具把新文本与你的旧 译文配成一对,好让你有个起点。

#, fuzzy
msgid "Welcome back, {name}"
msgstr "こんにちは {name}"

fuzzy 条目不会被程序使用——程序显示的是未翻译的原文——直到有人修订文本并 移除 fuzzy 标记为止。大多数 PO 编辑器都有一个专门做这件事的按钮。

阅读错误消息

工具会在编译目录时检查占位符,而这些消息是写给你的,不是写给程序员的。如果 你眼前明明能看到那些字符,只报告 {name} 缺失并没有帮助。因此,当占位符看似 存在、实际却无效时,消息会说明原因。对于原文 Hello {name},下列每种情况都会 在 translation does not match the source placeholders: 后给出对应说明:

你的译文写成 给出的原因
こんにちは {name} {name} is missing (the braces around it are not the ASCII { and })
こんにちは {{name}} {name} is missing (it is written {{name}}, which is how a literal brace is escaped)
こんにちは name {name} is missing (the name appears, but not inside braces)
こんにちは {名前} {name} is missing; {名前} is not in the source message

不可见字符会得到专门处理。输入法可能在花括号中产生 no-break space,而编辑器不会 显示它。因此消息会打印 code point,而不是让你去寻找一个根本找不到的字符:

placeholder {<U+00A0>name} has a space inside the braces; write {name}

名称混用不同书写系统时——例如 Cyrillic а 与 Latin 字母外观完全相同的 homoglyph 情况——会同时显示可读形式和转义形式,只有后者能揭示两者的差别:

translation does not match the source placeholders: {name} is missing;
{nаme} (n\u0430me) is not in the source message

当完全用 Greek 或 Cyrillic 写成的名称与 ASCII 源名称冲突时也会这样处理,包括 单字符 Latin a / Cyrillic а 的情况。

如果你遇到其中某一种而又不清楚该怎么改,最稳妥的做法是删掉自己输入的占位符, 直接从 msgid 里复制一份过来。

这些检查做不到什么

工具能验证你的占位符完好无损。它无法判断译文是否准确、是否自然、是否契合上下文 ——那完全取决于你。

有两件事比任何检查都更有帮助:

  • 阅读翻译者注释。 消息上方以 #. 开头的那一行,是开发者在告诉你它出现在 哪里、含义是什么。
  • msgctxt 提问。 同一个词带着不同上下文出现两次,正是因为两者需要译得 不一样——比如作为按钮的 “Open” 和作为状态的 “Open”。