对app添加多语言十分简单,按照以下步骤即可:
Part 1. 代码中的国际化
第一步: 创建Strings File
文件(Resource -> Strings File)
文件名称必须为Localizable.strings
第二步: 点击国际化按钮
出现国际化选项即可:
第三步: 添加语言 (工程文件 -> Project -> 添加)
国际化是针对于项目而非Target
选择需要添加的语言:
选择需要国际化的内容:
注意: 如果是先执行第三步,那么这里没有第三个选项。
点击Finish后,可以看到localizable文件多了一个下拉文件
第四步: 添加国际化Key-Value
在代码中使用NSLocalizedString(@"Key1", @"这是一个说明")
即可让该字符串替换为国际化字符串
Part 2. 项目配置中的国际化
项目配置和代码国际化十分相似,创建Strings File
文件,必须命名为InfoPlist
。选中文件,点击右侧Localize ...
按钮开启国际化即可。此步骤参考Part 1 中的配置方式即可。
这里特殊的地方是,需要国际化的是特殊的Key,这些Key 的查看方式如下:
这里<key>
标签中的即是对应的Key:
Part 3. 多语言问题(接口国际化)
当和服务器进行交互的时候,需要将对应的语言传给服务器,此时,由于各端的差异(iOS、Android、Web )通过系统方法获取到同一种的语言字符串是略有差异的,此时,就需要对其进行约定,统一处理。
一、 获取系统语言
通常,我们通过以下代码获取当前系统语言:
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
NSArray* languages = [defs objectForKey:@"AppleLanguages"];
NSString* preferredLang = languages.firstObject;
或者
NSString *preferredLanguage = [[[NSBundle mainBundle] preferredLocalizations] firstObject];
preferredLang 即当前的系统语言。
二、 获取语言误区(语言不仅仅是语言,包含语言+地区)
通过代码获取语言时,往往看到这样的:en-GB
和 en_GB
, 那这两个的区别是什么?
1. 首先要明确Language ID
和Locale ID
的关系
官方文档,一开始就给出了两者的定义
Language IDs identify a language, dialect, or script and are used to name language-specific resource folders stored in the app bundle.
翻译:
Language IDs 标识一种语言、方言 或者(一种语言的)字母系统 并 用于 存储 在应用程序包中 有特定语言命名的 资源文件夹中。
Locale IDs identify a set of regional conventions and are used in APIs—such as the NSLocale, NSDateFormatter, NSNumberFormatter, and NSCalendar classes—where region information is needed to format data.
翻译:
Locale IDs 标识一组约定区域 并 用于需要 区域信息 格式化日期的 API(例如 NSLocale、NSDateFormatter、NSNumberFormatter 和 NSCalendar 类)中
OS X and iOS use standard language ID and locale ID formats that consist of language and region designators. For example, using a language combined with a region designator, a language ID can distinguish between different languages and regional dialects.
翻译(机翻):
OS X 和 iOS 使用由语言和区域指示符组成的标准语言 ID 和区域设置 ID 格式。 例如,使用语言与地区指示符组合,语言 ID 可以区分不同的语言和地区方言。
由此可见,bundle
中的那些xxx.lproj
文件的名称xxx
, 就是Language ID
。其实这里说的不全,这里只是表明了应用程序包中,语言资源文件名称(这里表述的不全,下文详述)。
2. Language ID 详述
文档中有对Language ID
更全面的解释:
A language ID identifies a language used in many regions, a dialect used in a specific region, or a script used in multiple regions.
To specify a language used in many regions, use a language designator by itself.
To specify a specific dialect, use a hyphen to combine a language designator with a region designator.
To specify a script, combine a language designator with a script designator.
For example, to specify common English, use the en language designator as the language ID. To specify the English language as it is used in the United Kingdom, use en-GB as the language ID.
中间三句,表明了language ID
的表述方式:
1. To specify a language used in many regions, use a language designator by itself.
要指定在许多地区使用的语言,请单独使用语言指示符。
比如, 直接使用en
2. To specify a specific dialect, use a hyphen to combine a language designator with a region designator.
要指定特定方言,请使用连字符将语言指示符与地区指示符组合起来。
比如, 使用en-AU
,表示English as used in Australia(澳洲英语)
tips: hyphen 的意思是连接符,即英文的中划线。
3. To specify a specific dialect, use a hyphen to combine a language designator with a region designator.
机翻:
要指定脚本,请将语言指示符与脚本指示符结合起来。
比如,使用zh-Hans
,表示Chinese in the simplified script (简体中文)
结论:
language ID
是由语言
或者 语言-方言/script
或者 语言-地区
或者 语言-方言/script-地区
这样的结构组成,中间使用连接符(英文中划线)进行连接。
eg:语言选简体中文,地区选英国,获取到的语言就是zh-Hans-GB
。
eg:语言选英语(英国),地区选美国,获取到的语言就是en-GB
。注意,这里是语言-方言/script
的结构。
因为打印[NSLocale currentLocale]
可以看到结果是en_US
,这里可以看出地区是US。
eg:语言选英语,地区选中国,获取到的语言就是en-CN
。
3. Locale ID 详述
A locale ID identifies a specific region and its cultural conventions—such as the formatting of dates, times, and numbers.
To specify a locale, use an underscore character to combine a language ID with a region designator, as shown in Table B-5.
For example, the locale ID for English-language speakers in the United Kingdom is en_GB, while the locale for English-speaking residents of the United States is en_US.
中间的一句,表明了Locale ID
的表述方式:
使用英文下划线_
连接语言和地区。
结论:
locale ID
是由语言_地区
,这样的结构组成,中间使用英文下划线进行连接。
eg :语言选英语(英国),地区选美国,获取到的地区是en_US
。
3. 总结
看了文档以后,感觉描述的仍然有些模棱两可。不过,可以明确的是language ID
和 locale ID
并不是独立的,是互相包含的一种关系。
故,可以通过调用不同的API获取不同的值,再根据各自的特点进行解析。
比如:
[NSLocale currentLocale]
获取到的就是local
相关:
[[NSBundle mainBundle] preferredLocalizations]
获取到的就是language ID
相关:
三、统一语言类型
通过以上几点,获取语言并处理采用如下方式即可:
NSString *preferredLanguage = [[[NSBundle mainBundle] preferredLocalizations] firstObject];
preferredLanguage = preferredLanguage.lowercaseString;
// 特殊处理中文 简体繁体
if ([preferredLanguage hasPrefix:@"zh-hans"]) {
// 简体
preferredLanguage = @"cn";
} else if ([preferredLanguage hasPrefix:@"zh-hant"]) {
// 繁体
preferredLanguage = @"tw";
} else {
// 其他语言
preferredLanguage = [preferredLanguage componentsSeparatedByString:@"-"].firstObject;
}
if ([preferredLanguage isEqualToString:@"en"]) {
preferredLanguage = @"后台英语字符串";
} else if ([preferredLanguage isEqualToString:@"fr"]) {
preferredLanguage = @"后台法语字符串";
}
...
Part 4. 如何发现的文档
在看[NSLocale availableLocaleIdentifiers]
方法描述的文档中,我们找到了上述官方文档的地址:
一般说来,都是先看Xcode自带的文档说明,往往在其中就会帖一些网页文档的地址,网页版的文档往往更全面。
参考文档:
iOS本地化与国际化最佳实践。该文章中使用了Xcode导出/导入国际化文件以及storyboard国际化预览的步骤。可作为参考。