Localizing Strings in iOS: Default (Fallback) Language

Fallback language iOS (with incomplete Localizable.strings file)

As far as I know, there's no "official" way to do it, but I have implemented functions such as this before:

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;
}

borrowed from: https://stackoverflow.com/a/8784451/1403046

Basically, instead of NSLocalizedString(), which will return the input string, this version will fallback to English if necessary.

Localizing strings in iOS: default (fallback) language?

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.

Use default language fallback when key is untranslated

To achieve this, you could use the English words as the keys in the Localizable.strings file.

Another approach would be to check the outcome of NSLocalizedString and return the default english version (using a 'forced' bundle) in case the result is the same as the key.

It could look something like this

extension NSString {
class func NSLocalizedStringWithDefault (key:String, comment:String)->String {
let message = NSLocalizedString(key, comment: comment)
if message != key {
return message
}
let language = "en"
let path = NSBundle.mainBundle().pathForResource(language, ofType: "lproj")
let bundle = NSBundle(path: path!)
if let forcedString = bundle?.localizedStringForKey(key, value: nil, table: nil){
return forcedString
}else {
return key
}
}
}

Localized.string (eng)

"test-key-1" = "Test 1";
"test-key-2" = "Test 2";

Localized.string (esp)

"test-key-1" = "El Test 1";

then you could use it like this (assuming locale set to 'es'):

println(NSString.NSLocalizedStringWithDefault("test-key-1", comment: "")) // El Test 1
println(NSString.NSLocalizedStringWithDefault("test-key-2", comment: "")) // Test 2 (from eng file)

Not the cleanest way to implement, but you get the idea.

Does iOS fall back on another regional localized string?

I tried it out on the simulator with iOS 10.3 and the result is:

If an es-MX translation exists, but no es translation, then the Localizeable.strings for a user with locale es-PE fall back to the base language, in my case en.

If anyone has a reference to the docs please comment and I will add it to the answer. Because if the behaviour is currently not defined it may change for future iOS versions or it may even depend on the language and region. There are regions that would qualify as "parent" for other regions, e.g. es-419 (Spanish Latin America) for es-MX (Spanish-Mexico), so it would be interesting how the fallback behaviour is defined.

However since es-419 is a distinct language one can choose in the iOS settings I assume the fallback hierarchy is:

base

|- es

|- es-MX
|- es-PE
|- es-419
|- es-ES

Localization fallback language

The other answers were definitely correct but it wasn't exactly what I wanted. Instead I found another way to do it and wrote a static method that works perfectly for me in my environment and I wanted to add it here if anybody else wants to acheive the same thing:

+ (NSString *)localizedStringForKey:(NSString *)key table:(NSString *)table
{
NSString *str = [[NSBundle mainBundle] localizedStringForKey:key value:@"NA" table:table];
if ([str isEqualToString:@"NA"])
{
NSString *enPath = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"];
return [[NSBundle bundleWithPath:enPath] localizedStringForKey:key value:@"NA" table:table];
}

return str;
}

iOS localizable string with default values

The NSLocalizedString macro takes two parameters, a key and a comment. The key will be looked up in Localizable.strings file, which is a simple key-value pair collection.

As @TheEye pointed out in the comments via the blog post link, you can exercise more control, and explicitly include a default value by using the NSLocalizedStringWithDefaultValue macro instead.

What you have to realize is that you have a choice: you can either use the simpler macro and treat your key as the default value (and iOS will fall back to that) or use the more specialized macro that is more verbose but gives you more control instead.

Note, this has already been discussed here: Fallback language iOS (with incomplete Localizable.strings file)



Related Topics



Leave a reply



Submit