Swift : How to change language inside app?

34,165

Solution 1

found my answer :

NSUserDefaults.standardUserDefaults().setObject(["language identifier"], forKey: "AppleLanguages") 
NSUserDefaults.standardUserDefaults().synchronize()

unfortunately user must restart the app! if anyone could find a solution to not restart the application please inform me.

Solution 2

I think KababChi's answer was right. However, in the newer versions of Swift NSUserDefaults has been substituted by UserDefaults. So the code would look like this:

UserDefaults.standard.set(languages[indexPath.row], forKey: "AppleLanguages")
UserDefaults.standard.synchronize()

App still needs to be restarted to apply these changes.

Solution 3

You can use NSBundle+Language third party class.

Solution 4

In order to change the language without restarting your device you need to switch ‘lproj’ bundle.

You can make it using this code:

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 = Localization.currentAppleLanguage()
        var bundle = Bundle();
        if 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);
    }
}

Here we are exchanging the implementation of Bundle's localizedString method. Note: we exchanging the Implementation not the reference on the function.

Now add this line in the Appdelegate in the didFinishLaunchingWithOptions delegate method.

L102Localizer.DoTheSwizzling()

After that you need to reload your ViewControllers. In your Main.storyboard set Root View Controller's StoryboardId to "rootnav" and paste this code to your method that switches language:

let rootviewcontroller: UIWindow = ((UIApplication.shared.delegate?.window)!)!
rootviewcontroller.rootViewController = self.storyboard?.instantiateViewController(withIdentifier: "rootNav")
let mainwindow = (UIApplication.shared.delegate?.window!)!
mainwindow.backgroundColor = UIColor(hue: 0.6477, saturation: 0.6314, brightness: 0.6077, alpha: 0.8)
UIView.transition(with: mainwindow, duration: 0.55001, options: .transitionFlipFromLeft, animations: { () -> Void in
}) { (finished) -> Void in
}
Share:
34,165
Ali Hanifi
Author by

Ali Hanifi

Updated on July 20, 2022

Comments

  • Ali Hanifi
    Ali Hanifi almost 2 years

    i am using Localize-Swift library (Link) to localize my application and it works fine with .strings files. the problem is that i have to localize to a language which is right to left and i have to localize via Interface Builder Storyboard so i can make view controllers look right in RTL format. the question is how do i set the storyboard to user selected language in real time ?

    for example i have 2 storyboard files :

    1- ... /ProjectName/Base.lproj/Main.storyboard

    2- ... /ProjectName/fa-IR.lproj/Main.storyboard

    how do i switch between them in real time ?

    i already know i can change it in Schemes and device language but i want to do it real time and i dont want the users to restart their device.

    thanks

  • Hossam Ghareeb
    Hossam Ghareeb almost 8 years
    check my comment in your questions. I'm localizing the app without restarting
  • Yitzchak
    Yitzchak over 7 years
    your solution is so short, I found it early but didn't try. now after days I tried and I happy.. I used this: github.com/maximbilan/ios_language_manager It's exactly the same code (copy paste?!?!) but with additions, no bugs, with examples of usage and a running app. 10 minutes it was implemented in my project =]
  • Uma Madhavi
    Uma Madhavi over 6 years
    @HossamGhareeb . How can we achieve without restarting the app. please can u tell me
  • Eric Aya
    Eric Aya almost 6 years
    .synchronize() is obsolete and should not be used anymore, at all.
  • NiravS
    NiravS over 5 years
    How to set our string Key into this function?
  • Mrugesh Tank
    Mrugesh Tank about 5 years
    After using this how to get real phone language? I mean we've set French via app like mentioned way. but user's phone is in Spanish, then how can we get Spanish?
  • Sajid Zeb
    Sajid Zeb over 4 years
    This should be the accepted answer. It changed App language without restarting app. Thanks a bundle (y)
  • Angel F Syrus
    Angel F Syrus over 4 years
    In the extension of bundle it showing error as Use of unresolved identifier 'Localization'; did you mean 'localizations'? what have to do?