在我的iPhone应用程序中,我需要显示对象计数然后本地化,因为英语区分单数和复数,我执行以下操作
//伪代码
if (objectList.count == 1) { NSLog(@"%@", NSLocalizedString(@"1 object", @"display one objects"); } else { NSLog(@"%@", NSLocalizedString(@"%d objects", @"display multiple objects"); }
这适用于英语,但在许多其他语言中,名词的复数形式并不是简单地通过添加“s”来构建的。
As this page explains,语言之间有两点不同:
- 复数形式的构建形式有所不同。这是一个问题 语言有很多 违规行为。例如德语 是一个极端的案例。虽然英语和 德语是同一种语言的一部分 家庭(日耳曼语),几乎是常规的 形成复数名词形式 (附上's')几乎找不到 德语。
- 复数形式的数量不同。这对于那些人来说有点令人惊讶 谁只有罗马人的经验 和日耳曼语这里的 数字是相同的(有两个)。
我应该如何处理我的代码?
答案 0 :(得分:11)
NSLocalizedString将从您的应用包中的字符串表中读取。因此,您需要支持的语言列表在编译时是已知的。而不是担心如何为每种可能的语言编写代码,只需支持你支持的语言。
如果你的译者来找你并说,为了支持火星人,你需要单独拼写偶数和奇数,你可以调整你的代码,如:
if (objectList.count == 1) {
NSLocalizedString(@"ObjectCount1", @"display one");
} else if (objectList.count % 2 == 0) {
NSLocalizedString(@"ObjectCountEven", @"display even");
} else if (objectList.count % 2 == 0) {
NSLocalizedString(@"ObjectCountOdd", @"display odd");
}
en.lproj / Localizable.strings:
ObjectCount1 = "1 object";
ObjectCountEven = "%d objects";
ObjectCountOdd = "%d objects"; // same as ObjectCountEven
mars.lproj / Localizable.strings:
ObjectCount1 = "1 object-o";
ObjectCountEven = "%d object-e";
ObjectCountOdd = "%d object-o"; // same as ObjectCount1
很抱歉,如果这听起来不太理想,但是人类语言混乱且不规则,所以试图为他们所有人找到一个优雅,统一,通用的解决方案是浪费时间。没有一个。
答案 1 :(得分:4)
我刚刚发布了JJPluralForm,改编自Mozilla的PluralForm。
有了这个,您就不必担心执行所有if-else
,switch-case
代码来进行代码本地化,随着本地化数量的增长,无法维护。
您提供的示例之类的内容可以通过以下方式处理:
[[JJPluralForm sharedManager] pluralStringForNumber:numberOfObjects
withPluralForms:NSLocalizedString(@"N_OBJECTS_PLURAL_STRING", @"")
localizeNumeral:YES];
然后,每个Localizable.strings文件将N_OBJECTS_PLURAL_STRING
本地化为以分号分隔的复数形式列表。对于英语,那将是"%@ object;%@ objects"
。
查看项目了解更多详情。
答案 2 :(得分:4)
Smartling发布了一个开源框架,以支持符合CLDR标准的复数形式。
https://github.com/Smartling/ios-i18n
要使用它,请在键中添加一个特殊标记,该标记遵循CLDR样式标记并调用SLPluralizedString而不是NSLocalizedString。在运行时,库将根据应用程序当前运行的语言选择要使用的正确字符串。
所以你的英文.strings文件会有:
"%@ apples##{one}" = "One apple";
"%@ apples##{other}" = "%@ apples";
俄罗斯.strings档案:
"%@ apples##{one}" = "%@ яблоко";
"%@ apples##{few}" = "%@ яблока";
"%@ apples##{many}" = "%@ яблок";
"%@ apples##{other}" = "%@ яблока";
并且调用它的代码可能如下所示:
NSString *s2 = [NSString stringWithFormat:SLPluralizedString(@"%@ apples", number, nil), number];
请注意,此示例演示了此库的一个优点 - 它允许您使用可能甚至不使用格式说明符的表达语言编写原始字符串或翻译。
在撰写本文时,我是Smartling的产品经理。
答案 3 :(得分:2)
顺便说一句,从iOS 7和Mac OS X 10.9开始,本地化内置支持复数形式。从16:10开始,请参阅WWDC 2013 video“让您的应用程序成为世界就绪”。复数本地化在.stringsdict plist文件中,然后你就可以了
NSLog(@"%@", [NSString localizedStringWithFormat:
NSLocalizedString(@"%d objects", @"display multiple objects"), n]);
答案 4 :(得分:0)
这个问题有一个更强大的解决方案。看一下来自TranslationExchange.com的Tr8n库
https://github.com/tr8n/tr8n_objc_clientsdk
该库使用TranslationExchange的TML(翻译标记语言),这使得国际化过程非常容易。首先,你甚至不需要再次处理Strings XML文件了,真的...... - Tr8n SDK将为你动态创建和管理你的String文件 - 你永远不会再看它们。
你的具体例子就是:
Tr8nLocalizedStringWithTokens(@"{count || object}", @{@"count": objectList.count})
Tr8n库会自动为您选择任何语言的复数形式。哈?是的,这很神奇。以上令牌示例的完整形式实际上是:
{count:number || one: object, other: objects}
这意味着“count”标记是一种数字类型,使用关键字“one”和“other”映射到英文复数....但是Tr8n足够聪明,不能让你输入所有这些。它也足够聪明,可以将参数序列映射到适当的规则值。当然,它知道“count”通过命名约定与数字规则相关联。所以它变成了:
{count || object}
顺便说一句,既然你已经提到了俄语,那么上面的俄语翻译就是:
"{count || object}" = "{count || объект, объекта, объектов}"
这个例子太简单了,让我们来看看一个更有趣的例子:
Tr8nLocalizedStringWithTokens(
@"{user} uploaded {count || photo} to {user | his, her} photo album.",
@{@"user": user, @"count": 5}
)
首先,祝你好运使用标准iOS i18n库(或任何其他库)翻译这句话......这是一个笑话 - 但实际上,没有办法使用任何东西,但Tr8n。
上述翻译成俄语的TML只是:
@"{user || загрузил, загрузила} {count || фотографию, фотографии, фотографий} в свой фотоальбом."
在这里,我们处理性别规则与处理数字规则的方式相同。但是,除了“一个”,“少数”,“其他”,我们有“男性”,“女性”,“未知” - 嗯,每种语言可能有不同的性别和数字规则。 Tr8n会处理它,所以你没必要。
好的,让我们把它提升到一个新的水平。您已决定必须将照片数量设为粗体。一块蛋糕。
Tr8nLocalizedAttributedStringWithTokens(
@"{user} uploaded [bold: {count || photo}] to {user | his, her} photo album.",
@{
@"user": user,
@"count": 5,
@"bold": @{@"font":@{@"name": @"system", @"size": @12, @"type": @"bold"}}
}
)
[bold:...]是装饰标记。您是否注意到我们将宏切换到了AttributedString版本?这个宏实际上会使用iOS的原生装饰机制生成NSAttributedString。你能猜出俄语翻译会是什么吗?
@"{user || загрузил, загрузила} [bold: {count || фотографию, фотографии, фотографий}] в свой фотоальбом."
不过,您可以在其他地方预先定义所有装饰标记,这样您就不必每次都定义它们。
让我们再做一个最后的例子......说,你有一个以下列形式的新闻报道:
Tr8nLocalizedAttributedStringWithTokens(
@"{actor} sent {target} [bold: {count || gift}].",
@{
@"actor": user1,
@"target": user2,
@"count": 5
}
)
英语看起来并不有趣。但它支持俄语或支持语言案例的任何其他语言。 {target}的名称(如果恰好是俄语)实际上需要使用俄语Dative语言案例。
http://en.wikipedia.org/wiki/Dative_case
如果你不会说俄语,你可能不需要知道它。但是你的俄语翻译应该。让我们看看俄语翻译:
@"{actor || подарил, подарила} {target::dat} [bold: {count || подарок, подарка, подарков}].",
Tr8n非常聪明,可以使用其强大的语言规则引擎,并将Dative语言案例应用于通过{target}令牌传递的俄语名称......
对于一个简单的数字问题,这是一个很长的答案。感谢您阅读它。希望能帮助到你。
免责声明:我是Tr8n框架和TML语言的创建者。如果您有任何疑问,请告诉我,我很乐意帮助您解决所有翻译问题。