一、什么是国际化?
应用国际化简单来说就是使用你的应用能够让世界各国的用户使用。既然需要使各个国家的用户能够正常的使用,则必然我们应用必然符合各国用户所使用的语言。那么我们在应用如何去实现这个功能呢?能够使应用基于系统所设置的语言而进行相应的语言变化,符合用户的需要。下面就来简单总结一下,如何在项目中实现国际化。
二、如何在Xcode6中实现应用国际化?
1. 要对应用实现国际化,首先我们得先设置该项目支持哪几种语言,默认只支持英语。按下图所示进行设置(当我们添加了一种语言后,在 storyboard 文件中会自己添加一个该语言的国际化文件,以.strings结尾):
2. 对 storyboard 或 xib 文件 实现国际化:
a. 首先注意:一般我们进行国际化操作时,最好是在项目完成之后来做此操作,因为当我们添加其它语言到项目中的时候,Xcode会自动为storyboard文件生成该语言对应的国际化文件,且只会对现有的控件进行相关描述。如果后面我们再添加一些其它的控件的话,Xcode不会自动更新对这些控件的国际化支持,需要我们手动去操作,所以建议在项目开发完成后再做此操作,会方便很多。
b. 由于在 storyboard 中,在添加其它语言后Xcode会自动生成相应的国际化文件,所以 针对 storyboard 中的控件的国际化相对比较简单。我们只需要在对应语言的国际化文件中将对应key的值改成相应语言的描述即可。如下图所示(左图所示是修改后的中文、右图为英文):
在上图中需要注意的一点是,如果在文件中存在相同名称的控件描述,如在两个不同的控制器中都有一个取消按钮的情况,那么我们如何区别哪个按钮在国际化文件中对应的key是哪个呢?这个我们可以在 storyboard 中当我们选中某个控件的时候,在下图所示位置可以就看到对应控件key的名称:
c. 对 storyboard 文件实现国际化就只需要上面几个步骤,很简单。但对于xib文件就不适用了。原因是当我们初次创建xib文件的时候,Xcode不会自动为该xib文件实现国际化,不会生成相应的国际化文件(即使你是在创建xib文件之后再添加其它语言)。在xib中我们需要手动进行设置国际化,步骤也很简单,如下所示(选中xib文件,点击localize,默认选中Base后,在Localization下面就会生成相应支持国际化语言的选项,勾选后,在xib文件前面会出现一个三角形按钮,展开会看到已经生成了相应的国际化文件,同样建议国际化操作最好在项目完成之后进行,之后的操作同上面storyboard一样,编写相应key的国际化描述即可):
3. 对项目中的动态文本(即需要在程序中设置的内容,非静态内容)进行国际化
a. 使用宏(NSLocalizedStringFromTable),宏只针对字符串字面量才有用。
例如,我需要在程序中设置某个UILabel的值,正常情况下我们会这样:
self.titleName.text = @"标题名称";
但在国际化中,不应该这样写,要不然就无法实现所谓的国际化。应该写成如下的形式:
self.titleName.text = NSLocalizedStringFromTable(@"标题名称", @"Tab1ViewController", @"此字符串用来显示标题名称");
在国际化版本中应该这样写。(参数对应(key, table, comment))。对于所有需要显示在UI界面上的文本,都需要这样写。
然后我们需要使用终端命令来生成.strings国际化文件。方法如下:
打开终端 -》进行项目所在文件夹 -》 输入命令"genstrings *.m" 回车(可以看到在项目所在文件夹下面生成了一个以.strings结尾的文件,且该文件的文件名将是上面宏中的table的名称,这样不同的table会对应一个不同的文件,便于管理,当然也可以放到同一个table里面,如果内容较少的话) -》 将.strings文件拖到工程里面。
只生成文件还不够,接下来还需要对该文件进行“本地化”操作。方法与上面提到的将 xib 文件进行国际化的方法一样:选中该.strings文件 -》 点击“localized” -》 勾选所有需要支持的语言项 -》自动生成对应的语言文件 -》在各自的语言文件中修改相应的key对应的该语言的描述即可。
b. 如果我们想将某个变量或某个方法的返回值当作key的话,此时使用宏来完成国际化操作将会不可行,那怎么办呢?
如需要将变量或方法的返回值作为key的话,我们就需要使用NSBundle中的方法来进行国际化操作,实际上,在上面的宏中,封装的就是NSBundle的方法,宏只是让我们操作更方便而已,但对于变量或方法宏就无法支持,需要我们手动操作。如下所示:
NSString *title = @"标题名称2"; self.titleName.text = [[NSBundle mainBundle] localizedStringForKey:title value:@"国际化测试" table:@"TabBarCustom"];
这样我们就能当变量或方法的返回值当作key,生成国际化文件。说到国际化文件,如果我们不是使用宏的话,当我们使用命令genstrings的时候,并不会自动生成国际化文件,此命令只会扫描应用中用宏声明的值。所以我们这里需要去手动创建.strings文件。创建.strings文件的步骤是:新建文件 -》 选择"Resource" -》strings file 即可,但注意这里的文件名应该与上面的table名称一致,如果table有值的话。创建好strings文件后,接下来的操作就跟前面xib中国际化差不多了。也是选中文件 -》选择localize -》勾选需要支持的语言 -》在生成的相应文件中给对应的key实现相应语言的描述即可。
4.对 Setting Bundle 的国际化
应用程序的 Setting Bundle是提供给用户在系统的“设置”程序中给应用程序做一些快捷设置或默认设置的功能。由于展示在“设置”程序中的内容是由我们自己去配置的,而在用户更改系统语言时,也并不会自动去更改这里的语言,所以我们也应该对此进行国际化设置。针对 Setting Bundle 的国际化比较简单。我们只需要在 Setting Bundle里面增加一个语言文件,并修改相应语言的描述即可。具体操作见下图:
首先我们可以看到在 Setting.bundle 文件展示下面已经有一个用于语言描述的国际化文件夹,只不过默认是英文的。
然后选中Setting.bundle文件,右键点击 Show in Finder
接着在Finder中选中Setting.bundle文件,右键点击 显示包内容
在包内容中我们会看到最初只有一个en.lproj的文件夹,此时我们需要再添加一个您需要支持的语言的文件夹,但此处命名是有规范的,不能随便乱写。如下面我增加的是中文语言支持的文件夹,其中Root.plist可以从en.lproj中copy,但copy后需要修改对应key的相应语言描述即可。(当然你也可以直接copy整个文件夹,修改一下名称即可)这样,当系统切换到相应语言时,设置中对应该应用的描述也会做相应的改变,实现国际化操作。
5.对数字的国际化
我们都知道,世界上并不是每个国家的数字表示的方式都完全一样的,可能每个国家都有各自的特点,所以当我们在界面上显示某一个数字的时候,也需要符合该用户所使用语言的特点,而不是一个固定的格式。如最为明显的货币符号。
我们之前的写法是:
CGFloat f = 10002.2; NSString *str = [NSString stringWithFormat:@“%g”, f]; //将一个CGFloat转换成NSString
上面的形式f是什么就是什么,没有任何格式可言。但在国际化中我们需要根据用户的习惯来实现。
国际化中的写法:
NSString *str = [NSNumberFormatter localizedStringFromNumber:@(10002.2) numberStyle:NSNumberFormatterDecimalStyle]; //numberStyle也可以是其它值
同时,我们在将一个字符串解析成一个数字时,也需要对其它转换后的格式进行优化:
之前可能的写法:
NSString *str = @"22000"; int value = [str intValue];
国际化中的写法:
NSString *userInputtedString = @"22223.2";//变量或字面量 NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; [formatter setNumberStyle:NSNumberFormatterDecimalStyle]; NSNumber *parsedNumber = [formatter numberFromString:userInputtedString];
6. 对日期的国际化
对于日期,这个我们接触到的可能更明显,各个国家的日期显示格式也是不尽相同的,有的年在前,有的年在后,所以当我们在界面上显示一个日期的时候,也需要根据当前用户所使用的系统语言来决定显示什么格式,而不是一个固定的格式。
方法如下:
NSString *dateStr = [NSDateFormatter localizedStringFromDate:[NSDate date] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]; //返回一个将日期“本地化”后并按指定样式格式化的字符串
7. 总结
关于国际化的内容目前主要的就这么些,后续发现再做补充。