这样的句子:
"I visited this place {0} {1} ago."
虽然{0}
代表整数,但{1}
分别是“年”或“年”。
现在,在俄语中,“年”这个词不仅仅是单数或复数,而是取决于确切的数字(год-года-лет)。因此,任何区分“年”或“年”的规则对俄语来说都是不够的。
现在,我需要的信息是:有没有办法在资源包或源代码中添加规则,保留整个字符串,或者我必须将字符串拆分为
"I visited this place {0} " + "{1} " + "ago."
...在源代码中扩展规则?你怎么处理这样的问题?有没有最好的做法?
答案 0 :(得分:3)
不要通过连接本地化字符串来生成本地化输出。永远。出于任何原因。
在这里,您通过在较大的文本中间插入“年/年”的本地化形式来违反此规则。对于您的具体示例,这很容易解决 - 只需将“N year(s)”作为一个整体进行本地化并插入一个 - 但这并不能真正解决问题。有些结构的语言更依赖于上下文,这种方法在某些时候会致命地崩溃。
为了获得最佳效果,您应该将字符串作为一个整体进行本地化。对于俄语语言环境,字符串应该有3种不同的形式,具体取决于“years”参数的值(我不知道俄语,所以不知道哪种形式会用于什么值)。
我不确定您使用的是哪种技术,但gettext(问题标记为)支持开箱即用。
答案 1 :(得分:1)
在某种程度上,您已经回答了您的问题。你不应该连接字符串。基本上,占位符可用于数字,日期和动态文本 我认为测量单位(在这种情况下是时间)是 不 动态文本。
如何解决此问题?
我会给你一些两个想法的基本蓝图。两者都需要使用完整的句子。
你可以重新安排这个句子,这样你就不会遇到多个问题,即“这个地方已被访问了这个年数|月|日|时|分钟前:{0} ”。
这有明显的缺点,并且听起来不自然。虽然我不能给你一个语言的例子,这个概念不起作用,但这种语言存在的概率非零(斯拉夫语言不在其中,那是肯定的。)
使用一些基于规则的选择方法从资源文件中选择有效的复数形式。要做到这一点,你需要知道一点Language Plural Rules。基本上,您可以自己使用这些CLDR's rules,也可以决定其他内容,例如包装ICU4C's PluralRules类并使用其select method,选择有效的复数形式。
ICU Project site甚至列出了您可以在C#应用程序中使用的现有包装器,即GenICUWrapper和ICU-Dotnet。
就个人而言,我建议使用后一种方法(使用ICU包装器)。您可能希望看到my answer关于Java中的解决方案的类似问题。我相信.Net会基于同样的想法,只有你会使用string.Format()
而不是MessageFormat
,你会以.Net的方式阅读资源(无论你真正喜欢哪种风格)。