Demo下載地址:https://github.com/StarHuiDream/Multilingual
前序:
國際化锋边,多語言,App 本地化尊勿。是一個意思僧凤,就是讓App 支持多種語言用狱。國際化處理其實并不難,本文將講解國際化的基本解決方案拼弃。對app 文案國際化的時候需要注意UI的適配夏伊,因為不同的語言環(huán)境下,不同的文案的長度是不一樣的吻氧,所以這個處理起來很麻煩溺忧,而且很容易遺漏。
本文的組成:
一盯孙、App 名字的國際化
二鲁森、申請使用一些系統(tǒng)權(quán)限提示語的國際化
三、App 里面文案的國際化
四振惰、App 插件widget (today Extension)的國際化
一歌溉、App 名字的國際化
1、給項目添加本地語言包:
將App 要支持的國家或地區(qū)的語言在這里添加到工程里面骑晶。
添加完之后是這樣的:
2痛垛、添加語言文件夾
(1)選中項目文件夾,選擇New File
(2)選擇String File桶蛔,然后點擊Next
(3)將文件夾名改為InfoPlist
3匙头、將剛才導(dǎo)入的語言包導(dǎo)入到多語言文件夾
(1)選中 InfoPlist.strings 然后點擊 localize
(2)點擊localize之后會有一個彈框提示,直接點擊localize就行仔雷。
(3)將剛才在第一步添加的多語言文件都打上對勾蹂析。如下圖。
4碟婆、在對應(yīng)的語言文件里面寫上app 的名稱
InfoPlist.strings(Chinese (Simplifled))中文簡體
// app 的簡體中文名字
CFBundleDisplayName = "簡體";
InfoPlist.strings(Chinese (Traditional))中文繁體
// app 的繁體中文名字
CFBundleDisplayName = "繁體";
InfoPlist.strings(English)英文
// app 的繁體英文名字
CFBundleDisplayName = "English";
CFBundleDisplayName 是App 在手機桌面上展示的名稱电抚。
然后切換手機系統(tǒng)的語言,我們就可以看見在不同語言下App 的名稱竖共。
二蝙叛、申請使用一些系統(tǒng)權(quán)限提示語的國際化
iOS 10 之后如果App 想要訪問日歷和提醒事項以及定位,相冊肘迎,相機的等的使用權(quán)限的話甥温,我們必須在 我們的app 的Info.plist文件中添加相應(yīng)的關(guān)鍵字以及申請權(quán)限時候的提示語锻煌。
下面以申請使用定位權(quán)限為例:申請使用定位權(quán)限需要在工程的Info.plist文件中添加NSLocationWhenInUseUsageDescription 妓布,然后在后面寫上申請的理由。如下圖:
然后app 在使用定位權(quán)限的時候會把我們寫的申請理由彈框出來如下圖:
但是這種只支持一種語言宋梧。如果想做成在不同語言環(huán)境下提示不同的語言匣沼,需要我們在InfoPlist.strings 里面添加相應(yīng)的提示語。操作步驟和將app 名字國際化一樣捂龄。
如下圖:
NSLocationWhenInUseUsageDescription = "我們需要你的位置";
然后切換系統(tǒng)語言之后释涛,我們查看權(quán)限提示如下圖
三加叁、App 里面文案的國際化
內(nèi)容的國際化,包括頁面標(biāo)題唇撬,個個展示元素等等的國際化它匕。
1、添加Localizable.strings文件夾
這個步驟語可以參照第一章窖认,只是把文件夾名命名成Localizable就可以豫柬。然后將多語言文件導(dǎo)入文件夾,這一步也可以參照第一章扑浸。這里就不贅述了烧给。添加完成之后是這樣的。
2喝噪、頁面內(nèi)容的國際化主要包括以下三個方面
(1)將國際化文案預(yù)填進(jìn)對應(yīng)的語言文件
國際化文案由一個key 和對應(yīng)的文案組成,例如上圖础嫡,“生如夏花之絢爛,死如秋葉之靜美”是key ,后面的“生如夏花之絢爛,死如秋葉之靜美”酝惧,是它在中文繁體下對應(yīng)的文案榴鼎。
//中文繁體
"生如夏花之絢爛,死如秋葉之靜美"="生如夏花之絢爛,死如秋葉之靜美";
//中文簡體
"生如夏花之絢爛,死如秋葉之靜美"="生如夏花之絢爛,死如秋葉之靜美";
//英文
"生如夏花之絢爛,死如秋葉之靜美"="Let life be beautiful like summer flowers and death like autumn leaves";
注意:每個文案的key 在三個文件里面要保持一樣。
(2)獲取用戶給app 設(shè)置的語言晚唇。
NSString * _Nonnull const languageFileKey = @"languageFileKey";
+ (NSString *)fetchLangFileName{
NSString *languageFileNameStr = [[NSUserDefaults standardUserDefaults] stringForKey:languageFileKey];
// (1)這里根據(jù)自己的需求處理檬贰,
// (2)我的的處理方式是:用戶第一次使用app的時候,先獲取用戶系統(tǒng)的語言缺亮,如果用戶手機的語言我們做了國際化翁涤,我們將用戶的手機的當(dāng)前語言設(shè)置成app的語言,如果用戶手機系統(tǒng)的語言我們沒有做相應(yīng)的國際化處理萌踱,我直接將app的語言設(shè)置成英文葵礼,
// (3)注意:用這種方式獲取的用戶語言后面會打個-US(像這樣“zh-Hant-US”),但是語言包名后面沒這個所以需要處理一下
if (languageFileNameStr == nil || [languageFileNameStr isEqualToString:@""]) {
NSArray* languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"];
languageFileNameStr = [languages objectAtIndex:0];
if ([languageFileNameStr containsString:@"zh-Hant"]) {
languageFileNameStr = @"zh-Hant";
}else if ([languageFileNameStr containsString:@"zh-Hans"]){
languageFileNameStr = @"zh-Hans";
}else{
languageFileNameStr = @"en";
}
[STLanguageTool saveUserLocalLang:languageFileNameStr];
}
return languageFileNameStr;
}
+ (void)saveUserLocalLang:(NSString *_Nonnull)langFileName{
[[NSUserDefaults standardUserDefaults] setObject:langFileName forKey:languageFileKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
(3)通過NSLocalizedStringFromTableInBundle將相應(yīng)的語言渲染出來并鸵。
這里我們將這個方法定義成一個宏鸳粉,這樣在開發(fā)的時候就方便了
#define STLANG(key) NSLocalizedStringFromTableInBundle(key, @"Localizable", [STLanguageTool localizedBundle], nil)
+ (NSBundle *_Nonnull)localizedBundle{
NSString *langFileNameStr = [STLanguageTool fetchLangFileName];
NSString *path = [[NSBundle mainBundle] pathForResource:langFileNameStr ofType:@"lproj"];
NSBundle *mBundle = [NSBundle bundleWithPath:path];
return mBundle;
}
使用如下:
self.title = STLANG(@"第二個頁面");
self.textLabel.text = STLANG(@"生如夏花之絢爛,死如秋葉之靜美");
做到這一步,我們已經(jīng)實現(xiàn)了app 內(nèi)容的國際化园担,但是我們會發(fā)現(xiàn)這樣一個問題:每次切換語言的時候届谈,當(dāng)前頁面的語言是沒有發(fā)生變化的,原因是弯汰,當(dāng)前切換語言的頁面艰山,是已經(jīng)渲染過后的,所以每次切換語言的時候要對已經(jīng)渲染過的頁面要進(jìn)行一些特殊處理咏闪。我這里采用發(fā)送通知的方式對這個問題進(jìn)行處理曙搬。
+ (void)saveUserLocalLang:(NSString *_Nonnull)langFileName{
[[NSUserDefaults standardUserDefaults] setObject:langFileName forKey:languageFileKey];
[[NSUserDefaults standardUserDefaults] synchronize];
// 發(fā)送通知
[[NSNotificationCenter defaultCenter] postNotificationName:LangChangeNotification object:nil];
}
// 在已經(jīng)渲染過的頁面注冊通知
// 注冊通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(langChange)
name:LangChangeNotification
object:nil];
// 在已經(jīng)渲染過的頁面接受通知
-(void)langChange{
self.title = STLANG(@"第一個頁面");
self.contentLabel.text = STLANG(@"生如夏花之絢爛,死如秋葉之靜美");
[self.nextBtn setTitle:STLANG(@"下一頁") forState:UIControlStateNormal];
}
四、App 插件widget (today Extension)的國際化
1、widget(today Extension)
關(guān)于widget(today Extension)的開發(fā)可以參考我的另一篇文章 iOS 插件開發(fā)之 today widget
2纵装、引入國際化文案
在項目中創(chuàng)建完插件之后征讲,我們前面創(chuàng)建好的語言文件共享到today Extension,選中InfoPlist.string 然后在項目對應(yīng)的widget 處打上對勾橡娄,如下圖:
然后以同樣的方法將Localizable.strings诗箍,引入到widget。
3挽唉、widget 名字的國際化
將widge 的 info.plist 中的Bundle display name 對應(yīng)值修改成${PRODUCT_NAME}(這樣就和app 的名稱保持一致了)扳还。如下圖
${PRODUCT_NAME}
運行結(jié)果如下
4、widget 內(nèi)的國際化
選中我們之前分裝好的語言工具類的.m 文件將它引入widget橱夭。
引入語言工具之后氨距,我們就可像處理app 的國際化一樣對widget 進(jìn)行國際化。
// 注意這里要根據(jù)自己的需求來處理棘劣,如果想讓widget 語言與App 保持一致的話俏让,需要將用戶每次操作選擇的語言保存到appGroup 這樣,widget 才能訪問茬暇,
// 我這里的處理是讓widget 的語言和手機系統(tǒng)的保持一致首昔。
self.textLabel.text = STSYSLANG(@"生如夏花之絢爛,死如秋葉之靜美");