多語(yǔ)言適配 -- 根據(jù)當(dāng)前設(shè)備語(yǔ)言自動(dòng)切換顯示

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文件。

Snip20170102_10.png

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ì)。如下

"你好" = "你好";
  1. 每一行一句,等號(hào)前面是key,等號(hào)后面是value,引號(hào)前不加@,分號(hào)結(jié)尾。
  2. 當(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è)副本。

Snip20170102_11.png

各個(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本地化

xibstoryboard作為兩種不同類型的UI工具,他們的本地化,既可以通過(guò)代碼修改,也可以直接對(duì)xib和storyboard文件進(jìn)行本地化操作,操作類似strings文件的Localize操作,見(jiàn)下圖

Paste_Image.png

選中文件后,點(diǎn)擊右邊欄Localize按鈕,勾選對(duì)應(yīng)語(yǔ)言。

Paste_Image.png

這樣我們發(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)景有:

  1. 應(yīng)用名稱本地化
  2. 定位請(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)單?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容