2

用这样的一句话:

"I visited this place {0} {1} ago."

While{0}代表整数,{1}分别是单词“year”或“years”。现在,在俄语中,“年”这个词不仅仅是单数或复数,而是取决于确切的数字(год-года-лет)。因此,任何仅区分“年”或“年”的规则对于俄语来说都是不够的。

现在,我需要的信息是:有没有办法在资源包或源代码中添加规则,保留整个字符串,或者我必须将字符串拆分为

"I visited this place {0} " + "{1} " + "ago."

...扩展源代码中的规则?你如何处理这样的问题?有没有最佳实践?

4

2 回答 2

3

i18n 的黄金法则

不要通过连接本地化字符串来产生本地化输出。曾经。出于任何原因。


在这里,您在一段较大的文本中插入本地化形式的“年/年”违反了此规则。对于您的具体示例,这很容易解决 - 只需将“N year(s)”作为一个整体本地化并插入那个代替 - 但这并不能真正解决问题。有些语言的结构甚至更依赖于上下文,这种方法在某些时候会致命地崩溃。

为了获得最佳结果,您应该将字符串作为一个整体进行本地化。对于俄语语言环境,字符串应该有 3 种不同的形式,具体取决于“years”参数的值(我不懂俄语,所以不知道哪种形式用于什么值)。

我不确定您使用的是什么 i18n 技术,但 gettext (问题被标记)支持这一点。

于 2013-02-11T12:40:21.723 回答
1

在某种程度上,您已经回答了您的问题。您不应该连接字符串。基本上,占位符可用于数字、日期和动态文本。
我认为度量单位(在这种情况下为时间)不是动态文本。

你如何解决这个问题?

我会给你一些关于两个想法的基本蓝图。两者都需要使用完整的句子。

  1. 您可以重新排列句子,这样您就不会遇到复数的问题,即“该地点已被访问过这个年数|月|天|小时|分钟前:{0}”。
    这有明显的缺点,听起来不自然。虽然我不能给你一个这个概念不起作用的语言例子,但这种语言存在的可能性非零(斯拉夫语言不在其中,这是肯定的。)

  2. 使用一些基于规则的选择方法从资源文件中选择有效的复数形式。为此,您只需要了解一些Language Plural Rules。基本上,您可以自己使用这些CLDR 规则,也可以决定其他内容,例如包装ICU4C 的 PluralRules类并使用其select 方法来很好地选择有效的复数形式。ICU 项目站点甚至列出了可以在 C# 应用程序中使用的现有包装器,即
    GenICUWrapperICU -Dotnet

就个人而言,我推荐后一种方法(使用 ICU 包装器)。您可能希望看到对 Java 解决方案类似问题的回答。我相信 .Net 将基于相同的想法,只有你会使用string.Format()而不是MessageFormat你会以 .Net 的方式阅读资源(无论你实际喜欢什么风格)。

于 2013-02-11T17:05:48.797 回答