iOS應(yīng)用的本地化原理,是通過(guò)
strings
類型的文件,為同一種語(yǔ)言的不同翻譯設(shè)置翻譯表,應(yīng)用再根據(jù)用戶系統(tǒng)語(yǔ)言自動(dòng)檢索翻譯表通過(guò)對(duì)應(yīng)的鍵值對(duì)實(shí)現(xiàn)的。
NSBundle
在iOS應(yīng)用中,bundle的概念非常重要,可以理解為一些文件的集合。為此,蘋果的工程師們留下了NSBundle這個(gè)類,用于操作bundle內(nèi)的文件。而NSBundle類中的一些特定方法,則是給一些特定的文件實(shí)用的。
例如infoDictionary
用于讀取bundle中的info.plist文件。
@property (nullable, readonly, copy) NSDictionary<NSString *, id> *infoDictionary;
當(dāng)然還有我們今天要講的本地化方法
/* Method for retrieving localized strings. */
- (NSString *)localizedStringForKey:(NSString *)key value:(nullable NSString *)value table:(nullable NSString *)tableName NS_FORMAT_ARGUMENT(1);
這個(gè)方法就是用來(lái)讀去bundle中本地化字段的方法。而在日常使用中,我們用的更多的是兩個(gè)簡(jiǎn)化的宏:
NSLocalizedString(<#key#>, <#comment#>)
NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
宏定義
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:nil]
#define NSLocalizedStringFromTable(key, tbl, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment) \
[bundle localizedStringForKey:(key) value:@"" table:(tbl)]
#define NSLocalizedStringWithDefaultValue(key, tbl, bundle, val, comment) \
[bundle localizedStringForKey:(key) value:(val) table:(tbl)]
key
參數(shù)必填,comment
作為注釋參數(shù),是不影響返回值的,可以傳nil。
默認(rèn)本地化文件
新工程中是不包含本地化文件的,如果要給應(yīng)用添加本地化,首先需要添加Localizable.strings
文件。
Localizable.strings
文件就是本地化文件中的默認(rèn)文件,名字不要打錯(cuò),當(dāng)你使用NSLocalizedString(<#key#>, <#comment#>)
宏時(shí),不用輸入table名稱,便是默認(rèn)使用Localizable.strings
文件作為翻譯表。
如果你還有其他的翻譯表文件,例如other.strings,你可以這樣使用
NSLocalizedStringFromTable(@"你好", @"other", nil)
當(dāng)然現(xiàn)在并不會(huì)將你好翻譯成其他語(yǔ)言,下一步,你需要設(shè)置你的翻譯表。
Localizable.strings格式
strings文件的格式非常簡(jiǎn)單,但如果格式有錯(cuò),編譯器會(huì)報(bào)錯(cuò),并且不會(huì)提醒你到底哪里錯(cuò)了,所以務(wù)必要仔細(xì)。如下
"你好" = "你好";
- 每一行一句,等號(hào)前面是key,等號(hào)后面是value,引號(hào)前不加
@
,分號(hào)結(jié)尾。 - 當(dāng)添加多種語(yǔ)言后,同一個(gè)文件將會(huì)有不同語(yǔ)言的副本,存在工程目錄下的不同本地化文件夾中,但在xcode中還是以同一個(gè)文件顯示,但可以下拉切換語(yǔ)言進(jìn)行編輯。
添加本地化語(yǔ)言的方法如下,先選中strings
文件,然后又邊點(diǎn)擊Localize
按鈕,然后選項(xiàng)中會(huì)有Base和English兩個(gè)選項(xiàng),確認(rèn)后,這里會(huì)出現(xiàn)多選框,選取哪種語(yǔ)言,便會(huì)自動(dòng)生成對(duì)應(yīng)的副本。
添加其他語(yǔ)言
如圖選擇Project的Info標(biāo)簽,設(shè)置Localization選項(xiàng)
實(shí)戰(zhàn)
這里我們添加了簡(jiǎn)體中文和英文,對(duì)應(yīng)的Localizable.strings文件多了兩個(gè)副本。
各個(gè)文件中的內(nèi)容如下
//英語(yǔ)Localizable.strings(English)文件
"你好" = "hello";
//簡(jiǎn)體中文Localizable.strings(Simplified)文件
"你好" = "你好";
這樣一來(lái),當(dāng)我們?cè)诖a中使用"你好"這個(gè)key時(shí),系統(tǒng)便會(huì)自動(dòng)根據(jù)我們的系統(tǒng)語(yǔ)言,進(jìn)行本地化替換,當(dāng)系統(tǒng)語(yǔ)言并非我們本地化支持的語(yǔ)言時(shí),例如我們并未加入韓語(yǔ),本地化接口便會(huì)把key的默認(rèn)語(yǔ)言的本地化內(nèi)容返回,或者根據(jù)設(shè)備的第二語(yǔ)言進(jìn)行返回。當(dāng)使用的key并不存在時(shí),則會(huì)把key作為value返回。
xib和storyboard本地化
xib
和storyboard
作為兩種不同類型的UI工具,他們的本地化,既可以通過(guò)代碼修改,也可以直接對(duì)xib和storyboard文件進(jìn)行本地化操作,操作類似strings文件的Localize操作,見(jiàn)下圖
選中文件后,點(diǎn)擊右邊欄Localize
按鈕,勾選對(duì)應(yīng)語(yǔ)言。
這樣我們發(fā)現(xiàn)在Storyboard文件中,包含了Chinese版本的Strings文件,內(nèi)容如下
/* Class = "UILabel"; text = "用戶名"; ObjectID = "8f2-qK-7KS"; */
"8f2-qK-7KS.text" = "用戶名";
/* Class = "UIButton"; normalTitle = "登錄或注冊(cè)"; ObjectID = "ENI-bN-wSs"; */
"ENI-bN-wSs.normalTitle" = "登錄或注冊(cè)";
/* Class = "UIButton"; normalTitle = "上一步"; ObjectID = "IGn-o3-iJc"; */
"IGn-o3-iJc.normalTitle" = "上一步";
/* Class = "UILabel"; text = "用戶名"; ObjectID = "YHI-In-kPq"; */
"YHI-In-kPq.text" = "用戶名";
/* Class = "UIButton"; normalTitle = "登錄或注冊(cè)"; ObjectID = "hzS-mR-s9E"; */
"hzS-mR-s9E.normalTitle" = "登錄或注冊(cè)";
/* Class = "UILabel"; text = "標(biāo)題"; ObjectID = "rjb-sh-ADV"; */
"rjb-sh-ADV.text" = "標(biāo)題";
/* Class = "UILabel"; text = "標(biāo)題"; ObjectID = "wxc-43-QK7"; */
"wxc-43-QK7.text" = "標(biāo)題";
/* Class = "UIButton"; normalTitle = "用戶使用協(xié)議"; ObjectID = "xdy-郭佳-fv1"; */
"xdy-郭佳-fv1.normalTitle" = "用戶使用協(xié)議";
英文作為項(xiàng)目設(shè)置的基礎(chǔ)語(yǔ)言,直接使用storyboard內(nèi)容,中文的本地化,則由這個(gè)strings文件控制,是不是很簡(jiǎn)單。
info.plist的本地化
第二種特殊的本地化需求是對(duì)info.plist文件進(jìn)行本地化。具體的最常見(jiàn)的使用場(chǎng)景有:
- 應(yīng)用名稱本地化
- 定位請(qǐng)求提示語(yǔ)本地化
我們知道系統(tǒng)默認(rèn)的本地化文件名,叫做Localizable.strings
,info.plist文件也有自己對(duì)應(yīng)的本地化文件,叫做InfoPlist.strings
這個(gè)文件需要開發(fā)者自己添加,我們添加好以后,在info.plist中加入`CFBundleDisplayName`鍵值,這個(gè)鍵值決定應(yīng)用顯示的名字。
接下來(lái)在InfoPlist.strings文件中寫入本地化索引,注意CFBundleDisplayName
前后沒(méi)有引號(hào),這個(gè)文件是專門用來(lái)本地化info.plist文件的。
CFBundleDisplayName = "你的軟件名稱";
NSLocationAlwaysUsageDescription = "我需要使用手機(jī)的定位服務(wù),請(qǐng)授權(quán)";
NSLocationAlwaysUsageDescription
鍵值則是位置服務(wù)授權(quán)時(shí)候的提示語(yǔ)。如此一來(lái)就實(shí)現(xiàn)了info.plist文件本地化,是不是很簡(jiǎn)單?