一、 前言
在產(chǎn)品進(jìn)行國(guó)際化的過(guò)程中,多語(yǔ)言適配是必不可少的環(huán)節(jié),前期我們把項(xiàng)目中所有的多語(yǔ)言翻譯放到了項(xiàng)目主工程中,各個(gè)組件直接去使用并沒(méi)有什么問(wèn)題(我們的項(xiàng)目架構(gòu)是:本地組件 + 私有公共組件),但是有一些公共的模塊,要在多個(gè)項(xiàng)目中使用,同時(shí)也要做多語(yǔ)言適配,就需要把適配文件放到每個(gè)子組件中去處理。
二、組件添加多語(yǔ)言適配
在適配多語(yǔ)言的過(guò)程中我們嘗試了兩種解決方案:
方案一:
1、首先用 pod lib create multilingualModule 命令創(chuàng)建一個(gè)組件
2、選中 pods 項(xiàng)目,創(chuàng)建一個(gè) Localizable.strings 文件
3、根據(jù)以下步驟添加需要適配的多語(yǔ)言

4、把創(chuàng)建的多語(yǔ)言文件放到組件的 Assets 文件中,如圖:

至此,適配多語(yǔ)言的流程都已經(jīng)完成,經(jīng)過(guò)測(cè)試,可以順利的加載到需要適配的語(yǔ)言
按照 cocoapods 官方提倡的方式加載資源文件,在podspec文件中添加下面的代碼
s.resource_bundles = {
'multilingualModule' => ['multilingualModule/Assets/*']
}
方案二:
1、首先創(chuàng)建一個(gè)與組件同名的 bundle ,并把組件放到組件的 Assets 文件中

2、把按照方案一創(chuàng)建好的多語(yǔ)言文件放到創(chuàng)建好的bundle中 ,如圖:

3、在 podspec 文件中,把之前加載資源的方式改成下面這句代碼:
s.resource = 'multilingualModule/multilingualModule.bundle'
有人就會(huì)問(wèn)為什么不用官方推薦的方式加載資源了?
s.resource_bundles = {
'multilingualModule' => ['multilingualModule/Assets/*']
}
如果用這種方式加載資源,組件被編譯后,就會(huì)出現(xiàn)如下的情況,multilingualModule.bundle 中還包含一個(gè) multilingualModule.bundle ,顯然,這不是我們期望的結(jié)果,且通過(guò)以下方式查看:
在項(xiàng)目編譯的產(chǎn)物中找到 multilingualModule_Example.app ,并右鍵顯示包內(nèi)容,如圖:

繼續(xù)右鍵顯示包內(nèi)容,可以看到我們添加的多語(yǔ)言文件被包含在內(nèi)層的bundle中,如圖:

雖然這種方式也可以正常發(fā)布組件,但是我們是希望把所有的資源只包含在一個(gè) bundle中,便于我們管理
三、如何在組件中使用翻譯文件
如果我們把翻譯文件放到主工程中,通過(guò)mainbundle 的方式直接加載即可:
func localValue(str:String) -> String{
let bundle:Bundle = Bundle.main
return bundle.localizedString(forKey: str, value: nil, table: "Localizable")
}
但是組件中的資源文件,在編譯的之后,并沒(méi)有被放到 mainbundle 路徑,需要先找到 multilingualModule.bundle 然后再獲取資源文件,通過(guò)以下方式獲取
/// 加載組件內(nèi)部的多語(yǔ)言(默認(rèn)必須添加一個(gè)英文的多語(yǔ)言)
/// - Parameters:
/// - sourceCls: 當(dāng)前組件內(nèi)部的任意類文件
/// - txtStr: 需要翻譯的文本的 key
/// - Returns: 翻譯后的文本
func localValueWithModule(_ sourceCls: AnyClass,_ txtStr:String)->String{
var crBundle:Bundle? = nil
let sourceClsString = NSStringFromClass(sourceCls)
let list = sourceClsString.components(separatedBy: ".")
let frameWorkBundle = Bundle(for: sourceCls)
let resource = list[0]
if let url = frameWorkBundle.url(forResource: resource, withExtension: "bundle"){
crBundle = Bundle.init(url: url)
}
if crBundle != nil {
let path = crBundle?.path(forResource: getCurrLanString(), ofType: "lproj")
if path?.count ?? 0 > 0 {
//用這個(gè)路徑生成新的bundle
let bundle = Bundle(path: path!)!
let mes = bundle.localizedString(forKey: txtStr, value: nil, table: "Localizable")
return mes
}
}
return txtStr
}
注意:getCurrLanString() 獲取當(dāng)前需要翻譯的多語(yǔ)言
四、總結(jié)
在做子組件多語(yǔ)言適配的過(guò)程中也遇到了一些奇怪的問(wèn)題,這里把正確的流程思路記錄下,供有需求的同學(xué)參考~