单数/复数单词的本地化 - 语法数字的不同语言规则是什么?

时间:2011-08-21 05:40:06

标签: c# .net localization internationalization string.format

我一直在开发一个.NET字符串格式库来协助应用程序的本地化。它被称为 SmartFormat ,在GitHub上是开源的。

它试图解决的问题之一是Grammatical Numbers。这也被称为“单数和复数形式”或“条件格式”,这里有一个英文版的片段:

var message = "There {0:is|are} {0} {0:item|items} remaining";

// You can use the Smart.Format method just like using String.Format:
var output = Smart.Format(CultureInfo.CurrentUICulture, message, items.Count);

英国的规则,我相信你知道,有两种形式(单数和复数)可以应用于名词,动词和形容词。如果数量为1,则使用单数,否则使用复数。

我现在正试图通过为其他语言实施正确的规则来“开阔视野”!我已经明白,某些语言最多可以包含4种复数形式,并且需要一些逻辑来确定正确的形式。我想扩展我的代码以适应多种语言。例如,我听说俄语,波兰语和土耳其语的规则与英语完全不同,所以这可能是一个很好的起点。

但是,我只会说英语和西班牙语,那么如何确定许多常用语言的正确语法规则呢?

编辑:我也想知道我的单元测试的一些非英语“测试短语”:What are some good non-English phrases with singular and plural forms that can be used to test an internationalization and localization library?

3 个答案:

答案 0 :(得分:10)

当然,不同的语言有不同的复数规则。特别有趣的可能是阿拉伯语和波兰语,两者都包含相当多的复数形式。

如果您想详细了解这些规则,请访问Unicode Common Locale Data Repository,即Language Plural Rules

那里有很多有趣的信息,不幸的是其中有些信息是错误的。我希望复数形式是正确的(至少对于波兰语来说,就我所知,:)。

答案 1 :(得分:1)

如果您在问题正文中提供了您正在使用的规则样本,它们采用的格式会很好吗?

无论如何,在你的例子中:

var message = "There {0:is:are} {0} {0:item:items} remaining";

你似乎是基于两个选择段中的选择基于相同的单一规则的假设,并且两个选择之间存在直接对应关系 - 这是相同的单一规则将选择(是,项目)或(是,项目)。

这个假设对于其他语言来说不一定正确,例如虚拟语言English-ez(只是为了让读者容易理解,我发现外语中的例子令人恼火 - 我借用阿拉伯语但是简化了很多)。这种语言的规则如下:

第一个选择段与普通英语相同:

is: count=1
are: count=0, count=2..infinity

第二个选择部分与普通英语有不同的规则,假设以下简单规则:

item: count=1
item-da: count=2 # this language has a special dual form.
items: count=0, count=3..infinity 

现在单一规则解决方案还不够 - 我们可以建议一种不同的形式:

var message = "There {0:is:are@rule1} {0} {0:item:items@rule2} remaining";

此解决方案在其他情况下可能会出现问题,但我们正在讨论您提供的示例。

检查gettext(允许选择完整的消息到单个级别)和ICU(允许选择完整的消息到多个级别,即多个变量)。

答案 2 :(得分:0)

您采取的方法可能适用于大多数英语和西班牙语的案例,但很可能在许多其他语言上失败。问题是你只有一种试图解决所有语法数字的模式。

INFO  [RequestProcessingTimeInterceptor] [Start call] POST http://server/web/api/rest/catalog/2
INFO  [stdout] Hibernate: select .... from CATALOG catalog0_ where catalog0_.id=?
INFO  [CatalogServiceImpl] Updating catalog #2...
INFO  [CatalogServiceImpl] Catalog #2 updated !
INFO  [RequestProcessingTimeInterceptor] [Call took 23ms] POST http://server/web/api/rest/catalog/2

每种语法性别都需要一种模式。在这里,我将两个模式组合成一个多模式字符串。

var message = "There {0:is|are} {0} {0:item|items} remaining";

英语使用两个语法数字:单数和复数。一个开始奇异模式,另一个开始复数模式。

例如翻译成使用相同数量的语法数字的芬兰语时,你会使用

var message = PluralFormat("one;There is {0} item remaining;other;There are {0} items remaining", count);

然而,日语仅使用一个语法数字,因此日语只会使用其他语法。波兰语使用三个语法数字,因此它包含一个,少数和多个。

其次,您需要适当的规则来选择正确的模式数量多个模式。 Unicode联盟的CLDR包含XML文件中的规则。

我已经实现了一个开源库,它使用CLDR规则(从XML转换为C#代码并包含在库中)和多模式字符串,以支持语法数字和语法性别。

https://github.com/jaska45/I18N

使用此库,您的样本将变为

"one;{0} kappale jäljellä;other;{0} kappaletta jäljellä"