Strings are perhaps the most versatile data type in computing. They’re passed around as symbols, used to encode numeric values, associate values to keys, represent resource paths, store linguistic content, and format information. Having a strong handle on user-facing strings is essential to making a great user experience.

In Foundation, there is a convenient macro for denoting strings as user-facing: NSLocalized String .

NSLocalized String provides string localization in “compile-once / run everywhere” fashion, replacing all localized strings with their respective translation according to the string tables of the user settings. But even if you’re not going to localize your app to any other markets, NSLocalized String does wonders with respect to copy writing & editing.

For more information about Localization (l10n) and Internationalization (i18n) see the NSHipster article about NSLocale.

NSLocalized String is a Foundation macro that returns a localized version of a string. It has two arguments: key , which uniquely identifies the string to be localized, and comment , a string that is used to provide sufficient context for accurate translation.

In practice, the key is often just the base translation string to be used, while comment is usually nil , unless there is an ambiguous context:

text Field . placeholder = NSLocalized String ( @"Username" , nil );

NSLocalized String can also be used as a format string in NSString +string With Format: . In these cases, it’s important to use the comment argument to provide enough context to be properly translated.

self . title = [ NSString string With Format : NSLocalized String ( @"%@'s Profile" , @"{User First Name}'s Profile" ), user . name ]; label . text = [ NSString string With Format : NSLocalized String ( @"Showing %lu of %lu items" , @"Showing {number} of {total number} items" ), [ page count ], [ items count ]];

NSLocalized String & Co.

There are four varieties of NSLocalized String , with increasing levels of control (and obscurity):

NSString * NSLocalized String ( NSString * key , NSString * comment ) NSString * NSLocalized String From Table ( NSString * key , NSString * table Name , NSString * comment ) NSString * NSLocalized String From Table In Bundle ( NSString * key , NSString * table Name , NSBundle * bundle , NSString * comment ) NSString * NSLocalized String With Default Value ( NSString * key , NSString * table Name , NSBundle * bundle , NSString * value , NSString * comment )

99% of the time, NSLocalized String will suffice. If you’re working in a library or shared component, NSLocalized String From Table should be used instead.

At runtime, NSLocalized String determines the preferred language, and finds a corresponding Localizable.strings file in the app bundle. For example, if the user prefers French, the file fr.lproj/Localizable.strings will be consulted.

Here’s what that looks like:

/* No comment provided by engineer. */ "Username"="nom d'utilisateur"; /* {User First Name}'s Profile */ "%@'s Profile"="profil de %1$@";

Localizable.strings files are initially generated with genstrings .

The genstrings utility generates a .strings file(s) from the C or Objective-C (.c or .m) source code file(s) given as the argument(s). A .strings file is used for localizing an application for different languages, as described under “Internationalization” in the Cocoa Developer Documentation.

genstrings goes through each of the selected source files, and for each use of NSLocalized String , appends the key and comment into a target file. It’s up to the developer to then create a copy of that file for each targeted locale and have a localizer translate it.

No Madlibs

After reading that part about localized format strings, you may be tempted to take a clever, DRY approach by creating reusable grammar templates like @"{Noun} {Verb} {Noun}" , and localizing each word individually…

DON’T. This cannot be stressed enough: don’t subdivide localized strings. Context will be lost, grammatical constructions will be awkward and unidiomatic, verbs will be incorrectly conjugated, and you’ll have missed the point entirely—taking great effort to make something worse than if you hadn’t bothered in the first place.

Numbers, dates, and similar values are almost always safe replacements. Nouns are subject to pluralization and verb conjugation, but usually safe as direct or indirect objects.

For additional guidelines, see Apple’s Internationalization and Localization guide.

NSLocalized String is a remarkably reliable indicator of code quality. Those who care enough to take a few extra seconds to internationalize are very likely to be just as thoughtful when it comes to design and implementation.

Always wrap user-facing strings with NSLocalized String .