下面这段话摘自苹果的国际化和本地化指南:
Localization is the process of translating your app into multiple languages. But before you can localize your app, you internationalize it. Internationalization is the process of making your app able to adapt to different languages, regions, and cultures. Because a single language can be used in multiple parts of the world, your app should adapt to the regional and cultural conventions of where a person resides. An internationalized app appears as if it is a native app in all the languages and regions it supports.
The App Store is available in over 150 different countries, and internationalizing your app is the first step to reach this global market. Using iTunes Connect, you specify whether your app is available in all territories or specific territories. Then you customize your app for each target market that you want to support. Users in other countries want to use your app in a language they understand and see dates, times, and numbers in familiar, regional formats.
本地化是将您的应用翻译成多种语言的过程。 但是在您可以本地化您的应用之前,您需要将其国际化。 国际化是让您的应用能够适应不同语言,地区和文化的过程。 由于单一语言可用于世界的多个地区,因此您的应用应适应人们居住地区的地区和文化习俗。 一个国际化的应用看起来好像它是一个支持所有语言和地区的本地应用程序。
App Store可在150多个不同的国家/地区销售,应用国际化是迈向全球市场的第一步。 使用iTunes Connect,您可以指定您的应用在所有地区或特定地区是否可用。 然后,您可以针对您要支持的每个目标市场自定义您的应用。 其他国家的用户希望以他们理解的语言使用您的应用,并以熟悉的区域格式查看日期,时间和数字。
应用中那些字符串需要本地化
一般而言,所有你想以某种形式展现在用户眼前的字符串都需要本地化,包括标签和按钮上的文本,或者在运行时通过格式化字符串和数据动态生成的字符串。
工程配置(添加多语言)
- 选中PROJECT->INFO->Localizations,然后点击"+"号,添加你需要的语言类别
- 创建好工程之后默认的语言为英语。这里我们需要添加简体中文
- 添加完毕,我们可以看到有两种语言Chinese和English!
本地化应用名称(InfoPlist.strings)
通过InfoPlist.strings
文件,应用可以在不同的手机语言环境中,显示不同预先设置好的名字。例如,微信在简体中文环境下显示的名字为“微信”,而在英语环境下显示为“weChat”。
- 创建文件。command + N -> iOS -> Resource -> Strings File
- 文件名字必须为InfoPlist
- 创建完成之后,可以在工程目录中看到
InfoPlist.strings
文件
- 选中
InfoPlist.strings
文件,在右侧工具栏中,点击Localize,选择我们需要本地化的语言
- 默认为English,点击Localize
- 勾选Chinese(Simplified)
- 创建完成,此时我们可以看到,InfoPlist.strings文件以包含英语以及简体中文两种语言的文件
- 接下来,我们分别在不同的语言文件中设置响应的App名字
- 我们可以看到在不同的手机语言环境中,App显示的名字是不同的。
NSLocalizedString
NSLocalizedString
这个宏是字符串本地化的核心。NSLocalizedString
提供本地化字符串的 “一次编译,随处运行” 的方式,根据用户设置的字符串表把所有本地化字符串替换成对应的翻译。它有两个参数
key
:进行本地化的唯一字符串标识,comment
:用于提供用来准确翻译的足够的上下文的字符串。在实践中,key
往往只是用来翻译的基准字符串,而comment
通常是 nil在运行时,
NSLocalizedString
首先会确定当前的手机语言环境,并在应用程序包中找到相应的Localizable.strings
文件,查找和参数匹配的键值(在下面的例子中 key==home),然后读出真正要显示的字符串。
在实践中,key 往往只是用来翻译的基准字符串,而 comment 通常是 nil
在使用NSLocalizedString
之前我们需要先创建好相应的Localizable.strings
文件,创建的方法跟创建InfoPlist.strings
相同,这里就不具体说明了。
基本使用
- 在不同的文件中为同一个key设置不同的值
执行下面的代码
NSLog(@"Home == %@",NSLocalizedString(@"home", nil));
在英语环境中,打印的是Home == home
,而在中文环境中,打印的是Home == 主页
Key键值命名建议
如果项目比较巨大的话,Localizable.strings
中的字符串键值一定会越来越多。 这就涉及到每个键的命名,如果随意命名,就难免造成混乱,比如:
"home"="主页";
"myhome"="我的主页";
"rate"="给个评价";
"newshome"="新闻主页";
"loadnews"="加载新闻";
一个相对好一些的名称组织方式是使用命名空间
"main.home"="主页";
"my.home"="我的主页";
"my.rate"="给个评价";
"news.home"="新闻主页";
"news.load"="加载新闻";
这里的命名空间不会有编译层面的检测,只是我们在逻辑上的组织,通过对名称简单的合理组织,对项目的可维护性会有很大的提高。
另外几个宏
NSLocalizedStringFromTable(key, tbl, comment)
可以通过tbl
参数,用来确定.strings
的文件名。 默认情况下,系统会从Main Bundle
中加载名称为Localizable.strings
的文件。 如果这样调用:
NSLocalizedStringFromTable(@"home", @"town", nil);
那会在town.strings
文件中查询,而不是在默认的Localizable.strings
。当项目的规模比较大时,可以将不同模块的字符串资源切开分别存放,然后通过相应的tbl
加载资源
NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment)
与上面那个宏相比,这一个宏可以指定bundle
。
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"external" ofType:@"bundle"];
NSBundle *extBundle = [NSBundle bundleWithPath:bundlePath];
if (extBundle) {
NSLocalizedStringFromTableInBundle(@"home", @"table", extBundle, nil);
}
上面这段代码,首先加载external.bundle
, 然后从这个bundle
里面的table.strings
文件中查找对应的字符串键值home
。
这样,除了用文件把字符串分开,还可以把这些文件分散在不同的 Bundle 中。又多了一个维度,对于依赖模块非常多的大项目中,这个机制还是比较有用的。比如不同模块的团队都用同一个键值命名字符串,通过文件和 Bundle 的分离,就可以避免重名冲突。
合理的注释comment
还记得我们最开始例子中的comment
参数吧,用作对这个键值的注释,大多数键值名称其实已经基本表示清除含义了,比如:
"news.home" = "新闻主页";
"news.load" = "加载新闻";
对于这些键值,是否写注释都不妨碍理解。 注释更适合的场景是格式化输出,比如这样:
"%d views"="have seen %d views";
上面这个字符串资源本身又是一个格式化输出模板, 那么我们就可以这样调用:
NSString *format = NSLocalizedString(@"%i views", @"{总浏览量} views")
print(String(format: format, 20))
NSLog(format, 20);
这里comment
给每个格式化参数的含义做了注释,这样其他人就能更快的看懂这段代码的含义。
调试技巧
- 切换语言无需在模拟器中设置,只需要在Xcode中进行如下设置: Edit->Scheme->Run->Options ->Application Languages -> 选择需要调试的语言。
结尾
这次介绍了NSLocalizedString
的基本用法,以及它的几个类似宏的应用场景。这几个宏对于规模稍大的项目,以及模块化思路都有很好的帮助。还给大家分享了关于注释和键值命名的一些建议。无论你开发的 APP 是否真的需要多语言,使用NSLocalizedString
而不是直接把字符串写到代码里面都是一个相对好一些的选择,因为能够轻松地查看所有用户将看到字符串是很有用的。
最后,喜欢的话请点个赞吧!