12pm
12pm

Reputation: 518

How to set default localization for iOS app

I'm developing app for Russian-speaking people. A lot of countries near Russia have the second language - Russian. My app has two localizations: Russian and English. And I need to set Russian localization like default. English should be only for people who use English like device's language.

I know that Apple recommends to use localization in priority of preferred languages in settings but I have an important reason to don't follow this recommendation.

How can I set Russian localization like default?

Upvotes: 22

Views: 32752

Answers (6)

Voloda2
Voloda2

Reputation: 12617

preferredLanguages sometimes return "ru_RU" but my lproj is ru.lproj. So I decided to another solutions. I added "test.lang.phrase = "YES"; to all my localizable strings files. I load a default localization if localization isn't found.

NSString *result = nil;
NSString *testLang = NSLocalizedString(@"test.lang.phrase", nil);
if ([testLang isEqualToString:@"YES"]) {
    result = NSLocalizedString(str, nil);
}
if (!result) {
    NSBundle *myLangBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"]];
    result = NSLocalizedStringFromTableInBundle(str, nil, myLangBundle,nil);
}

Upvotes: 0

Huralnyk
Huralnyk

Reputation: 747

As eofster said you should set AppleLanguages key in NSUserDefaults to array of languages with desired order, but in order to work at first lunch you should do it very early, even earlier than applicationWillLunchWithOptions:

As for me this solution works great and has advantage on using NSLocalizedStringFromTableInBundle because it works with storyboards and nibs as well.

Here is step by step solution on Swift language.

  1. Make subclass of UIApplication as described here: Subclass UIApplication with Swift

  2. Second override init method of you UIApplication subclass to substitute list of preferred languages on your own.

    override init() {
        if let languages = NSUserDefaults.standardUserDefaults().objectForKey("AppleLanguages") as? [String],
            let language = languages.first where !language.hasPrefix("en")
        {
            NSUserDefaults.standardUserDefaults().setObject(["ru", "en"], forKey: "AppleLanguages")
        }
    
        super.init()
    }
    

    Swift 4:

    override init() {
    if let languages = UserDefaults.standard.object(forKey: "AppleLanguages") as? [String],
        let language = languages.first(where:{!$0.hasPrefix("en")})
    {
        UserDefaults.standard.set(["ru", "en"], forKey: "AppleLanguages")
    }
    
    super.init()
    

    }

  3. That's all. If first preferred language is not English you'll substitute list with Russian as first language.

P.S. If you're doing not only localization, but internationalization don't forget to check locale which is used by date pickers, date formatters, number formatters, etc.

Upvotes: 4

Gleb Tarasov
Gleb Tarasov

Reputation: 885

In my case I have only Russian localization with hard-coded strings in my app, but I use libraries with localization bundles. Strings from libraries were in English by default. Because NSBundle.mainBundle.preferredLanguages were [ "en" ].

They became Russian after I specified app localization language in Info.plist with CFBundleLocalizations key:

screenshot

CFBundleLocalizations (Array - iOS, OS X) identifies the localizations handled manually by your app. If your executable is unbundled or does not use the existing bundle localization mechanism, you can include this key to specify the localizations your app does handle.

Each entry in this property’s array is a string identifying the language name or ISO language designator of the supported localization. See “Language and Locale Designations” in Internationalization and Localization Guide in Internationalization Documentation for information on how to specify language designators.

Upvotes: 5

12pm
12pm

Reputation: 518

I have not found the right solution. Only one way that is suitable for my issue is to use NSLocalizedStringFromTableInBundle instead NSLocalizedString. This way doesn't allow to localize images or nibs but with strings it works great.

Firstly you need to define the current device language:

NSString *lang = (NSString *)[[NSLocale preferredLanguages] objectAtIndex:0];

Next find the bundle for this language:

NSBundle *myLangBundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:lang ofType:@"lproj"]];

If bundle is found then use it in NSLocalizedStringFromTableInBundle:

_label.text = NSLocalizedStringFromTableInBundle(@"LabelText",nil,myLangBundle,nil);

Otherwise find and use default bundle.

Upvotes: 4

Laszlo
Laszlo

Reputation: 2778

I think you need to use the Localization native development region key in your info.plist file.

enter image description here

Upvotes: 33

eofster
eofster

Reputation: 2047

You probably need to set Russian as a value of CFBundleDevelopmentRegion in the Info.plist.

CFBundleDevelopmentRegion (String - iOS, OS X) specifies the native region for the bundle. This key contains a string value that usually corresponds to the native language of the person who wrote the bundle. The language specified by this value is used as the default language if a resource cannot be located for the user’s preferred region or language.

Update

If you really want and need to override the language priority of the OS, you could use AppleLanguages user defaults key (although, as you know, it is not recommended):

[[NSUserDefaults standardUserDefaults] setObject:@[@“ru”, @“en”] forKey:@“AppleLanguages”];

Upvotes: 12

Related Questions