开发java的时候要求实现语言国际化,在java中用了i18来进行处理,移动端也可以进行处理:
方法可以有以下两种:
方案一:在原国际化版本的基础上做修改,在info.plist文件中新增key="appLanguage"的键值对,保存用户设定的语言类别。通过切换语言类别来改变语言。(例子:微信)
优点:之前有国际化操作的基础,执行起来并不复杂。
缺点:切换完语言后,需要重新创建app keywindow的跟控制器,会有个跳转的过程,用户体验不好。
方案二:切换语言后,发送通知,每个控制器收到通知后,更改语言。(例子:新浪微博)
优点:很自然的切换语言,选择语言后即可切换,不需要重置根控制器,用户体验好。
缺点:每个控制器都得注册接收通知,工作量太大,而且storyboard也得单独处理。
两种方法都可实现,我们来看方案一:
中英切换,就是让App根据自身设置的语言去读取对应的国际化文件。在NSUserDefault中有一个字段:"AppleLanguages",这个字段就是负责存储App语言的字段,默认这个字段会根据系统语言去变动,中文系统他就存储中文,英文系统就存储英文。
.h文件:
// NTVLocalized.h #importstatic NSString * const AppLanguage = @"appLanguage"; @interface NTVLocalized : NSObject + (NTVLocalized *)sharedInstance; //初始化多语言功能 - (void)initLanguage; //当前语言 - (NSString *)currentLanguage; //设置要转换的语言 - (void)setLanguage:(NSString *)language; //设置为系统语言 - (void)systemLanguage; @end
.m文件:
// NTVLocalized.m #import "NTVLocalized.h" @implementation NTVLocalized + (NTVLocalized *)sharedInstance { static NTVLocalized *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[NTVLocalized alloc] init]; }); return instance; } - (void)initLanguage{ NSString *language=[self currentLanguage]; if (language.length>0) { NSLog(@"自设置语言:%@",language); }else{ [self systemLanguage]; } } - (NSString *)currentLanguage{ NSString *language=[[NSUserDefaults standardUserDefaults]objectForKey:AppLanguage]; return language; } - (void)setLanguage:(NSString *)language{ [[NSUserDefaults standardUserDefaults] setObject:language forKey:AppLanguage]; } - (void)systemLanguage{ NSString *languageCode = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"][0]; NSLog(@"系统语言:%@",languageCode); if([languageCode hasPrefix:@"zh-Hans"]){ languageCode = @"zh-Hans";//简体中文 }else if([languageCode hasPrefix:@"en"]){ languageCode = @"en";//英语 } [self setLanguage:languageCode]; } @end
当语言设置完成后,需要重新设置keywindow的rootViewController才可以实现语言的切换。
然而这样设置后,我们发现只有NSLocalizedString(key, comment)设置的语言才能正常显示我们需要的语言,storyBoard和xib配置的页面语言不跟着切换。
设置AppleLanguages字段的话,只会在下次启动App才会生效,在App启动后就已经生成了一个Bundle,里面识别好了对应着AppleLanguages的国际化文件,在App运行期间设置这个字段,是不生效的,所以我们去修改这个Bundle,写一个NSBundle的扩展。
// NSBundle+language.m #import "NSBundle+language.h" #importstatic const char _bundle = 0; @interface BundleEx : NSBundle @end @implementation BundleEx - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName { NSBundle *bundle = objc_getAssociatedObject(self, &_bundle); return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName]; } @end @implementation NSBundle (Language) + (void)setLanguage:(NSString *)language { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ object_setClass([NSBundle mainBundle], [BundleEx class]); }); objc_setAssociatedObject([NSBundle mainBundle], &_bundle, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } @end
// NSBundle+language.h #import@interface NSBundle (language) // 设置语言 + (void)setLanguage:(NSString *)language; @end
重新写一下设置语言的方法:
- (void)setLanguage:(NSString *)language{ [NSBundle setLanguage:language]; [[NSUserDefaults standardUserDefaults] setObject:language forKey:AppLanguage]; [[NSUserDefaults standardUserDefaults] synchronize]; }
修改bundle后可实现语言的全部切换,不需要重启APP
若有疑问咨询QQ:1147726728