Application localization in iOS development

iOS 对国际化的支持是相对比较完善的。

应用的国际化支持

在 Project 属性中,有 Localizations 一项,在其中可以管理支持的语言列表,还可以选择是否开启 Base 语言。

为资源文件开启国际化

在资源文件(如 strings/xib/storyboard)的文件属性中,可以在 Localization 项中进行国际化语言的管理。如果尚未国际化,会有一个长长的 Localization 按钮,点击后开启这个文件的国际化。如果已国际化,会显示并可管理当前文件已支持的语言。

如果想取消对这个文件的国际化,在 Xcode 里做不到。唯一的办法是,去 Finder 里把各个语言的 .lproj 目录下的这个资源文件删掉,只留一份放到工程目录的最外层(而不从属与任何 .lproj 目录)。

字符串的国际化:

自己新建一个 String 文件到工程里,名为 Localizable.strings 即可。(这是默认的文件名,调用 NSLocalizedString 方法默认取这个文件,如果用了其他的文件名,则每次调用方法时,需要指定文件名)

例如,Localizable.strings 内容为:

Localizable.strings(Chinese (Simplified))
1
2
3
4
5
"Today" = "今天";
"Yesterday" = "昨天";
"%d days ago" = "%d天前";
/* {User First Name}'s Profile */
"%@'s Profile"="%@'s Profile";
Localizable.strings(English)
1
2
3
4
5
"Today" = "Today";
"Yesterday" = "Yesterday";
"%d days ago" = "%d days ago";
/* {User First Name}'s Profile */
"%@'s Profile"="%@的个人资料";

获取时:

1
2
3
4
5
NSString *str;
str = NSLocalizedString(@"Today", nil);
int temp = 3;
str = [NSString stringWithFormat:NSLocalizedString(@"%d days ago", nil), temp];
str = [NSString stringWithFormat:NSLocalizedString(@"%@'s Profile", @"{User First Name}'s Profile"), user.name];

上面是常用的情况。还有一种复杂的情况,是在有些语言里,某两个参数的位置可能会颠倒,这时需要使用转义符:

1
"%@ Error! %@ failed!" = "%2$@ 失败了!%1$@ 错误了!";

更为详细的可参照:
http://nshipster.com/nslocalizedstring/
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html
https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/InternationalizingYourCode/InternationalizingYourCode.html

xib/storyboard 的国际化

除了借助 localizable strings 文件进行界面国际化之外,对于 xib/storyboard 可以直接进行国际化。虽然看上去很方便、很直观,但其实并不是特别好用。

它的原理其实还是 localizable strings,只不过这个 strings 文件是 Xcode 自动创建的。创建的时机是在你对这个界面开启 localization 时,而且它并不会监控 xib/storyboard 的变化。如果你在 localization 之后又改变了这个 xib/storyboard,主要是增加了新的控件,那么这个新控件并不会自动出现在 strings 文件中。

那你就没办法了,Xcode 也没有提供同步的手段,你唯一能做的是查看 xib 的源代码,从中找到新建控件的 ID,然后自己写到那个 strings 文件里--噢,这一点都不方便。

Bundle Display Name 的国际化

显然,需要对不同语言设定不同的应用名称,也就是 Bundle Display Name,我们都知道它在 Info.plist 里。

但注意,不是把 Info.plist 进行 Localization,如果对 Info.plist 进行了 Localization,会编译报错 the file Info.plist does not exist.

正确的方式是在工程里新建一个名为 InfoPlist.strings 的文件,然后对这个 strings 文件进行国际化,在里面写入:

1
"CFBundleDisplayName" = "名称";

即可。

注意,需要把 InfoPlist.strings 文件加到工程属性里的 Copy Bundle Resources 里(默认应该就给加上了,如果有问题可以检查一下)。但不要把 Info.plist 文件加到 Copy Bundle Resources 里,否则出现编译警告。

Base 语言的问题

测试发现,将 iOS 设备设置为并没有支持的语言时,应用并没有正确地显示为 Base 中的字符串(英语),而是显示成了简体中文。

Stackoverflow 上有很多国内外开发者遇到了这个问题,但都未找到原因和解决方法。

http://stackoverflow.com/questions/20241256/ios-app-default-language-en-is-not-applied
http://stackoverflow.com/questions/20584984/ios-set-a-default-language-in-xcode-for-my-app
http://stackoverflow.com/questions/18114994/does-my-base-internationalization-storyboard-have-to-correspond-to-a-fallback-la

App Store 应用名称及简介的国际化

希望让应用在不同国家的 App Store 中显示不同语言的名称,在 iTunes Connect 里新建应用时先用一个主要语言新建,如简体中文,新建成功后在 App 信息里可以看到“可本地化的信息”,可以在右侧选择语言,并且填入相对应的信息。另外,在版本中对应用简介、关键字、截图等也都须进行国际化。

如果未做本地化,则按照选择的主要语言显示。