iOS國際化原理分析
國際化其實(shí)都大同小異姿染,其核心思想就是為每種語言單獨(dú)定義一份資源背亥。
iOS就是通過xxx.lproj目錄來定義每個(gè)語言的資源,這里的資源可以是圖片悬赏,文本狡汉,Storyboard,Xib等闽颇。我們在項(xiàng)目中可以看到的物理目錄結(jié)構(gòu)
每種語言都有自己的語言代碼.lproj文件夾盾戴,加載資源時(shí)只需要加載相應(yīng)語言文件夾下的資源就OK,這步可以系統(tǒng)為我們完成兵多,也可以手動去做尖啡。
一、 根據(jù)本地設(shè)置自動切換國際化語言
1. 添加項(xiàng)目支持的國際化語言剩膘。
首先點(diǎn)擊項(xiàng)目->PROJECT->Info->Localizations中添加要支持的語言.
此處Use Base Internationalization開啟狀態(tài)下衅斩,每個(gè)國際化資源文件會有個(gè)Base選項(xiàng),主要針對String援雇,Storyboard矛渴,Xib作為一個(gè)基礎(chǔ)的模板。
在點(diǎn)擊+ 添加相應(yīng)語言時(shí)會彈出以下對話框惫搏,意思是為現(xiàn)有的資源添加語言文件具温,我們點(diǎn)擊Finish就行了.
2.創(chuàng)建Localizable.strings文件,它是iOS默認(rèn)加載的文件筐赔,如果想用自定義名稱命名铣猩,在使用NSLocalizedString方法時(shí)指定tableName為自定義名稱就好了,但你的應(yīng)用規(guī)模不是很大就不要分模塊搞特殊了茴丰。
每個(gè)資源文件如果想為一種語言添加支持达皿,通過其屬性面板中的Localization添加相應(yīng)語言就行了天吓,此時(shí)Localizable.strings處于可展開狀態(tài),子級有著相應(yīng)語言的副本峦椰。我們把相應(yīng)語言的文本放在副本里面就行了.
3. ?在string文件中創(chuàng)建相應(yīng)的key龄寞,value值,類似于這樣汤功。
然后就是創(chuàng)建宏了
#define MyNSLocalizedString(key)? ? NSLocalizedString(key, nil)
這樣在每個(gè)賦值的地方都用到這宏來賦值物邑。
注意啦,這里只是最基本的做法滔金,現(xiàn)在告訴大家一個(gè)偷懶的方法色解,那就是給需要賦值的控件添加分類,然后通過runtime機(jī)制餐茵,將給控件設(shè)置文本的方法替換成自己的方法科阎,然后再里面實(shí)現(xiàn)國際化操作。下面以UILabel的分類為例
```
#import "UILabel+SGLocalizable.h"
#import@implementation UILabel (SGLocalizable)
- (void)setNeedChange:(BOOL)needChange
{
?objc_setAssociatedObject(self, @"needChange", @(needChange), ? ? ? ? OBJC_ASSOCIATION_ASSIGN);
}
- (BOOL)needChange
{
return [objc_getAssociatedObject(self, @"needChange") boolValue];
}
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalInitSelector = @selector(setText:);
Method originalInitMethod = class_getInstanceMethod(class, originalInitSelector);
SEL swizzledInitSelector = @selector(setSGText:);
Method swizzledInitMethod = class_getInstanceMethod(class, swizzledInitSelector);
BOOL didInitAddMethod =
class_addMethod(class,
originalInitSelector,
method_getImplementation(swizzledInitMethod),
method_getTypeEncoding(swizzledInitMethod));
if (didInitAddMethod) {
class_replaceMethod(class,
swizzledInitSelector,
method_getImplementation(originalInitMethod),
method_getTypeEncoding(originalInitMethod));
} else {
method_exchangeImplementations(originalInitMethod, swizzledInitMethod);
}
});
}
- (void)setSGText:(NSString *)text
{
if (self.needChange == YES)
{
[self setSGText:text];
}
else
{
//? ? ? ? NSString *str = MyNSLocalizedString(text);
[self setSGText:DTGetStringWithKeyFromTable(text,@"Localizable")];
}
}
```
二忿族、 應(yīng)用內(nèi)切換國際化語言
應(yīng)用內(nèi)切換語言锣笨,實(shí)際上就是根據(jù)其原理來設(shè)置的。上面已經(jīng)講到道批,iOS就是通過xxx.lproj目錄來定義每個(gè)語言的資源票唆。
1. 首先創(chuàng)建一個(gè)國際化的管理類
```
+ (id)sharedInstance
{
if (!sharedModel)
{
sharedModel = [[DTLanguageUtils alloc]init];
}
return sharedModel;
}
-(instancetype)init
{
self = [super init];
if (self)
{
[self initLanguage];
}
return self;
}
```
在初始化的時(shí)候需要判斷當(dāng)前的系統(tǒng)設(shè)置是何種語言。
```
languageStr = [[[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"] firstObject]];
```
得到的languageStr就是資源文件夾的名稱 比如zh-Hans屹徘,en走趋。
2. 然后接下來是設(shè)置語言。
```
-(void)setNewLanguage:(LanguageType )language{
if (language ==self.languageType)
{
return;
}
switch (language) {
case LanguageTypeZHCN:
{
NSString *path = [[NSBundle mainBundle]pathForResource:CNS ofType:@"lproj"];
self.bundle = [NSBundle bundleWithPath:path];
}
break;
case LanguageTypeZHTK:
{
NSString *path = [[NSBundle mainBundle]pathForResource:CNT ofType:@"lproj"];
self.bundle = [NSBundle bundleWithPath:path];
}
break;
case LanguageTypeEN:
{
NSString *path = [[NSBundle mainBundle]pathForResource:EN ofType:@"lproj"];
self.bundle = [NSBundle bundleWithPath:path];
}
break;
default:
break;
}
self.languageType = language;
[MyUserDefaults setObject:@(language) forKey:LanguageMode];
[MyUserDefaults synchronize];
[self resetRootViewController];
}
/**
*? 返回table中指定的key的值
*
*? @param key? key
*? @param table table
*
*? @return 返回table中指定的key的值
*/
-(NSString *)getStringForKey:(NSString *)key withTable:(NSString *)table
{
if (self.bundle)
{
return NSLocalizedStringFromTableInBundle(key, table, self.bundle, @"");
}
return NSLocalizedStringFromTable(key, table, @"");
}
```
最后就是定義一個(gè)獲取多語言的宏了
#define DTGetStringWithKeyFromTable(key, tbl)? ? ? [[DTLanguageUtils sharedInstance] getStringForKey:key withTable:tbl]
完結(jié)