/Localizing

轻松搞定StoaryBoard / Xib多语言,App内切换多语言

Primary LanguageObjective-C

Localizing

###本文会用gif详细演示如何支持多语言,如何轻松搞定StroaryBoard / Xib的多语言,以及App内切换多语言。最后 说下加上参数 和 参数顺序的NSLocalizedString

#首先让程序支持多语言

  • 创建一个 Localizable 名字的文件,注意 L 一定要大写
  • 切换到 Project 里,添加需要支持的语言,这里只做支持英文 中文 Localize1.gif

#上面步骤完后,会出现两个文件Localizable.strings(English) Localizable.strings(Simplified)

以 "key" = "value" 的方式添加多语言,如下图,左边的是英文,右边的是中文 image.png

代码用NSLocalizedString(@"key", nil)调用 如:

self.label.text = NSLocalizedString(@"password", nil); [self.button setTitle:NSLocalizedString(@"press", nil) forState:UIControlStateNormal];

Localize2.gif

#StoaryBoard/Xib多语言 #####通常如果StoaryBoard / Xib要支持多语言,有两种方法

  • 一个是 image.png 在Localization里勾选相应的Localizable Strings,这样每个StoaryBoard / Xib 都生成对应的几个Localizable Strings文件,一旦界面有改动,并不会同步到Localizable Strings文件里,很麻烦。

  • 第二个办法 就是IBOutlet每个需要多语言的控件,有很多控件的文字就是写死的,这样做也是很麻烦

#####本文给出两个方法是让你在StoaryBoard / Xib界面上直接支持多语言 如 UILabel 控件,为UILable生成一个分类UILabel + XIBLocalizable,同理其他UIButton UITextField UITextVIew等都可以生成对应的分类,这里只举UILable作为例子。

  • 第一个办法利用IBInspectable修饰属性
@interface UILabel (XIBLocalizabe)
@property (nonatomic, copy)IBInspectable NSString *xibLocKey;
@end

@implementation UILabel (XIBLocalizabe)

  • (void)setXibLocKey:(NSString *)xibLocKey{ self.text = xibLocKey.localized; }
  • (NSString *)xibLocKey{ return nil; } @end

这样在界面上会多出一个Label属性,赋值上多语言对应的key值即可

171540263200_.pic.jpg

Localize3.gif

  • 第二个办法 其实已经完成了,上面实现了setXibLocKey方法,我们可以在User Defined Runtime Attributes添加xibLocKey这个Key Path image.png Localize4.gif

#App内切换多语言 这里引用了别人实现的 NSBundle+AppLanguageSwitch 简单讲讲实现过程

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object_setClass([NSBundle mainBundle],[ZZBundleEx class]);
NSString *language = [self getCusLanguage];
if (language) {
[self setCusLanguage:language];
}
});
}

这里用了runtime的object_setClass,意思是将[NSBundle mainBundle]的对象指定到 ZZBundleEx 这个类上

@interface ZZBundleEx : NSBundle
@end

@implementation ZZBundleEx
/*ZZBundleEx继承自NSBundle
并重写了 - (NSString *)localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName 方法
从NSBundle+AppLanguageSwitch的分类里取出关联属性 NSBundle值 ,这个值(即xxx.lproj的一个文件)是我们在分类里设定的对应语言的值,所以能达到在APP内切换语言的效果
bundle :  .../Localizing.app/zh-Hans.lproj  中文
bundle :  .../Localizing.app/en.lproj  英文
*/
- (NSString *)localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)tableName {
NSBundle *bundle = objc_getAssociatedObject(self, &kBundleKey);
if (bundle) {
return [bundle localizedStringForKey:key value:value table:tableName];
} else {
return [super localizedStringForKey:key value:value table:tableName];
}
}
@end

Localize5.gif

NSLocalizedString加上参数 并且根据语言的不同指定参数的顺序

Locaizable.strings(Chinese (Simplified))

"birth" = "我出生在 %@";
"from" = "我是来自%1$@的%2$@";

Locaizable.strings(English)

"birth" = "I was born in %@";
"from" = "I am %2$@ from %1$@";

ViewController.m

//带参数的 NSLocalizedString
self.birthLabel.text = [NSString stringWithFormat:NSLocalizedString(@"birth", nil),@"shenzhen"];

//带参数 并且可以指定顺序的 NSLocalizedString
self.fromLabel.text = [NSString stringWithFormat:NSLocalizedString(@"from", nil),@"shenzhen",@"hjn"];

看下效果 localizedstring_1.gif

应该很直观了吧,带参数的话本地化文件里直接用%@代替,代码里用[NSString stringWithFormat:...]包裹,至于顺序就把 %@ 变成 %1$@ 的代表放入第一参数的值... 以此类推

#Demo 最后附上 github Demo