Setting "AppleLanguages" doesn't change app language

Solution 1:

You have to set the AppleLanguages key with an array, not a string:

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

Solution 2:

Yes you can change the app language immediately like,

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)

use your NSUserDefaults value to language.

Solution 3:

Here is how you change the language prior to launch in swift -

Lets say i want to force Hebrew localization:

1. Create your own Main.swift class

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. Remove your AppDelegate.swift "main" responsibility

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

This will make your app forced to a locale WITHOUT needing any launch

Solution 4:

This solution work for me:
1. Create an extension of 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. Call DoTheSwizzling in AppDelegate




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


3. Create Language Utils



    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. Create Language Type



    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. Remember that you have to config Application Language in Scheme to SystemLanguage
enter image description here
6. Then Every time you need to localize your app, you only need to call. Utils.setLanguage({LanguageType})