开发一款伟大的iOS应用程序是件了不起的事情,但是还有比优秀的代码、华丽的设计以及直观化交互更多的事要做。跻身在App Store排行榜前列还需要正合时宜的产品营销、扩大用户群的能力、实用的工具以及尽可能广泛地获得用户的技术。
对很多开发者来说,国际市场是事后的想法,但由于App Store提供了无缝的全球分享模式,任何iOS开发者都可以通过一键点击把应用程序发布至超过150个国家的市场。亚洲和欧洲代表了潜在客户不断增长的市场,这两个市场中很多人都不是以英语为母语,但是为了让应用充分利用市场的潜力,你至少要把应用语言国际化。
这篇教程将通过一款名为iLikeIt的应用带你了解最基础的国际化概念,并为你的应用添加国际化的支持。该示例应用有一个标签和一个You Like?按钮,用户无论何时点击You Like?,一些乐观的销售数据和对应的图片就会从按钮下方淡入显示。
不过现在,该应用仅仅有英语版本。
注意:国际化另一个重要的方面是使用Auto Layout改变文本的大小。不过为了让本教程尽可能地简单,我们不会主要关注Auto Layout。对于Auto Layout这个话题,我们另有其他教程。 |
国际化 vs 本地化(Internationalization vs Localization)
在你开始学习本教程之前,很重要的一点是了解国际化和本地化之间的不同之处,很多人经常会把这两个概念搞混。
简单说,国际化是一个应用程序国际兼容性设计的过程,比如:
1.以用户母语处理文本输入和输出;
2.处理不同的日期、时间以及数字格式;
3.利用适当的历法和时区处理数据;
国际化是一项你和开发者通过利用系统提供的API来实现的活动,并在代码上做一些补充和修改,从而让应用的中文版、阿拉伯语版本和英文版一样好。
相比之下,本地化仅仅是把应用的用户界面和资源翻译成不同的语言,这是你可以也应该交给别人做的工作,除非你能精通app应该支持的每种语言。
现在开始(Getting Started)
第一步是downloadiLikeIt项目,我们将会在整个教程中使用它。
在Xcode 5中打开该项目,并在模拟器上运行,你将会看到以下界面:
从截图中看出,你需要本地化四个项目:
UI元素: Hello Label
UI元素: You like? Button
销售数据文本: Yesterday you sold 1000000 apps
图片文本: I LIKE IT
花一小会儿时间浏览文件和文件夹来熟悉下项目结构。 Main.storyboard包含单个屏幕,它是ViewController类的实例。
从代码中分离文本
目前,应用展示的所有文本都是以硬编码字符串存在于Main.storyboard和ViewController里。为了本地化这些字符串,你需要把它们放在一个单独的文件中。
你将会在包中简单地引用这些字符串,而不是在你的方法中进行硬编码。
Xcode使用带有".strings" 扩展名的文件来储存和检索app中使用的所有字符串,以支持每种语言。根据iOS设备当前使用的语言,代码中一个简单的方法调用将会查找并返回要求的字符数串。
试试看,打开 File>New>File,选择Resource中Strings Fils,如图:
点击下一步,为文件命名为Localizable.strings,然后点击save。
注意:Localizable.strings是iOS用来本地化文本默认的文件名称。请抑制以其他内容给它命名的冲动,否则以后你每次引用本地化字符串的时候要一次次输入.strings 文件名。 |
现在,你已经创建了Localizable.strings文件,你需要添加所有的文本--当前硬编码在app中的文本。你需要遵从一个特定但简单的格式:
"KEY" = "CONTENT";
这些键/内容对功能就像NSDictionary ,惯例是使用默认的内容翻译作为内容的键:比如You Like?,你应该写:
"You like?" = "You like?";
Key/content对也可以包含格式化字符串:
"Yesterday you sold %@ apps" = "Yesterday you sold %@ apps";
现在切换至ViewController.m,找到viewDidLoad方法,现在app会为likeButton和salesCountLabel设置文本,展示如下:
_salesCountLabel.text = [NSString stringWithFormat:@"Yesterday you sold %@ apps", @(1000000)]; [_likeButton setTitle:@"You like?" forState:UIControlStateNormal];
取而代之的方法是,你需要从此前创建的Localizable.strings文件中读入字符串。用一个名为NSLocalizedString的宏修改这两行代码如下所示:
_salesCountLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Yesterday you sold %@ apps", nil), @(1000000)]; [_likeButton setTitle:NSLocalizedString(@"You like?", nil) forState:UIControlStateNormal];
宏包将一个稍长的代码片段包裹为一个更易于管理的长度,它使用#define指令创建。如果你想知道NSLocalizedString宏是什么,可按住Control键并在NSLocalizedString点击,可以看到它的定义如下:
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
在当前的语言中,NSLocalizedString宏使用localizedStringForKey方法查找给定键值的字符串。它为table name传递nil,所以它使用默认的字符串文件名(Localizable.strings)。更多细节,可查看苹果的NSBundle Class Reference。
注意:这个宏把注释作为一个参数,但似乎没什么用。不像此前那样需要手动把每个key/value对键入Localizable.strings,你还可以使用iOS SDK带的一个叫做genstrings的工具来自动处理(非常适用于大型项目)。 |
如果使用这个方法,你可以为每个字符串加上一个注释,注释会显示在默认的字符串边上,作为translator的辅助。比如你可以添加一个注释指出字符串在哪里使用。
已经有了足够的背景信息,现在开始吧!
创建并运行你的项目,并且它应该像之前一样在主屏幕上展示相同的文本,但是西班牙文在哪里?现在你的应用已经进行了本地化设置,添加翻译是小事一桩。
添加西班牙语本地化(Adding a Spanish Localization)
想要添加支持另一种语言,你可以点击左窗格中的iLikeIt项目文件夹,在旁边的窗格中选择Project(不是 Target),然后在Info标签下你会看到一个Localizations分区。点击点击“+”,然后选择Spanish (es)。
下个屏幕会询问你哪些文件需要本地化。选中所有文件并点击Finish。注意:Localizable.strings没有展示在这个列表中,不过不用惊慌!
在这一点上,Xcode已经在幕后设置好了一些目录,针对你选择的语言,这些目录包含不同版本的InfoPlist.strings和Main.storyboard。你可以使用Finder打开项目文件夹看看,你会看到如图所示:
看到en.lproj和es.lproj了吗?它们包含文件的特定语言版本。
en是English的本地化代码,es是Spanish的本地化代码。关于其他语言,可参看完整的语言代码列表。
从现在开始,当你的app想要获得某个文件的英文版,它就会去en.lproj中查找,而当它想要某个文件的西班牙语版时,它就会去es.lproj找。非常简单!把你的资源文件放在合适的文件夹里,剩下的事情就交给iOS负责了。
但是等等,Localizable.strings呢?想让Xcode知道你想将它本地化,那你可以在左窗格里选中文件,然后在右窗格中打开File Inspector。
你会看到一个Localize标签,点击并选择英语(因为当前是英语),最后点击Localize。
现在File Inspector面板将会展示文件所属的语言。目前,正如你所看到的,文件只针对英文进行本地化。可通过点击Spanish左边的框框添加西班牙语本地化。
回到左窗格并点击Localizable.strings旁边的箭头,它会显示出子元素。现在文件已经有了两个版本:一个是英文本,一个是西班牙语版。
想修改西班牙语的文本,可选择Localizable.strings (Spanish),并用如下内容替代它的内容:
"Yesterday you sold %@ apps" = "Ayer le vendió %@ aplicaciones"; "You like?" = "~Es bueno?~";
恭喜!现在你的应用支持两种语言了!
为了测试和验证所有事情都正常工作,你可以在模拟器/设备上把展示语言更改为Spanish,方法是打开设置应用,然后选择:General -> International -> Language -> Espanol.
如果 Xcode debugger仍在运行中,你可以在Xcode中点击“stop”,然后点击“Build & Run”,你将会看到:
地区vs语言(Locale vs Language)
100万是个相当不错的销售数据,我们可以为它添加一些格式让它看起来更好!
打开ViewController.m并将为_salesCountLabel设置文本的代码行替换为:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; NSString *numberString = [numberFormatter stringFromNumber:@(1000000)]; _salesCountLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Yesterday you sold %@ apps", nil), numberString];
编译并运行应用程序,那么数字就会更容易辨认一些。
这对美国人来说非常棒,但在西班牙,100万写作“1.000.000″而不是“1,000,000″。在西班牙文环境下运行应用程序,你将会看到逗号用来隔开0。在iOS中,数字格式化是基于地区/国家,而不是语言,所以为了了解某个西班牙人如何查看销售数据,可打开Settings.ap,并通过导航改变区域:General -> International -> Region Format -> Spanish -> Spain
在此编译和运行应用程序,现在你会看到正确的数字格式:
一点额外的前期工作,NSNumberFormatter会自动为合适的区域格式化你的数字。可能的情况下,请拒绝重新发明轮子,因为在iOS上,通常按照苹果的方式做才能有回报。
国际化Storyboards(Internationalizing Storyboards)
Storyboard中的元素,比如标签、按钮以及图片可以在代码中或者直接在storyboard中设置。在设置文本编程时,你已经学会了如何支持多种语言,但是屏幕顶部的“Hello”标签没有IBOutlet,只能在Main.storyboard中设置它的文本。
你可以添加一个IBOutlet,将其连接到Main.storyboard中的label上,然后使用NSLocalizedString设置其文本属性,就像使用likeButton和 salesCountLabel那样,但是这里有一个本地化storyboard元素更简单的方法,不需要任何附加代码。
打开Main.storyboard左侧的小三角形,你会看到Main.storyboard (Base)和Main.storyboard (Spanish)。点击Main.storyboard (Spanish)打
开编辑器,你会看到storyboard中的本地化文本。你已经有了一个Hello标签入口,如下:
/* Class = "IBUILabel"; text = "Hello"; ObjectID = "pUp-yc-27W"; */ "pUp-yc-27W.text" = "Hello";
用西班牙语翻译的“Hola”替换两个“Hello”:
/* Class = "IBUILabel"; text = "Hola"; ObjectID = "pUp-yc-27W"; */ "pUp-yc-27W.text" = "Hola";
注意:绝对不要直接改变自动生成的ObjectID,也不要复制和粘贴上边的代码行,因为标签的ObjectID可能已经跟上边展示的不一样了。 |
图片的国际化(Internationalizing Images)
由于应用程序使用了包含英语文本的图片,所以你需要把图片本地化,因为零零散散的英文文本会让你的西班牙应用看起来很不专业,并且也有损于应用的整体易用性和市场潜力。
本地化图片,首先需要下载西班牙语版本的图片(在大多数浏览器上是右键点击>保存为):
打开Images.xcassets,拖放此前下载的图片megusta.png并添加至左侧的图片列表,从而把图片添加至资产Asset catalog。Asset catalogs不能被国际化,所以你需要有一个方法来本地化图片。
打开Localizable.strings (English) ,并添加如下内容:
"imageName" = "ilike";
把以下代码添加至Localizable.strings (Spanish)文件:
"imageName" = "megusta";
从现在开始,你将使用imageName key来检索本地化版本的图片。打开ViewController.m并把如下代码添加到viewDidLoad方法中:
[_imageView setImage:[UIImage imageNamed:NSLocalizedString(@"imageName", nil)]];
如果需要,将模拟器/设备切换到西班牙语,编译并运行,然后你会看到本地化图片的展示。
现在你已经有了将应用程序针对多种不同语言本地化所需的所有工具。
注意:这仅适用于每种语言有不同文件名的情况。一个更好的方法是本地化资源文件夹,如这篇文章所描述的那样。 |
额外奖励
作为最后的奖励,我们来本地化应用的名字。Info.plist有一个特殊的文件(InfoPlist.strings),你可以在里边用字符串覆盖其他语言。为给应用程序一个不同的西班牙语名字,可打开Supporting Files > InfoPlist.strings (Spanish),并插入以下代码:
"CFBundleDisplayName" = "Me Gusta";
它改变了应用的名称,像Springboard上展示的那样。
练习:国际化音频文件(Exercise: Internationalizing Audio files)
学习到这里,你应该熟悉了基本的国际化知识。这是一个简单的练习,你可以通过两个不同的音频文件(一个是英文版,一个是西班牙语版)来测试下自己新掌握的知识,并基于用户选择的语言播放合适的文件。
以下是必要步骤的简单描述:
1.下载示例音频文件(sample audio files)。
2.把box-en.wav首个音频文件拷贝到项目中。
3.打开音频文件inspector,选择本地化按钮,确保你选择了英语和西班牙语作为支持语言。
4.重命名第二个音频文件(box-es.wav),和第一个名字(box-en.wav)一样,然后将其拷贝到es.Iproj文件夹。
5.确保你在Finder提示中选择了“Replace File”。
何去何从
Final Project包含了你在该教程中所写的全部代码。
现在你知道了国际化一款iPhone app所需的基本技术,那就为你现有的应用添加外语支持吧,或者在设计下一款应用时为其添加一门外语支持。正如你所看到的那样,这几乎没有花费多少时间,而它将会让你的应用接触到更宽广更多样化的受众,并且你的非英语用户也会感谢你!
对于实际的翻译,你可以使用Google的免费翻译服务(http://www.google.com/translate),但结果可能不是丝毫不差的。如果你可以花点钱,那么你可以考虑苹果的Internationalization and Localization页面下方列出了第三方服务提供商。
如果你有任何关于国际化的问题或建议,请加入论坛讨论!