- Translating GUIs
- Time and Dates
- Translating Text
- Caching Locale Information
- When Not To Localize
It is incredibly tempting to hard-code strings in Cocoa. Creating a literal string is very easy. There are very few cases where this is actually a sensible thing to do. If you are using a string as the name of a key in a dictionary, or the name of an exception, then you should declare it like this:
extern NSString *kSomeKey;
And then define it in an implementation file like this:
NSString *kSomeKey = @"kSomeKey";
This means that everywhere you use kSomeKey you will be using the same instance. This saves a small amount of memory but, more importantly, means that you can use pointer comparison to compare the two strings, which is a lot faster than comparing their values. This is such a common idiom that EtoileFoundation provides some macros that let you declare constant strings even more easily.
For strings that are presented to the user, Cocoa provides some functions that make localization easier. The NSLocalizedString() function looks up a string at run time. These strings are loaded from a .strings file in the user dictionary. This is a simplified version of a property list, which just contains a set of key-value pairs. If the strings file is not available, this function returns the input string. This makes it trivial to use while developing, you just pass it the version for your own locale and it is almost equivalent to using hard-coded strings.
You can automatically generate a strings file for a project with the genstrings utility. This will create a strings file containing all of the strings that your code tries to access. The first argument to NSLocalizedString() will be used as a key in the strings table and the second argument will be a used as a comment above the string. This is used to provide some metadata to translators. For example, if a string is a single word, like "Print," then you might want to indicate that you mean the verb, not the noun, as they might be completely different words in the target language. Your application would look quite silly if it had a file menu item which said the local language version of print-as-in-printed-artwork.
To simplify creation of localized strings, GNUstep provides this macro:
#define _(X) NSLocalizedString (X, @"")
This lets you define localized strings trivially, with just three more characters to type than a non-localized string. In your code, you'd just use _(@"Some string") instead of @"Some string".