6
votes

I know many developers just do it like this: They start developing their app in English, and put NSLoclaizedString(@"Tap this to do that!", @"Telling what to do...") instead of simply @"Tap this to do that!".

Then they run genstrings which creates a Localizable.strings file somehow by extracting all these strings. The messy part: The long text used in code becomes the key. It works. Until one day where you quickly go into your code and change the english string and forget about Localization and that it serves as the key for all those Localizable.strings files.

So I tend to use "real" keys which don't get mixed up with strings. For a quick test I created a project localized to English and French. Then I set the Simulator language to German. Because, you know, it would suck terribly if the user would ever see the key like TTTDT.

So with just English and German in place, I launched the demo app. And what I got was the English text from the English Localizable.strings file.

Conclusion: It seems that NSLocalizedString falls back to the English file if the OS language is not covered by the app.

Quesion: Assuming there IS always an Localizable.strings (English) file, and the keys ARE in the file along with properly formatted values. Are there circumstances under which NSLocalizedString would fail and then display the key directly?

4

4 Answers

4
votes

To answer your question: Yes, I have experienced the issue you are worrying about, i.e. the key names showed up even though a localizable.strings file was present and included entries for those key names. This happens when you have more than one localizable.strings files in your project. Which can easily happen if you drop a set of files from an Open Source project that has their own localizable.strings (such as ShareKit) into your project.

Here is a related question that discusses this issue.

But at least if you use ID-style key names, you would notice such a problem when you test your app in any language. If you used the English (or base language) string as the keys, then you wouldn't see this insidious problem until you test the localized versions and it could slip by unnoticed more easily.

So on top of your point on having to remember to update the keys (in all languages) when rewording text, there is the issue of potentially hiding bugs when using the English text as key (English would look OK, but localized versions wouldn't). Therefore it seems to me that using "real" key names rather than actual text is more practical. If you are still worried that for some reason the key names might show up, pick a key that is at least descriptive enough to be understandable.

1
votes

We tend to use "real" keys but they are usually the English text (or an abbreviated form) and add "Key" to the end. That way it is clear.

0
votes

I wrote some custom code which actually verifies that all the keys in the app appear in all the localizable.string files. There were two steps to this process - using genstrings to generate a new localizable strings file containing all the keys currently referenced in the source. Then I used some objective-C api's to load in my existing localizable.strings files, and compared that they all had the exact same set of keys (no more and no less) as the newly generated one.

0
votes

I think a better approach (especially for we programmers) can be:

1) put TECHNICAL strings in code

2) traslate with a dedicate convenience function

In This way:

a) more details for us

b) we modify ONLY localized string in "Localizable.strings"

c) we can send a plain "Localizable.strings" externally without going crazy to search strings on code and replacing them, once got translation.

d) adding a language is a matter of 2 clicks, and pasting a text.

e) we can make errors more generic/ more gentle to final user:

sample:

"NETWORK_ERROR" = "Network error";

"NETWORK_ERROR_NO_DATA" = "no data. Pls check settings";

"NETWORK_ERROR_NO_JSON" = "no data. Pls check settings";

Final user cannot understand 404 or JSON parsing error, so as google does..

"Opps... a network error occurred". (Coder will see the real cause in code)

and finally... start EARLY to localise.

convenience f.:

func localized(_ msg: String)->String{
    let s = NSLocalizedString(msg, comment : "")
    return s
}