Localizing strings in iOS: default (fallback) language?

30,178

Solution 1

Perhaps this should help? -- iPhone: localization / internationalization default strings file

It should fallback to English by default. I've just switched my phone to a language into which my app is not localized, and the text was all in English, as expected.

Important: as @hyperspasm commented : To expand on/rephrase this, the fallback language is the language which was most recently chosen by the user in the device Settings, that is also represented in the app's bundle.

Solution 2

To avoid all those lengthy syntax and more having more descriptive var name for translators, I derived my own helper method L() for translation and falling back to English

NSString * L(NSString * translation_key) {
    NSString * s = NSLocalizedString(translation_key, nil);
    if (![[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:@"en"] && [s isEqualToString:translation_key]) {
    NSString * path = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
    NSBundle * languageBundle = [NSBundle bundleWithPath:path];
    s = [languageBundle localizedStringForKey:translation_key value:@"" table:nil];
    }
    return s;
}

My Localizable.strings would look like this

"SOME_ACTION_BUTTON" = "Do action";

So in my code, i would use L(@"SOME_ACTION_BUTTON") to get the correct string

Though sometime the key is longer than the translation itself HELP_BUTTON_IN_NAV_BAR = 'Help' but it saves me a lot of time explaining what it is to whoever is helping me doing the translation

Solution 3

You need to make sure that the value of CFBundleDevelopmentRegion in your Info.plist is the language region that you would like to fallback to. (e.g. "en")

Solution 4

@Bogus answer in Swift 4, works like a charm on iOS 11.1:

public func NSLocalizedString(_ key: String, tableName: String? = nil, bundle: Bundle = Bundle.main, value: String = "", comment: String) -> String {
    let fallbackLanguage = "en"
    guard let fallbackBundlePath = Bundle.main.path(forResource: fallbackLanguage, ofType: "lproj") else { return key }
    guard let fallbackBundle = Bundle(path: fallbackBundlePath) else { return key }
    let fallbackString = fallbackBundle.localizedString(forKey: key, value: comment, table: nil)
    return Bundle.main.localizedString(forKey: key, value: fallbackString, table: nil)
}

Solution 5

A fast way to do this without replacing any methods is "overriding" the NSLocalizedString define and using the methods that Apple uses for this define to replace it and add the additional fallback logic in the "overridden" method.

#undef NSLocalizedString
#define NSLocalizedString(key, comment) [self localizedStringForKey:(key) replaceValue:(comment)]

+ (NSString *)localizedStringForKey:(NSString *)key replaceValue:(NSString *)comment {
    NSString *fallbackLanguage = @"en";
    NSString *fallbackBundlePath = [[NSBundle mainBundle] pathForResource:fallbackLanguage ofType:@"lproj"];    
    NSBundle *fallbackBundle = [NSBundle bundleWithPath:fallbackBundlePath];
    NSString *fallbackString = [fallbackBundle localizedStringForKey:key value:comment table:nil];    
    NSString *localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:fallbackString table:nil];

    return localizedString;
}
Share:
30,178
Volker Voecking
Author by

Volker Voecking

Updated on July 09, 2022

Comments

  • Volker Voecking
    Volker Voecking almost 2 years

    Is there a way to set a default language to be used when the device UI language is not supported by an app?

    Example: My app is localized into English and German:

    // en.lproj:
    "POWER_TO_THE_PEOPLE_BTN" = "Power";
    "POWER_PLUG_BTN" = "Power";
    
    // de.lproj:
    "POWER_TO_THE_PEOPLE_BTN"  = "Macht";
    "POWER_PLUG_BTN" = "Spannung";
    

    Now, if I run the app on a device with UI language set to Italian the app will use the key strings POWER_TO_THE_PEOPLE_BTN and POWER_PLUG_BTN.

    There must be a way to specify a default (fallback) language to be used by the application in such a case.

    From the above example it should be clear that using the English string as a key will not work.

    The only option I see right now is to use NSLocalizedStringWithDefaultValue instead of NSLocalizedString.

  • Felix
    Felix over 10 years
    The fallback language is the first language in [NSLocale preferredLanguages] that is supported by the app. It is not always english. If you change the language in the settings it will move to the top of the list.
  • Jona
    Jona over 9 years
    Thanks for sharing. I do like your provided solution. It's a smart way of using iOS crappy fallback system where it returns the key if it doesn't find the string.... :P :)
  • hyperspasm
    hyperspasm over 9 years
    To expand on/rephrase this, the fallback language is the language which was most recently chosen by the user in Settings, that is also represented in the app's bundle.
  • MANIAK_dobrii
    MANIAK_dobrii over 8 years
    This is (currently) the only correct solution apart from the crutches (could be suitable at the moment) suggested by the others. For details check this article: maniak-dobrii.com/understanding-ios-internationalization
  • Dan Rosenstark
    Dan Rosenstark over 8 years
    I did a riff on this so it falls back per-string and not per-language. It's possible that I missed the point entirely, of course, but it appears to work in practice. github.com/drosenstark/categories
  • Sunil Kumar
    Sunil Kumar over 8 years
    This is not getting called. I have created the category on NSBundle and passed the supported language array.
  • Siamaster
    Siamaster almost 8 years
    I plus oned it, but I regret it now. I had set up my phone to choose a language in this order : Swedish, French, English. I had no localization for Swedish so I wanted it to fallback to English, but instead it fell back on French. See my solution.
  • Otávio
    Otávio over 7 years
    This does not seem to work anymore, tested a device with Finnish language available only in the settings. The app has Finnish and English translations, en is defined in the Info.plist for the key CFBundleDevelopmentRegion still the keys that does not exist in the Finnish .string files don't fallback to English version.
  • Makalele
    Makalele over 6 years
    Doesn't work on iOS 11, sorry. I'm getting keys instead of translations (from Base).
  • Rahul Bansal
    Rahul Bansal about 4 years
    Can we set fallback language as English regardless of language which was chosen most recently?