3

I want my app language to change on button click..

My code is:

@IBAction func convertlang(_ sender: Any) {
   if L102Language.currentAppleLanguage() == "en" {
        L102Language.setAppleLAnguageTo(lang: "ar")
        UIView.appearance().semanticContentAttribute = .forceRightToLeft
    } else {
        L102Language.setAppleLAnguageTo(lang: "en")
        UIView.appearance().semanticContentAttribute = .forceLeftToRight
    }
}

let APPLE_LANGUAGE_KEY = "AppleLanguages"
class L102Language {
    class func currentAppleLanguage() -> String{
         let userdef = UserDefaults.standard
         let langArray = userdef.object(forKey: APPLE_LANGUAGE_KEY) as! NSArray
         let current = langArray.firstObject as! String
    return current
}

class func setAppleLAnguageTo(lang: String) {
    let userdef = UserDefaults.standard
    userdef.set([lang,currentAppleLanguage()], forKey: APPLE_LANGUAGE_KEY)
    userdef.synchronize()
}}

and this works fine and convert the language when i click on the button..

the problem is i need to restart the app to see the language change..

i searched for this but most of them were for objective-c and tried some for swift but didn't work..

how to do this?

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Lama
  • 255
  • 3
  • 17
  • So you have a class that sets UserDefaults values regarding current language settings. Where/how/when are they read? what actually tells the system or your application that the language has changed it and should update? – Scriptable Apr 11 '18 at 11:43
  • @Scriptable on button click it will that the language has changed – Lama Apr 11 '18 at 12:31
  • how does it do that on button click? you have a complicated issue and only shown part of the code, so you cannot expect a good answer – Scriptable Apr 11 '18 at 12:35
  • @Scriptable this is all the code i have which convert the language for me.. and its working just fine.. the only issue is that i have to restart the application to see the other language... – Lama Apr 11 '18 at 12:51

3 Answers3

6

You can't change the language at runtime with normal button click. If you really need that, you need to use a custom localization system instead.

To change the app language during runtime, I have done this manually by creating two different storyboards. I saved the language preference in NSUserDefaults but NOT with the key AppleLanguages and then called AppDelegate's didFinishLaunchingWithOptions method to select storyboard.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainEnglish" bundle:nil];
UINavigationController *navigationcontroller=[[UINavigationController alloc]init];
RegistorViewController *registor=[storyboard instantiateViewControllerWithIdentifier:@"Registor"];
[self.window setRootViewController:navigationcontroller];
[self.window makeKeyAndVisible];
[navigationvontroller pushViewController:registor animated:NO];

Though this is not what apple wants a developer to do in runtime.

Someone even asked an Apple engineer and this is the response:

In general, you should not change the iOS system language (via use of the AppleLanguages pref key) from within your application. This goes against the basic iOS user model for switching languages in the Settings app, and also uses a preference key that is not documented, meaning that at some point in the future, the key name could change, which would break your application.

If you want to switch languages in your application, you can do so via manually loading resource files in your bundle. You can use NSBundle:pathForResource:ofType:inDirectory:forLocalization: for this purpose, but keep in mind that your application would be responsible for all loading of localized data.

Community
  • 1
  • 1
Arnab
  • 4,216
  • 2
  • 28
  • 50
4

I had faced the same problem in my project recently. You are using the correct code to change app language but it change only string file data not the storyboard. For complete localisation you have to restart the app again, because there is no any another way to do this. You can show a popup to user "Please restart your app to change language completely". Because we can kill the app programatically, but after doing this there is no way to restart the app again.

Vitaly Potlov
  • 365
  • 1
  • 7
  • 14
0

This might not be the most iOS-typical way of doing things, but I tend to treat static content like any other data in the app, especially when I'm using VIPER (although other patterns would work) and a unidirectional data flow.

With that in mind, for this I would have a service accessing a store of static content keyed of the user's language preference. When that changes I would trigger a refresh of the content.

This has worked well for projects when I also have server data as well as local data that needs to be localised.

To be fair, I've never used the standard tools much. And I suspect this may not be ideal for right-to-left language types.

Scott McKenzie
  • 16,052
  • 8
  • 45
  • 70