Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift : How to change language inside app?

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

like image 467
Ali Hanifi Avatar asked May 09 '16 08:05

Ali Hanifi


People also ask

How do I change localization language in Swift?

Click on iOS->App/Single View App->Next. Name your project and select the language as Swift. Select a desired location and click on Create. To start with Localization, click on your Project Name -> go to Info Tab -> Under Localizations, click on the '+' button.


4 Answers

You can use NSBundle+Language third party class.

like image 138
Keyur Hirani Avatar answered Oct 05 '22 06:10

Keyur Hirani


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.

like image 24
jordivilagut Avatar answered Oct 05 '22 06:10

jordivilagut


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.

like image 23
Ali Hanifi Avatar answered Oct 05 '22 06:10

Ali Hanifi


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
}
like image 34
Azamat Bekkhozha Avatar answered Oct 05 '22 07:10

Azamat Bekkhozha