Fallback language iOS (with incomplete Localizable.strings file)
Asked Answered
H

4

20

I have an iOS project that is localized into 16 languages. Only some words are not localized (Mainly those that go into an update and the localization office did not deliver in time). For my keys I do not use the english wording, as this can also change if a translator wishes. So now if I just don't have a translation for a language, if falls back to the key that I used. But as this key is not 'human readable' or at least not 'human enjoyable to read' this is a problem.

I did some research but couldn't find a solution to my exact problem. I have fe.:

Localizable.strings in en.lproj
@"Key1" = @"Value 1"
@"Key2" = @"Value 2"

Localizable.strings in de.lproj
@"Key1" = @"Wert 1"
// Note that @"Key2" is missing here in my de.lproj

I would expect that if I make NSLocalizedString(@"Key2", ...)
and am running on a german phone, it falls back to the english
translation for this key as it exists...

So for now i just copied the english translation into the missing Localizable.strings files. But this is a big hack! But also using the english words as keys seems to be a hack to me!

Is there any way to tell my app, that it should use f.e. english as the fallback if there is no value for a given key? I tried adding a base localization but this doesn't help...

Thanks a lot

Heller answered 25/11, 2013 at 15:17 Comment(2)
"But also using the english words as keys seems to be a hack to me!" -- not at all. It's a pretty elegant solution, and exactly fixes the problem you're describing. Just because the translator might change the actual words used in the English translation, doesn't mean that the key has to change. That said, the new Base localization that Maxthon mentions is an even better approach most of the time.Infatuate
Using the word as a key is not an elegant solution. The key has to be unique. Imagine using the work "run" in English as the key. Depending on what you do this could be for example "løpe" og "kjøre" in Norwegian, or the imperative forms of those. There would have to be different keys for each meaning, not one key to cover them all because the English version is incidentally the same.Fisher
M
15

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://mcmap.net/q/383844/-localizing-strings-in-ios-default-fallback-language

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

Mystic answered 25/11, 2013 at 15:37 Comment(2)
That sucks... :) The problem is if i use L(...) the genstrings (used by Linguan) will not find it... but thanks for your answer... if I will not get an other response that's better, I will accept yours soon. Cheers!Heller
You can pass -s to genstrings to tell it what function you use instead of NSLocalizedString.Infatuate
B
6

Inspired by this and this, my Swift code version:

public func LS(_ key: String) -> String {
    let value = NSLocalizedString(key, comment: "")
    if value != key || NSLocale.preferredLanguages.first == "en" {
        return value
    }

    // Fall back to en
    guard
        let path = Bundle.main.path(forResource: "en", ofType: "lproj"),
        let bundle = Bundle(path: path)
        else { return value }
    return NSLocalizedString(key, bundle: bundle, comment: "")
}

Many developers expect an incomplete translation to fallback on the development language.. but that's not the way Apple choose to behave. I have a pseudocode to help better understand how Apple choose to fallback.

Brewage answered 24/1, 2018 at 6:12 Comment(2)
This solution is obviously WRONG because if key == value (what often happens with European languages) - it will always fall back to englishEctogenous
@Ectogenous If you create the strings file in peculiar way, it will work. For en, the key is always the same as the value. So if the european language is "Foo" = "Foo", then it will fall back to en, which is also "Foo" = "Foo". While it is wrong to fallback to en, the result is correct.Brewage
V
0

For Swift project SwiftGen tool can be used. It generates string constants that will contain fallback strings from base localisation language. If a string key is not found in the localization file for currently selected language then the fallback string will be used.

Example of a generated constant for CommonTextClose localization key from Localizable.strings file:

internal static let commonTextClose = L10n.tr("Localizable", "CommonTextClose", fallback: "Close")
Vise answered 30/12, 2022 at 15:27 Comment(0)
A
-7

You can use a Base localization and all unlocalized strings will be taken from this.

Alisealisen answered 28/11, 2013 at 3:53 Comment(4)
I did add a Base localization for my Localizable.strings but it is not taking the missing localizations from their... I was hoping it would do that, but it's not... Is there any setting I have to activate in Xcode?Heller
It is not true. Or I miss somethingExemplum
No this does not help. Base Internationalization simply let's you separate localizable strings from your xibs or storyboards into strings files which is surely a great help but doesn't solve anything here.Weekend
Read the Apple docs on Base Internationalization and you'll see this answer is completely wrongJebel

© 2022 - 2024 — McMap. All rights reserved.