在我们支持的 42 种语言中,有 14 种语言的复数类别“one”并不仅用于数字 1
语言
应用中的字符串“今日还剩一个习惯”有一个复数对应项“今日还剩 %d 个习惯”。Android 根据类别在两者之间进行选择:英语中“one”用于 1,“other”用于其他所有数字。在俄语中,类别“one”用于 1、21、31、41 等。我们的翻译检查在同一天两次出错,每次方向相反。
它拒绝的正确翻译
11 月 2 日,我们再次在示例应用上运行翻译套件。对于俄语的“one”,模型写入了“Осталась %d привычка на сегодня”:“今日还剩 %d 个习惯”,其中包含数字。我们的检查将其与英语的“one”形式进行比较,发现了一个英语中没有的 %d,并将其作为虚构的占位符拒绝。模型是正确的。剩余 21 个习惯的用户会使用此形式,因此它必须显示数字。我们更改了检查规则:形式可以添加英语“other”形式中使用的计数。下一次运行写入了示例应用的全部 350 个字符串。
它本应通过的错误翻译
同样的检查却放行了相反的情况。如果模型写入了“Осталась одна привычка”(“还剩一个习惯”),字符串中没有丢失任何内容,因此通过了检查,而剩余 21 个习惯的用户会被告知他们只剩一个。旧规则允许任何“one”形式省略数字,因为在英语中“one”仅指 1。
现在,检查机制知道每个类别涵盖哪些数字,这来自 CLDR,即 Android 和 ICU 使用的 Unicode 复数规则。涵盖多个数字的类别形式必须显示数字。仅涵盖单个数字的形式可以省略它:德语的“one”仅指 1,因此“Noch eine Gewohnheit”在那里是可以接受的。
“one”不仅指 1 的情况
在 Babel 2.10 中的 CLDR 数据所知的 41 种目标语言中,有 14 种语言的“one”涵盖的数字不止 1:
- 1、21、31、41……:俄语、乌克兰语、塞尔维亚语、马其顿语。
- 0 和 1:法语、葡萄牙语、波斯语、亚美尼亚语、卡纳达语、旁遮普语、阿姆哈拉语。“Une habitude restante”将用于 0 个习惯。
- 1 和 11:苏格兰盖尔语。1、101、201……:斯洛文尼亚语,其“two”也涵盖 102 和 202。
- 所有不以 4、6 或 9 结尾的数字:菲律宾语。
在 ICU 消息中,其自身的分支会改变这一点。如果在消息中使用 =0{…},法语的“one”将仅保留 1,检查机制会考虑到这一点。
对照 Android 自身的字符串进行检查
在发布这条规则之前,我们在 Android 框架字符串中的复数消息上运行了它:涵盖我们 39 种语言的 897 条翻译。它没有发现任何问题。Google 的译者在涵盖多个数字的每个分支中都放入了数字,包括俄语的“单数”分支,即使英语为数字 1 单独设置了一个分支。当我们手动从俄语的一个“单数”分支中移除数字后,检查结果显示该形式也用于 21、31、41 和 51。
该规则已包含在 translation-checks 1.2.0 中,可在 GitHub 上免费获取,适用于 ICU 消息;同时也包含在 Polyglot 1.2.0 中,适用于 Android 复数形式和 ICU 消息。本周我们添加的其他检查项请参见关于其他文字字母的说明。