Cornwell
Cornwell

Reputation: 3410

Getting "real" locale used by MacOS

I've made a MacOS app where the user can select the language he wants inside the app.

To set a localized title in a button I do this:

NSLocalizedString("CONTEXT_MENU_OPT_QUIT", bundle: myClass.localeBundle, comment: "Context menu option");

And I run this code at start-up to set localeBundle:

    func getLocale() -> String {
        let availableLanguages: [String] = Bundle.main.localizations;
        var locale: String = userDefaults!.string(forKey: "locale") ?? "";

        if (locale.isEmpty) {
            let preferredLocale: String = Locale.preferredLanguages.first!;

            if (availableLanguages.contains(preferredLocale) == false) {
                locale = "en";
            }
        }
        return locale;
    }

    func loadLocale() {
        let currentLocale: String = self.getLocale();
        var bundlePath: String;

        bundlePath = Bundle.main.path(forResource: currentLocale, ofType: "lproj")!;
        myClass.localeBundle = Bundle.init(path: bundlePath)!;
    }

This works for most people, but if you have the system language set differently than the expected region, this will fail. Eg.:

Language is Portuguese, region is set to Russia: Locale.preferredLanguages.first! will return pt-RU

Considering I only have translations for pt-PT and pt-BR the code I have will default to "en", because "pt-RU" doesn't exist.

How do I get pt-PT and pt-BR independently of the user's region?

Thank you

Upvotes: 1

Views: 379

Answers (1)

Ken Thomases
Ken Thomases

Reputation: 90571

The user's setting for preferred language (as set in System Preferences) is stored in user defaults under the key "AppleLanguages". It's an array of language identifier strings (like "pt-BR").

The user's setting is in the global domain but, as with all user defaults, you can override that in more local domains. In particular, you can set it in the application domain to affect just your app.

So, I think you should just store an array with the identifier for the language chosen by the user for your app under the "AppleLanguages" key and then let the system do its thing. You should not try to reproduce the resource search algorithm yourself.

If you want to keep using your technique, you can use the localization properties and methods of Bundle to pick one of the actual localizations available in a bundle according to a list of preferred ones. That is, don't query the localizations and then check if it contains your locale identifier; use preferredLocalizations(from:forPreferences:) to do the search for you. It likely uses a more sophisticated algorithm. Also, keep in mind the distinction between locale and language and, especially, locale IDs vs language IDs. The represent different things and have different forms, but you seem to be using them interchangeably.

Upvotes: 2

Related Questions