【问题标题】:Setting "AppleLanguages" doesn't change app language设置“AppleLanguages”不会更改应用程序语言
【发布时间】:2015-06-10 07:10:18
【问题描述】:

我正在尝试实现一个可以更改应用语言的功能。
我试着这样设置:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("de", forKey: "AppleLanguages")

应用重启后语言仍然是“系统默认”。
现在我通过设置Scheme > Application Language > language来测试不同的语言。
但是用户是否可以单击按钮并在重新启动后查看选择的语言?

还有什么正确的方法可以避免在重启时更改语言?

【问题讨论】:

    标签: ios swift ios8


    【解决方案1】:

    您必须使用数组而不是字符串来设置 AppleLanguages 键:

    UserDefaults.standard.set(["de"], forKey: "AppleLanguages")
    

    【讨论】:

    【解决方案2】:

    是的,您可以立即更改应用语言,例如,

    var language = "de"
    let path = NSBundle.mainBundle().pathForResource(language, ofType: "lproj")
    let bundle = NSBundle(path: path!)
    let string = bundle?.localizedStringForKey("key", value: nil, table: nil)
    

    将您的 NSUserDefaults 值用于语言。

    【讨论】:

    • 我在应用程序委托中尝试了这个,它没有改变任何东西
    • 您是否检查过您的 NSUserDefaults 是否保留了您保存的值?
    • 对不起你的代码工作我不明白这一点。这意味着当用户更改语言时,我必须以某种方式将其(语言代码)保存在 userdefaults 中,并在每次翻译时获取它,对吗?
    • @Paddy。自 1 周以来,我对更改语言感到震惊,当我添加此代码时,如何以编程方式更改我的语言,我遇到了崩溃
    • 这在发送本地化推送通知时是否有效?
    【解决方案3】:

    这是在swift 发布之前更改语言的方法 -

    假设我想强制Hebrew 本地化:

    1。创建你自己的 Main.swift 类

    import Foundation
    import UIKit
    
    // Your initialization code here
    let langCultureCode: String = "he_IL"
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject([langCultureCode], forKey: "AppleLanguages")
    defaults.synchronize()
    
    UIApplicationMain(Process.argc, Process.unsafeArgv, nil, NSStringFromClass(AppDelegate))
    

    2。删除您的 AppDelegate.swift “主要”责任

    //@UIApplicationMain <-- COMMENT THIS OUT
    class AppDelegate: UIResponder, UIApplicationDelegate 
    

    这将使您的应用程序在不需要任何启动的情况下强制使用区域设置

    【讨论】:

    • 我已经创建了 Main.swift 文件,然后我需要在哪个函数或函数名称下编写你在答案的第一点提供的代码??
    • @iDeveloper 没有功能,这就是Main.swift 文件的样子。
    • 遗憾的是,这对我来说不再适用了……还有人在 swift 3 xcode 7+ 中遇到问题吗?
    • 首先是 main.swift 而不是 Main.swift,其次,这不适用于 XCode 8。
    • @DeyaEldeen 您是否找到了这种方法的替代方法?我目前只在我的应用程序中需要希伯来语本地化,甚至不需要英语,但我无法从一开始就强制执行它。如果我在 App Delegate 中使用“AppLanguages”键,我必须先终止该应用程序,然后执行本地化。
    【解决方案4】:

    这个解决方案对我有用:
    1.创建Bundle的扩展

    
    
        import Foundation
    
        class L012Localizer: NSObject {
            class func DoTheSwizzling() {
                MethodSwizzleGivenClassName(cls: Bundle.self, originalSelector: #selector(Bundle.localizedString(forKey:value:table:)), overrideSelector:
                    #selector(Bundle.specialLocalizedString(key:value:table:)))
            }
        }
    
        extension Bundle {
            @objc func specialLocalizedString(key: String, value: String?, table tableName: String?) -> String {
                let currentLanguage = Utils.currentLanguage().rawValue
                var bundle = Bundle();
                if currentLanguage != "" , let _path = Bundle.main.path(forResource: currentLanguage, ofType: "lproj") {
                    bundle = Bundle(path: _path)!
                } else {
                    let _path = Bundle.main.path(forResource: "Base", ofType: "lproj")!
                    bundle = Bundle(path: _path)!
                }
                return (bundle.specialLocalizedString(key: key, value: value, table: tableName))
            }
        }
    
        func MethodSwizzleGivenClassName(cls: AnyClass, originalSelector: Selector, overrideSelector: Selector){
    
            let origMethod: Method = class_getInstanceMethod(cls, originalSelector)!;
            let overrideMethod: Method = class_getInstanceMethod(cls, overrideSelector)!;
            if (class_addMethod(cls, originalSelector, method_getImplementation(overrideMethod), method_getTypeEncoding(overrideMethod))) {
                class_replaceMethod(cls, overrideSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
            } else {
                method_exchangeImplementations(origMethod, overrideMethod);
            }
        }
    
    


    2.在AppDelegate中调用DoTheSwizzling

    
    
    
         func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
                L012Localizer.DoTheSwizzling()
                return true
            }
    
    


    3. 创建语言工具

    
    
        class Utils: NSObject {
            class func setLanguage(_ lang: LanguageType) {
                UserDefaults.standard.set([lang.rawValue], forKey: "AppleLanguages")
            }
    
            class func currentLanguage() -> LanguageType {
                if let langs = UserDefaults.standard.object(forKey: "AppleLanguages") as? [String], let currentLang = langs.first {
                    return LanguageType(rawValue: currentLang) ?? .english
                }
    
                return .english
            }
        }
    
    


    4. 创建语言类型

    
    
        enum LanguageType: String {
            case english = "en"
            case korea = "ko"
            case vietnamese = "vi-VN"
    
            func toString() -> String {
                switch self {
                case .korea:
                    return "Korea".localized
                case .vietnamese:
                    return "Vietnamese".localized
                default:
                    return "English".localized
                }
            }
        }
    
    


    5. 请记住,您必须将 Scheme 中的 Application Language 配置为 SystemLanguage

    6.然后每次你需要本地化你的应用程序,你只需要调用。 Utils.setLanguage({LanguageType})

    【讨论】:

      【解决方案5】:

      如果是出于测试目的,只需在模拟器设置应用中更改语言即可。
      如果您想在您的应用程序中制作某种语言选择器,那很漂亮painful,我认为您不应该这样做。
      您的应用从设备读取语言和区域设置并相应地更改 UI。
      覆盖此行为很困难,并且您永远无法完成语言的完全更改,例如,如果您尝试在您的应用和设备中显示地图语言是西班牙语,但应用程序语言是英语,您会看到用西班牙语写的地图指示。
      Here 一个可以提供帮助的项目。

      【讨论】:

      • 但是,如果我决定采取艰难的方式,那么这意味着我需要按照@Paddy 在他的回答中所写的方式在每个视图中获取本地化值。我说的对吗?
      • Paddy 解释的方式强制系统在指定的项目语言目录中查找本地化字符串。方式不是唯一的。如果你在google上搜索你会发现很多实验,即使它们在obj-c后面的概念仍然有效。
      【解决方案6】:

      您可以在 AppDelegate.swift 中尝试以下操作,但更改不会立即出现,而是在您杀死并重新启动您的应用程序之后。 -

      NSUserDefaults.standardUserDefaults().removeObjectForKey("AppleLanguages")
      NSUserDefaults.standardUserDefaults().setObject(["de"], forKey: "AppleLanguages"   
      NSUserDefaults.standardUserDefaults().synchronize()
      

      【讨论】:

        【解决方案7】:

        更新了@royherma 的回答中提到的main.swift 文件的Swift 语法。这将避免在覆盖 UserDefaults 设置后必须重新启动应用程序:

        import Foundation
        import UIKit
        
        // Your initialization code here
        let langCultureCode: String = "LANGUAGE_CODE"
        
        UserDefaults.standard.set([langCultureCode], forKey: "AppleLanguages")
        UserDefaults.standard.synchronize()
        
        UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self))
        

        在您的AppDelegate.swift 文件中删除@UIApplicationMain

        【讨论】:

        • 我怎样才能改变这种语言,更多的时间?没有任何功能,下次怎么执行“main.swift”文件代码?
        猜你喜欢
        • 1970-01-01
        • 2015-06-19
        • 2015-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多