我有一个课程,实现了我们都知道和喜爱的“拍照/选择图书馆”。它在这里https://github.com/fulldecent/FDTake这是通过git submodule包含在我的其他项目中,并且工作正常。
现在我需要将该课程中的文本翻译成中文,因此它是“拍照/选照片”或类似的东西。有没有一种很好的方式将翻译放在那里,所以每个人都可以使用它们?
本地化通常由NSLocalizedString(<#key#>, <#comment#>)
宏处理。在源代码中,用宏替换所有硬编码字符串。例如:
[self.buttonTitles addObject:@"Hi"]; // hard coded greeting
同
[self.theLabel setText:(NSLocalizedString(@"theKey", @"Hi"))];
然后genstrings
(来自终端内)用于扫描实现文件(* .m)并将其输出写入语言项目文件夹(此处:en.lproj)
$ genstrings -o en.lproj/ *.m
在en.lproj/
目录中有一个名为Localizable.strings
的文件。其内容将是:
/* Hi */
"theKey" = "theKey";
评论/* Hi */
取自我们的源代码。应该向(讲英语的)用户显示字符串Hi
。所以我们需要编辑等号右边的字符串并使其成为问候语,= "theKey"
必须成为= "Hi"
:
/* Hi */
"theKey" = "Hi!";
如果只有几个字符串或者没有打算修改字符串,那么这一切都很好。当gestrings再次运行它将覆盖修改,你实际上失去了在Localizable.strings
完成的工作。一个想法可能是将genstrings的输出写入不同的位置。但是,您必须手动合并更改。一旦Localizable.strings
文件增长,它就变成了一个噩梦,试图保持源代码和Localizable.strings
同步。所以我们试着避免这种情况。
使用NSLocalizedStringWithDefaultValue(<#key#>, <#tbl#>, <#bundle#>, <#val#>, <#comment#>)
有很大的帮助。该宏将允许在Localizable.strings
文件中设置默认值,此外,它将使得对值字段的初始编辑的需要消失。
把它放在一起:
[self.theLabel setText:NSLocalizedStringWithDefaultValue(@"theKey2", @"Localizable", [NSBundle mainBundle], @"Hi!", @"informal greeting"))];
运行上面使用的genstrings
命令后,Localizable.strings
现在有一个小的不同
/* informal greeting */
"theKey2" = "Hi!";
除了现在告诉翻译我们想要非正式问候的评论之外,“Hi!”
已经存在于价值领域。无需转到Localizable.strings文件,搜索正确的行,将字段“theKey”修改为“Hi!”。 genstrings
根据NSLocalizedStringWithDefaultValue提供的默认值为我们做了这个。
将文件Localizable.strings
添加到xcode项目中。
更改源代码后,对于Xcode内部的新语言,首先添加本地化到Localizable.strings
。 Xcode将在基于原始Localizable.strings
的子文件夹下生成Localizable.strings
的副本。
我个人不会说中文,而是说德语。因此,如果要添加德语本地化,我的翻译将在de.lproj/Localizable.strings
下,it.lproj/
下的意大利语等等。
根据需要编辑新的Localizable.strings
:
(德语)
/* informal greeting */
"theKey2" = "Hallo!";
(意大利)
/* informal greeting */
"theKey2" = "Ciao!";
然后构建并运行。
********* begin edit
以上考虑了“标准”xcode项目。您在询问是否批量模拟模块,因此允许您的代码成为项目的补充。我建议你创建一个包含本地化的包。当有人将您的代码包含到他们的项目中时,本地化将保持独立。有关捆绑包的完整文档是here。
使用捆绑进行本地化的项目是QuincyKit(可能还有更多,这是第一个想到的)
因此,当将本地化放入除mainBundle
以外的捆绑中时,下面一行中的[NSBundle mainBundle]
必须更改
[self.theLabel setText:NSLocalizedStringWithDefaultValue(@"theKey2", @"Localizable", [NSBundle mainBundle], @"Hi!", @"informal greeting"))];
而不是从mainBundle获取字符串,获取对您自己的模块的引用。文档建议:
NSBundle* myBundle = [NSBundle bundleForClass:[self class]];
这条线变成:
[self.theLabel setText:NSLocalizedStringWithDefaultValue(@"theKey2", @"Localizable", myBundle, @"Hi!", @"informal greeting"))];
********* end edit
我认为捆绑(如Olaf建议的那样)可以很好地工作,但另一种方法是减少开销以确保可本地化的字符串资源不会干扰同一解决方案中的另一个项目(causing a weird problem to people reusing your component in another localized project)是将localizable.strings
文件名更改为唯一文件名。这意味着你使用NSLocalizedString
的地方现在需要使用它的变体NSLocalizedStringFromTable
(Apple documentation),其中tableName与你的字符串文件同名(没有.strings扩展名)。你可以定义自己的宏,这样它只是NSLocalizedString
的直接替代品,比如FDTakeLocalizedString
。
与localizable.strings
文件相比,使用XIB文件或故事板发生文件名冲突的可能性要小得多。但在这两种情况下,如果使用带前缀的命名约定(比如FDTake.strings和FDTake-Main.xib),它将消除风险并且只能提供帮助。