swift - app国际化, 优雅切换


https://www.jianshu.com/p/e5d5fac05b8c

在开发的过程中, 可能你们的app 会有这样的需求, 需要坚持多种语言. 怎么做到不重启app 就更换了语言, 下面我们来讨论下.
首先我们知道, 如果你的app 中需要支持多种语言, 往往我们会选择一个Localizable.strings, 它会一种语言生成一个文件夹, 相当于一个包吧. 所以我们只要做到切换时, 选择对应的语言包就可以了.废话不多说, 我们开始吧.

  • 开始国际化
    点击项目->PROJECT->Info->Localizations -> + , 添加你想要的语言, 这个谈论中/英

    • 选择想用本地化的storyboard/xib...



创建Localizable.strings

 


 

 

 

建议命名为: Localizable
  • 选择你新创建的 Localizable.strings , Localize... 
    xx.png

    添加你语言, 最后效果



  • Localizable.strings 文件中写入
    "key" = "value"; 这样的格式.

  • storyboard 中生成的



  • 要想生成这种形式, 可以先切换成 , 再切换回来



  • 我们这里主要讨论下怎么切换, 这些简单配置, 就不详细了, 请看最后的Demo.

  • 用自己创建的Bundle,想xcode 用自己指定的bundle , 达到切换语言的目的.

import Foundation class AppSettings: NSObject { fileprivate static let kSharedSettingsKey = "DefaultUserSettings" static let shared: AppSettings = { let appSettings: AppSettings if let savedData = UserDefaults.standard.object(forKey: AppSettings.kSharedSettingsKey) as? Data, let defaultSettings = NSKeyedUnarchiver.unarchiveObject(with: savedData) as? AppSettings { appSettings = defaultSettings } else { appSettings = AppSettings() } return appSettings }() static func saveSharedInstance() { let data = NSKeyedArchiver.archivedData(withRootObject: AppSettings.shared) UserDefaults.standard.set(data, forKey: AppSettings.kSharedSettingsKey) } enum Language: String { /// 请注意, 这个命名不是随意的, 是根据你本地的语言包,可以show in finder 看到. en.lproj / zh-Hans.lproj case Chinese = "zh-Hans" case English = "en" var code: String { return rawValue } } /// 判断手机语言是不是中文 static func localeIsChinese() -> Bool { if let lang = Locale.preferredLanguages.first { return lang.hasPrefix("zh") ? true : false ; } else { return false } } var language: Language override init() { // 第一次初始语言, 看手机是什么语言 language = AppSettings.localeIsChinese() ? .Chinese : .English super.init() } } private var bundleByLanguageCode: [String: Foundation.Bundle] = [:] extension AppSettings.Language { var bundle: Foundation.Bundle? { /// 存起来, 避免一直创建 if let bundle = bundleByLanguageCode[code] { return bundle } else { let mainBundle = Foundation.Bundle.main if let path = mainBundle.path(forResource: code, ofType: "lproj"), let bundle = Foundation.Bundle(path: path) { bundleByLanguageCode[code] = bundle return bundle } else { return nil } } } } /// 首先, 我们会在启动时设置成我们自己的Bundle,这样就可以做到,当使用时会调用这个方法. class Bundle: Foundation.Bundle { override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String { if let bundle = AppSettings.shared.language.bundle { return bundle.localizedString(forKey: key, value: value, table: tableName) } else { return super.localizedString(forKey: key, value: value, table: tableName) } } } 

AppDelegate中


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { object_setClass(Foundation.Bundle.main, Bundle.self) return true } 

使用

/// comment 是传参, 假如你的value 中需要外界来决定内容,可以用%@,然后comment传参. NSLocalizedString("key", comment: "") //切换语言时,只要设置就可以: AppSettings.shared.language = .English // .Chinese 

重置story

  • 对于story 中的国际化, 我们需要重设一下RootViewController
    func resetRootViewController() { if let appdelegate = UIApplication.shared.delegate { let storyBoard = UIStoryboard.init(name: "Main", bundle: nil) if let mainController = storyBoard.instantiateViewController(withIdentifier: "rootViewController") as? UINavigationController { appdelegate.window??.rootViewController = mainController } } } 


作者:Jason_风筝
链接:https://www.jianshu.com/p/e5d5fac05b8c
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

 

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM