iOS 多語(yǔ)言版本的開發(fā)(二)
題記
iOS 多語(yǔ)言版本的開發(fā)(一) 中我們完成了讓應(yīng)用跟隨系統(tǒng)語(yǔ)言進(jìn)行切換润讥,而用戶自己卻不能切換的功能选脊,也基本上算是實(shí)現(xiàn)了多語(yǔ)言版本至会;可是懊亡,對(duì)于某些應(yīng)用來說,實(shí)現(xiàn)跟隨系統(tǒng)語(yǔ)言切換的同時(shí)驾霜, 也想要實(shí)現(xiàn)讓用戶自己選擇應(yīng)用語(yǔ)言版本的功能案训;針對(duì)這種情況,利用這篇文章來寫寫如何讓用戶自己切換應(yīng)用語(yǔ)言版本粪糙;
語(yǔ)言文件存在的形式
想要實(shí)現(xiàn)用戶自己手動(dòng)切換語(yǔ)言版本强霎,就先要了解語(yǔ)言文件在資源文件中存在的形式;
如圖中,不管是英語(yǔ)(en.lproj)蓉冈、簡(jiǎn)體(zh-Hans.lproj)城舞、還是繁體(zh-Hant.lproj)都是以
.lproj
的文件夾形式存在, 所以當(dāng)我們要切換語(yǔ)言的時(shí)候,其實(shí)也就是做到去取這些.lproj
文件夾中的ASLocalized.strings
文件寞酿;
到這里家夺,原理應(yīng)該懂了,接下來就是動(dòng)手實(shí)現(xiàn)了伐弹;
根據(jù)語(yǔ)言獲取ASLocalized.strings
這時(shí)候拉馋,需要根據(jù)不同的語(yǔ)言.lproj
獲取到對(duì)應(yīng)的ASLocalized.strings
語(yǔ)言文件, 從而讓頁(yè)面顯示對(duì)應(yīng)的語(yǔ)言內(nèi)容;
這里暫且先根據(jù)English獲取英語(yǔ)的語(yǔ)言文件,English 的.lproj存在的形式是en.lproj
NSString *path = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
NSString *showValue = [[NSBundle bundleWithPath:path] localizedStringForKey:@"showTxt" value:nil table:@"ASLocalized"];
NSLog(@"result: %@", showValue);
輸出結(jié)果:result: this is test text
以上代碼惨好,只是以English 為語(yǔ)言文件煌茴,是寫死的,如果想要讓用戶自己手動(dòng)改變日川,只需要替換掉[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"]
中的en
為其他的語(yǔ)言標(biāo)識(shí)就好了蔓腐; 既然是用戶手動(dòng)切換,那就需要寫代碼去實(shí)現(xiàn)了龄句;
到這里回论,有一個(gè)問題散罕,如何讓用戶選擇后一個(gè)語(yǔ)言后,即使程序退出后傀蓉,下次進(jìn)入依然保留呢笨使, 既然需要保存數(shù)據(jù),就要涉及到本地存儲(chǔ)了僚害,對(duì)于少量的保存我們可以使用NSUserDefaults
來操作硫椰,簡(jiǎn)單方便快捷;至于其他的存儲(chǔ)方式四大基本對(duì)象的write方法萨蚕,歸檔靶草,sqllite,CoreData 需要的同學(xué)岳遥,可以自己去腦補(bǔ)奕翔,這里我不多介紹了;
使用NSUserDefaults 記錄選擇的語(yǔ)言
這里我簡(jiǎn)單寫了個(gè)界面浩蓉,作為輔助講解
- (IBAction)changeLanguage:(UIButton *)sender {
switch (sender.tag) {
case 101: { //簡(jiǎn)體
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hans" forKey:appLanguage];
}
break;
case 102: { //繁體
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hant" forKey:appLanguage];
}
break;
case 103: { //English
[[NSUserDefaults standardUserDefaults] setObject:@"en" forKey:appLanguage];
}
break;
default:
break;
}
}
以上方法派继,是圖中三種語(yǔ)言的點(diǎn)擊事件,分別將對(duì)應(yīng)的語(yǔ)言標(biāo)識(shí)捻艳,記錄到NSUserDefaults
對(duì)應(yīng)的 appLanguage
key 中
既然重新選擇了語(yǔ)言驾窟,就需要重新加載控件的內(nèi)容,因?yàn)槭荄emo??认轨,這里直接將給控件賦值寫成一個(gè)方法绅络,如下:
- (void)showLbl {
NSString *lanType =[NSString stringWithFormat:@"%@", [[NSUserDefaults standardUserDefaults] objectForKey:@"appLanguage"]];
NSString *path = [[NSBundle mainBundle] pathForResource:lanType ofType:@"lproj"];
NSString *showValue = [[NSBundle bundleWithPath:path] localizedStringForKey:@"showTxt" value:nil table:@"ASLocalized"];
NSLog(@"result: %@", showValue);
self.lblShowTxt.text = showValue;
}
可將此方法在點(diǎn)擊事件中調(diào)用下,即可嘁字;
Demo效果圖:
首次進(jìn)入應(yīng)用的考慮
到這里恩急,還沒有完,這時(shí)我們需要考慮下纪蜒,用戶第一次進(jìn)來時(shí)衷恭,該顯示什么樣的語(yǔ)言,是跟隨系統(tǒng)纯续,還是我們給一種默認(rèn)的語(yǔ)言随珠;
1、給一種默認(rèn)語(yǔ)言
這種處理很簡(jiǎn)單杆烁,只需要在didFinishLaunchingWithOptions
方法中牙丽,進(jìn)行判斷本地是否記錄了語(yǔ)言標(biāo)識(shí),如果沒有給一種默認(rèn)即可兔魂,代碼如下:
if (![[NSUserDefaults standardUserDefaults] objectForKey:appLanguage]) {
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hans" forKey:appLanguage];
}
2、跟隨系統(tǒng)語(yǔ)言
這種處理相對(duì)來說举娩,比較復(fù)雜寫析校,首頁(yè)需要獲取系統(tǒng)的首選語(yǔ)言順序构罗,然后取第一個(gè)首選語(yǔ)言,其次智玻,還要判斷你要做的語(yǔ)言版本遂唧,首選語(yǔ)言組中存在與否;
獲取首選語(yǔ)言:NSArray *languages = [NSLocale preferredLanguages];
獲取第一個(gè)首選語(yǔ)言: NSString *language = [languages objectAtIndex:0];
處理過程如下:
if (![[NSUserDefaults standardUserDefaults] objectForKey:appLanguage]) {
NSArray *languages = [NSLocale preferredLanguages];
NSString *language = [languages objectAtIndex:0];
if ([language hasPrefix:@"zh-Hans"]) {
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hans" forKey:appLanguage];
} else if ([language hasPrefix:@"zh-TW"] || [language hasPrefix:@"zh-HK"] || [language hasPrefix:@"zh-Hant"]) {
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hant" forKey:appLanguage];
} else if ([language hasPrefix:@"en"]) {
[[NSUserDefaults standardUserDefaults] setObject:@"en" forKey:appLanguage];
}else{
[[NSUserDefaults standardUserDefaults] setObject:@"zh-Hans" forKey:appLanguage];
}
}
注:由于繁體又有臺(tái)灣繁體和香港繁體之分吊奢,所以代碼中也做出了相應(yīng)的處理盖彭;
╮(╯▽╰)╭ 到了這里基本上算是完成了多語(yǔ)言版本的工作了,但是页滚,但是召边,但是,這只是完成了項(xiàng)目起步期裹驰,項(xiàng)目中還不存在大量的中文字符串的情況隧熙;暫時(shí)先不考慮項(xiàng)目已經(jīng)開發(fā)完成的情況,接下來先來優(yōu)化下幻林,我們剛剛寫過的代碼贞盯;
對(duì)于showLbl
方法中的內(nèi)容,可以定義成宏沪饺,以供項(xiàng)目中躏敢,任何地方需要多元化時(shí)的使用;
#define ASLocalizedString(key) [NSString stringWithFormat:@"%@", [[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"%@",[[NSUserDefaults standardUserDefaults] objectForKey:@"appLanguage"]] ofType:@"lproj"]] localizedStringForKey:(key) value:nil table:@"ASLocalized"]]
為了方便,我將showLbl 中取key對(duì)應(yīng)的語(yǔ)言內(nèi)容整葡,封裝進(jìn)了一個(gè)帶參數(shù)的宏中父丰;
使用起來就很Easy了,只需要這樣使用即可:ASLocalizedString(@"showTxt")