Ali Almohsen
Ali Almohsen

Reputation: 1321

Change App Localization Based on User Selection

I've read lots of answers about this, but most are many years old and I don't know what's the latest info.

On first launch, my app will ask the user which language (s)he prefers, rather than just using the OS default language.

  1. How can I set the localization rest of the app to the selected language?
  2. How can I get which language the user has selected in other views?

I thought the following code would set the language, but it didn't do the job:

UserDefaults.standard.set("AR", forKey: "AppleLanguages")
UserDefaults.standard.synchronize()

Upvotes: 1

Views: 1479

Answers (2)

dmorrow
dmorrow

Reputation: 5674

I have handled this with a LanguageManager singleton class, which handles all the localization. Here is some psuedo code, as its typically a fairly large class.

It has a list of all locales that are supported, for example:

let supportedLocales = ['en-US', 'en-CA', 'fr', 'es-ES', 'es-MX'] 

It also stores the selected language in UserDefaults. When the selectedLocale changes, it sends a Notification, in case you want to notify your views or anything else:

var selectedLocale: String? {
    get {
        return UserDefaults.standard.object(forKey: UserDefaultsKeys.selectedLocale) as? String
    }
    set (newLocale) {
        let didChange = self.selectedLocale != newLocale
        UserDefaults.standard.set(newLocale, forKey: UserDefaultsKeys.selectedLocale)
        UserDefaults.standard.synchronize()
        if didChange {
            NotificationCenter.default.post(name: Notification.Name.localeDidChange, object: nil)
        }
    }
}

Now, in order to pull strings out of your localized.strings files, you can't use the standard Apple methods - you have to provide your own. Use LanguageManager.shared.getString(for key:String, alt:String) to reference keys in your .strings file to pull out localized strings.

var selectedLanguage:String? {
    //returns just the language portion of the locale - eg: 'en' from 'en-US'
    if let selectedLocale = selectedLocale {
        return selectedLocale.components(separatedBy: "-")[0]
    }
    return nil
}

func getString(for key:String, alt:String) -> String
{
    var val:String? = getString(for:key, language: selectedLocale)
    if val == nil {
        val = getString(for:key, language: selectedLanguage)
    }
    if val == nil {
        val = getString(for:key, language: "en") //default to English
    }
    if let val = val {
        return val 
    }

    return  alternate //use fallback
}


func getString(for key:String, language:String) -> String?
{
    let path = Bundle.main.path(forResource:language, ofType:"lproj")
    if let languageBundle = Bundle(path:path) {
        return languageBundle.localizedString(for: key)
    }
    return nil
}

Upvotes: 2

Lalit kumar
Lalit kumar

Reputation: 2207

By default is the English Language // You can set Language according you

  UserDefaults.standard.set("en", forKey: "Apple")
  UserDefaults.standard.synchronize()

If you want to current system language than use code

let langStr = Locale.current.languageCode //and set in UserDeafaults
 UserDefaults.standard.set(langStr, forKey: "Apple")

var currentlanguage: String?
self.currentlanguage = UserDefaults.standard.object(forKey: "Apple") as! String?
print("current language ---%@",self.currentlanguage)

Upvotes: 0

Related Questions