一,新启动的工程
1.找到Project的Localizations选项,点击加号(+),添加需要国际化的语言(一般工程中默认支持英文,为了方便演示,我只添加了中文简体支持)。此时会弹出一个选择框,选择你所要支持的Xib文件或StoryBoard文件。不需要支持Xib或StoryBoard文件则不勾选。
这里Use Base Internationalization开启状态下,每个国际化资源文件会有个Base选项,主要针对String,Xib,Storyboard作为一个基础的模板。
2.创建多语言文件,一般命名为Localizable.string。如果在开发过程中不指定文件名,系统会默认在Bundle中寻找这个名称的文件。当然,也可以任意命名,在开发过程中手动指定一下文件名即可。
3.找到并选中刚刚新建的Localizable.string文件,点击Inspector下Localization选项下的Localize按钮,任意选择一个语言(我选择的是English),然后点击Localize按钮,此时Localization选项会出现应用支持的语言列表,选择需要国际化的语言,Localizable.string文件下则会多出和所选择语言对应的子文件。
ViewController中初始化了一个Label,并用NSLocalized宏对这个Label的字符串进行国际化适配。
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *localizationLabel = [[UILabel alloc] initWithFrame:CGRectMake(150, 200, 100, 20)];
[self.view addSubview:localizationLabel];
//利用NSLocalizedString宏对字符串进行国际化适配
localizationLabel.text = NSLocalizedString(@"Hello", @"description for this key.");
}
宏定义的解析
《1》NSLocalizedString(key, comment)
NSLocalizedString其实是从mainBundle中默认读取了Localizable.string中的key所对应的value。comment参数则是对key的描述,有利于翻译人员理解这个key所适用的场景。
《2》NSLocalizedStringFromTable(key, tbl, comment)
NSLocalizedStringFromTable则是从mainBundle中读取指定多语言文件中的key所对应的value。tbl参数就是用于指定多语言文件名的参数。
《3》NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment)
NSLocalizedStringFromTableInBundle会读取指定Bundle中所指定的多语言文件中的key所对应的value。bundle参数就是用于传入所指定的Bundle。
《4》NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment)
NSLocalizedStringWithDefaultValue则是从指定Bundle中读取指定多语言文件中的key所对应的value,如果取不到对应的value,允许指定一个默认的value。val参数就是用于传入默认的value值。
在Localizable.strings(English)中加入如下键值对:
"Hello" = "Hello";
在Localizable.strings(Chinese(Simplified))中加入如下键值对:
"Hello" = "你好";
至此,一个简单的可以跟随系统语言切换的Demo就完成了。
二,替换系统国际化宏定义
由系统宏定义可知,如果使用了系统的NSLocalizedString宏,它是默认是从mainBundle中读取Localizable.strings中的value的。使用其他的3个宏则可以指定文件名或是Bundle,但是使用起来也是不太灵活。为了使用起来更加方便灵活,我们可以自定义一个国际化的宏,实现其内部的逻辑。
下面,给出一种我自己的实现方式。
#import <Foundation/Foundation.h>
//语言国际化
#define CustomLocalizedSting(key) [[CustomLocalized standardCustom] stringWithKey:key]
@interface CustomLocalized : NSObject
+ (instancetype)standardCustom;
- (NSBundle *)bundle;
- (NSString *)currentLanguage;
- (void)setUserLanguage:(NSString *)language;
- (NSString *)stringWithKey:(NSString *)key;
@end
#import "CustomLocalized.h"
static NSBundle *_bundle;
static NSString *const kUserLanguage = @"kUserLanguage";
@implementation CustomLocalized
+ (instancetype)standardCustom {
static CustomLocalized *customer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
customer = [[CustomLocalized alloc] init];
});
return customer;
}
- (instancetype)init {
if (self = [super init]) {
if (!_bundle) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userLanguage = [defaults valueForKey:kUserLanguage];
//用户未手动设置过语言
if (userLanguage.length == 0) {
NSArray *languages = [[NSBundle mainBundle] preferredLocalizations];
NSString *systemLanguage = languages.firstObject;
userLanguage = systemLanguage;
}
if ([userLanguage isEqualToString:@"zh-HK"] || [userLanguage isEqualToString:@"zh-TW"]) {
userLanguage = @"zh-Hant";
}
NSString *path = [[NSBundle mainBundle] pathForResource:userLanguage ofType:@"lproj"];
_bundle = [NSBundle bundleWithPath:path];
}
}
return self;
}
- (NSBundle *)bundle {
return _bundle;
}
- (NSString *)currentLanguage {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userLanguage = [defaults valueForKey:kUserLanguage];
if (userLanguage.length == 0) {
NSArray *languages = [[NSBundle mainBundle] preferredLocalizations];
NSString *systemLanguage = languages.firstObject;
return systemLanguage;
}
return userLanguage;
}
- (void)setUserLanguage:(NSString *)language {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *path = [[NSBundle mainBundle] pathForResource:language ofType:@"lproj"];
_bundle = [NSBundle bundleWithPath:path];
[defaults setValue:language forKey:kUserLanguage];
[defaults synchronize];
}
- (NSString *)stringWithKey:(NSString *)key {
if (_bundle) {
return [_bundle localizedStringForKey:key value:nil table:@"Localizable"];
}else {
return NSLocalizedString(key, nil);
}
}
@end
使用的时候,只需把原来NSLocalizedString(key, nil)的地方替换为CustomLocalizedSting(key)即可。此时如果用户没有手动更改过语言,默认是跟随系统语言变化的