1、App 的语言配置列表可从如下方式读取:
let languageArray = UserDefaults.standard.object(forKey: "AppleLanguages") as! [String]
默认语言为数组的第一个值所存储的语言,可以通过更改该数组值得存储顺序来实现app内如的语言切换。
UserDefaults.standard.set(["zh-Hans-CN", "en-CN"], forKey: "AppleLanguages")
2、更改完语言数组以后需要重新设置app的rootViewController
//Bundle.main.onLanguage()
let storyboard = UIStoryboard.init(name: "Main", bundle: nil)
let tabBarController = storyboard.instantiateViewController(withIdentifier: "tabBarController") as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = tabBarController
UIApplication.shared.keyWindow?.backgroundColor = UIColor.white
UIApplication.shared.keyWindow?.makeKeyAndVisible()
3、此时发现并能实时的切换语言,因为在app启动时资源文件已经读取,此时并未更改读取的资源文件。因此需要在切换语言是更换资源路径。继承Bundle,重写localizedString本地化函数,写一个扩展将Bundle类型替换为自定义的BundleEx类型,在语言切换时调用Bundle.main.onLanguage()然后再更换为rootViewController。
class BundleEx: Bundle {
override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
if let bundle = Bundle.getLanguageBundel() {
return bundle.localizedString(forKey: key, value: value, table: tableName)
}else {
return super.localizedString(forKey: key, value: value, table: tableName)
}
}
}
extension Bundle {
private static var onLanguageDispatchOnce: ()->Void = {
//替换Bundle.main为自定义的BundleEx
object_setClass(Bundle.main, BundleEx.self)
}
func onLanguage(){
Bundle.onLanguageDispatchOnce()
}
class func getLanguageBundel() -> Bundle? {
var languageString = "Base"
let languageArray = UserDefaults.standard.object(forKey: "AppleLanguages") as! [String]
if languageArray.first == "zh-Hans-CN"{
languageString = "zh-Hans"
}
let languageBundlePath = Bundle.main.path(forResource: languageString, ofType: "lproj")
guard languageBundlePath != nil else {
return nil
}
let languageBundle = Bundle.init(path: languageBundlePath!)
guard languageBundle != nil else {
return nil
}
return languageBundle!
}
}
注意事项:storyboard类型和xib类型的本地化文件需要是.strings类型,如果是storyboard类型和xib类型在切换语言时不能实时更新。