6

My app changes the language at runtime and advises the user to restart the app. I do it like this:

    typealias LanguageLocaleType = (language: String?, locale: String?, title: String)

    let elements: [LanguageLocaleType] = [
        (nil, nil, "System Default"),
        ("en", "en_US", "English"),
        ("ar", "ar_SA", "Arabic"),
    ]

    //...func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)...

    let element = elements[indexPath.row]

    guard let language = element.language else {
        // How to really reset app back to OS language/locale???
        UserDefaults.standard.removeObject(forKey: "AppleLanguages")
        UserDefaults.standard.removeObject(forKey: "AppleLocale")
        return
    }

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

    if let locale = element.locale, !locale.isEmpty,
        Locale.current.identifier != locale,
        !Locale.current.identifier.hasPrefix("\(language)_") {
            UserDefaults.standard.set(locale, forKey: "AppleLocale")
    }

I want to offer to set languages in a list with the right one selected, one of which being offered it to set language back to System Default. However, there's no way to find the OS-level language and locale that I could find. Since after I mess around with setting the UserDefaults, Bundle.main.preferredLocalizations is not reliable and do not match the system default (event when I remove the key from the User Default).

Is there a way to get the OS-level language and locale instead of the app-level?

TruMan1
  • 33,665
  • 59
  • 184
  • 335
  • 1
    https://stackoverflow.com/questions/27053135/how-to-get-a-users-time-zone/27053592#27053592 – Leo Dabus Jun 30 '17 at 21:57
  • @LeoDabus that's a good thought, but I don't want to assume the user's language/locale just by their location since they could've chosen their own lanaguage/locale from the iOS settings. – TruMan1 Jun 30 '17 at 22:19
  • 7
    What are you trying to accomplish with this? Advising a restart is a pretty terrible UX and against Apple's HIG – GetSwifty Jun 30 '17 at 23:28
  • Specifically, what you varying based on locale/language? – GetSwifty Jun 30 '17 at 23:30
  • I am offering to change their language and locale and restart, they can either tap `Later` or `OK` which will `exit(0)`. Not at as good as Android, but better than swizzling. But how do I offer them to change back to `System Default`, where is the system-level chosen value? – TruMan1 Jul 01 '17 at 01:31
  • you want to change language at runtime ? without restarting ? – iOS Geek Jul 01 '17 at 04:55
  • Pretty sure if you call exit(), your App will be rejected, so find another way. Building your own support for this should be trivial. E.g. having a json file for each language, and a method to get a language value for a key. Switching language, just reload the json file for that language. – thomas gotzsche Jul 01 '17 at 09:32
  • It's not that easy. There's right-to-left support plus locale needs to change for numbers and dates. – TruMan1 Jul 01 '17 at 13:52
  • @iOSGeek yes I'd like to change the language and locale at runtime without ugly hacks like swizzling. Killing the app at a dialog isn't that bad, especially if I put a fade out illusion. It sucks but there's no native support for changing language and locale at runtime :( – TruMan1 Jul 01 '17 at 13:55
  • we can do it I had made a project on changing language at runtime I will share link . I did it by making use of some libraries made in a project – iOS Geek Jul 03 '17 at 02:52
  • https://stackoverflow.com/questions/1669645/how-to-force-nslocalizedstring-to-use-a-specific-language?noredirect=1&lq=1 – ramacode Jul 04 '17 at 09:15
  • I've seen this and nothing tells me what the system language is. – TruMan1 Jul 04 '17 at 10:45
  • want to get current system Language or change language at runtime ? – iOS Geek Jul 05 '17 at 04:24
  • Just get the current system language. So I can change back to the system default after messing with UserDefault keys "AppleLanguages" and "AppleLocale". – TruMan1 Jul 05 '17 at 04:28
  • Could you let us know what you're intended use-case for this app? Changing the UI Language sounds like a translation/learning based applicaiton, which might understandable. Not so much in other types of apps since the device language could always be appropriate.. – jlmurph Jul 07 '17 at 20:21
  • 1
    @TruMan1You can get the application language with `Locale.current.languageCode` and user preferred language with `Locale.preferredLanguages` .While reset get the current Language code from `Locale.current.languageCode` – LC 웃 Jul 08 '17 at 04:01
  • As far as I know, there is no way to list all iOS-supported languages/regions, just the identifiers. In my application I am doing the same thing, but I have two `UITextField`s where the user can enter the language and region code and then I change the locale by restarting the app. If this is what you need, I'll post an answer with relevant code. – smeshko Jul 10 '17 at 09:38

4 Answers4

4

You should be able to get currently selected OS language like this.

    let language  = NSLocale.preferredLanguages[0]

if this is not what you are looking for, refer to this answer https://stackoverflow.com/a/30750120/809821

Rukshan
  • 7,902
  • 6
  • 43
  • 61
  • 4
    why sleepwalkerrfx 's answer is not correct , would you plz . . describe ? @TruMan1 – roy Jul 10 '17 at 11:44
1

I will recommend you to use this library from Cocoa pods.

In your Podfile add this line:

pod 'Localize-Swift', '~> 1.7'

An then install your pods using this command:

pod install

Then if you don't have Localizable.strings, for example Localizable.strings (English) file add this lines.

"LD" = "Loading ...";
"CAMP" = "Campus";
"MAP" = "MAP";

The first word is like your TAG and the next word is your value .

Then in your ViewController you can use your string like this.

Example of use:

let progressHUD = ProgressHUD(text: "LD".localized())
let progressHUD = ProgressHUD(text: "CAMP".localized())
let progressHUD = ProgressHUD(text: "MAP".localized())

And that is all.

I hope this help.

Cristian Cardoso
  • 665
  • 6
  • 11
1

I found an answer which seems to do something similar, by playing with the Bundle language files of your app. As in setting the proper one.

While you state that playing with Bundle properties seems to fiddle with your use case, I'd look into saving the setted language with Core Data, inside an app file, or inside and XML (.plist). You could set up a checking method in didFinishWithOptions which checks the presence of this variable then runs the language prompt if absent or leaves as is if present (adding a check to make sure the right language is set would be wise). Since this does not alter the Settings-set language, you'd always have a quick reference point outside of your app through NSLocale to switch back to it with ease if the user so chooses.

Here's the post

Disclaimer 1 : i haven't tested this, but it seems like a plausible, and Apple-Tolerated thing to do. Disclaimer 2 : as the OP in the link states, and as some have mentioned here, changing app language is not recommended by Apple. Notably due to NSLocale keys, and how frequently Swift is updated which could lead to your code being unuseable or requiring massive overhaul.. As i mentioned in a comment above, i'd reconsider this use-case sadly :(

jlmurph
  • 1,050
  • 8
  • 17
1

In reference to your question above you can either as stated above create your own bundle or use a prebuilt class like the following:https://github.com/mumensh/iOS-Localization

Nick B
  • 423
  • 3
  • 6