同学面试时遇到一个问题,面试官问他,有一个现成的APP马上要上线了,怎么在不改原来代码,也不改xib、storyboard的情况下快速实现国际化。这里应同学请求写下此教程。反正国际化的步骤都要搞一遍,干脆写一个详细、全面的教程。
一、配置国际化语言
点击progect->info->localizations下的‘+’,选择你要支持的语言,默认支持英文,如下图
二、应用名称国际化
新建一个Strings File类型的文件,且名称必须为InfoPlist。
选中刚刚新建的文件,在Xcode的右侧文件检查器中点击Localize,点击Localize后,会弹出一个对话框,展开对话框列表,选择我们需要本地化的语言如English,然后点击对话框的Localize按钮。
再看Xcode右侧的File inspection变成了下图的样式,勾选需要支持的中文、英文,如下图
你刚刚新建的InfoPlist.stirings左侧多了一个箭头,点击箭头可以展开,可以看到中文、英文两个文件。在英文文件中加一句代码
CFBundleDisplayName = "LFInternationalizationDemo";
在中文文件中加一句代码
CFBundleDisplayName = "峰哥国际化示例";
运行你的APP,查看APP名称,切换手机语言,再运行你的APP,查看APP名称。
三、APP中文字国际化
和应用名称国际化一样,新建一个Strings File类型的文件,不一样的是名称必须为Localizable。在Xcode的右侧文件检查器中点击Localize,然后跟上面步骤一样直到可以展开中、英文两个Localizable.strings。
英文文件中加代码
"账号" = "Account"; "登录" = "Login";
中文文件中加代码
"账号" = "账号"; "登录" = "登录";
然后给label、button设置文字代码如下
self.lbAccount.text = NSLocalizedString(@"账号", nil); [self.btLogin setTitle:NSLocalizedString(@"登录", nil) forState:UIControlStateNormal];
四、Storyboard或XIB国际化
先将中文版或英文版中一个做好后,再进行国际化,这样会省事很多,我这里先做好了中文版。
选中storyboard,跟上面步骤一样,在Xcode的右侧文件检查器中勾选支持的语言,如下图
展开storyboard文件如下图
打开Main.strings(English),或Main.strings(Chiness),发现都是中文的。这时候你需要将Main.strings(English)中的中文改成英文。
如果你觉得密密麻麻都是文字,分不清对应哪个控件上的文字。你可以将.strings文件变成.storyboard文件,像下图这样
这时候你就可以在.storyboard文件文件上直观的改你需要改的语言。
五、图片、声音文件国际化
1.方式1
搞两套图片,一套英文命名,一套中文命名。然后跟文字国际化一样获取当前语言图片名字
NSString *imageName = NSLocalizedString(@"icon", nil); UIImage *image = [UIImage imageNamed:imageName]; self.imageView.image = image;
2.方式2
两套图片一样的名字,将其中一套图片拖到工程。选中一张图片,跟前面InfoPlist.stirings文件一样,在Xcode的右侧文件检查器中点击Localize,勾选需要支持的语言。然后,右击[email protected]>show in Finder,我们发现在en.Iproj和zh-Hans.lproj文件中多了一个名为[email protected]的图片。将这个图片换成对应语言的图片即可。
声音文件跟图片一样、不说了。
六、应用内切换语言
到手机设置里切换语言太麻烦,我们可以做成应用内切换语言。
//自动跟随系统 - (IBAction)autoLanguage:(id)sender { NSString *phoneLanguage = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]; [self changeLanguage:phoneLanguage]; } - (IBAction)chiness:(id)sender { [self changeLanguage:@"zh-Hans"]; } - (IBAction)english:(id)sender { [self changeLanguage:@"en"]; } - (void)changeLanguage:(NSString *)language { [[NSUserDefaults standardUserDefaults] setObject:@[language] forKey:@"AppleLanguages"]; [NSBundle setMainBundelLanguage:language]; NSBundle * currentMainBundel = [NSBundle getCurrentMainBundel]; UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:currentMainBundel]; MainTabBarController *tabbar = [storyboard instantiateViewControllerWithIdentifier:@"MainTabBarController"]; [UIApplication sharedApplication].keyWindow.rootViewController = tabbar; [[UIApplication sharedApplication].keyWindow makeKeyAndVisible]; }
这里setMainBundelLanguage和getCurrentMainBundel两个方法是封装在 NSBundle 的 category中,代码如下
#import "NSBundle+LF.h" #import <objc/runtime.h> static const NSString *_bundlekey = @"_bundlekey"; @interface BundleEx : NSBundle @end @implementation BundleEx - (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName { NSBundle *bundle = objc_getAssociatedObject(self, &_bundlekey); return bundle ? [bundle localizedStringForKey:key value:value table:tableName] : [super localizedStringForKey:key value:value table:tableName]; } @end @implementation NSBundle (LF) + (void)setMainBundelLanguage:(NSString *)language { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ object_setClass([NSBundle mainBundle], [BundleEx class]); }); objc_setAssociatedObject([NSBundle mainBundle], &_bundlekey, language ? [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:language ofType:@"lproj"]] : nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } + (NSBundle *)getCurrentMainBundel { NSString * currentLanguage = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"][0]; NSString *path = [[ NSBundle mainBundle ] pathForResource:currentLanguage ofType:@"lproj" ]; NSBundle * current = [NSBundle bundleWithPath:path]; return current; } @end
七、如何快速国际化一个现成APP
不知不觉写到天亮了,未完待续