Support for Internationalization

Both OS X and iOS support internationalization and localized content in a variety of ways.

The notion of a preferred language set and the mechanisms of bundles, localized resources, and runtime binding are behind this support.

How Users Specify Language Preferences

Users specify the languages they would prefer to see using the preferences of the target platform. Figure 1 shows the interface used to select language preferences in both OS X (v10.6) and iOS.

Figure 1  Language preferences
Language pane of the System Preferences International moduleLanguage pane of the System Preferences International module

In iOS, the user designates a preferred language by navigating to General > International > Language in the Settings application. Because iOS-based devices support only one user, only one language at a time is selected. In OS X, the Language & Text system preference panel lets the user designate both a preferred language and one or more fallback languages in case the preferred language is unavailable.

The system stores the list of languages as a per-user default under the AppleLanguages key. It is not recommended that you retrieve the value of this key directly though. The codes found in the database may not include the canonical forms of the language or locale IDs. Instead, you can use the preferredLanguages method of the NSLocale class or the CFLocaleCopyPreferredLanguages function to retrieve the user’s list of preferred languages.

When your application requests the path to a resource file in its bundle directory, the bundle interfaces search for a resource whose localization most closely matches the preferred languages of the user. The bundle interfaces consist of the NSBundle class in the Foundation framework and the functions supporting the CFBundleRef type in Core Foundation. These interfaces provide support for locating resource files inside your application’s bundle directory. When searching that directory, they always return the localized resource that is most appropriate for the current user. If a localization does not exist for the user’s preferred language, the search continues using the user’s preferred fallback languages (where appropriate). If none of the bundle’s localizations match the user preferences, the interfaces return the resource associated with the localization used during development of the software.

When searching for resources in OS X, the bundle interfaces take into account the user’s preferred region settings in addition to the preferred language settings. For languages that have multiple dialects, an application can specify custom resource files for each region. For example, for the English language, an application might include different sets of resource files for users in the United States, Great Britain, Canada, and Australia. By using the user’s preferred region settings, the bundle interfaces are able to return even more precisely localized content to the user. This support is available in OS X only, though; in iOS, only the preferred language is taken into consideration.

How Users Specify Locale Preferences

Locale preferences convey regional differences for the way dates, times, and numbers are displayed. OS X and iOS specify predefined locales for many world regions, as shown in Figure 2. In iOS, the user can select the desired region only, but in OS X the user can also customize the information for any of the default locales to further personalize the system.

Figure 2  Locale preferences
Locale information in Formats paneLocale information in Formats pane

In most cases, your code should never have to worry about applying locale preferences. Most APIs take the user’s preferences into account when getting or formatting locale-sensitive data. However, there may still be situations where you need to get locale information. For example, you might want to display the current locale settings, do comparisons of different locales, or apply locales other than the current locale to a specific piece of data. In those situations, the Foundation framework provides the NSLocale class and the Core Foundation framework provides the CFLocaleRef opaque type for retrieving locale information.

Bundles

An application bundle is a directory containing your application’s executable binary and any associated resource files. Although iOS supports only application bundles, OS X supports many different kinds of bundles, including framework and plug-in bundles. Bundles provide a way to organize complex pieces of software to make them more manageable. The bundle directory acts as a top-level container for all of the files needed to make the application run. The structure inside that directory is then used to separate code and resources and to organize them in ways that make it easier to find things.

In order to understand how resource files for multiple languages may be stored inside a single application bundle, it is worth taking the time to examine the basic bundle structure of an application. Listing 1 shows the partial structure of a Mac app that contains a few localized resource files. The text on the left identifies the directories and files in the bundle while the descriptions on the right indicate the purpose of the key items.

Listing 1  Structure of a Mac app bundle

MyApp.app/                             The bundle directory
    Contents/
        MacOS/
            MyApp                      The application executable
        Info.plist
        Resources/                     All resources go here
            MyApp.icns                 Non-localized resources
            PeaceSign.tiff
            en.lproj/                  Resources localized for English
                StopSign.eps           A localized image
                Localizable.strings    Contains localized strings
                MyApp.nib              A localized nib file
            fr.lproj/                  Resources localized for French
                StopSign.eps
                Localizable.strings
                MyApp.nib
            ja.lproj/                  Resources localized for Japanese
...

As you can see from this structure, an internationalized application needs one .lproj directory for each localization it supports. The directories are named according to the language-version of the resources they contain. By default, a project directory contains only a single language directory corresponding to the language you are using to develop the application.

Although you could simply copy the files in your development language directory and translate them, the preferred way to create new localized resource files is using Xcode. When you select a resource file and open an inspector window, the General tab includes a Make Localizable button. Clicking this button for a resource file tells Xcode that it should place a copy of the original resource file in a language-specific project directory at build time. Each copy is based on the initial contents of the resource file. As your translators localize the files though, you can replace the initial file with the newly translated version and rebuild your project.

In an application bundle, there are several standard types of resources that require localization:

At localization time, you send the source-language .lproj folder (for example, en.lproj for developers in English-speaking countries) to a localization service, or to your in-house translation department. You also need to send the compiled application to allow the localizer to view dynamically-loaded resources in context, to ensure appropriate translations and to ensure adequate dimensions for user interface elements that display dynamically-loaded resources. For each target language, the translator sends back a .lproj folder in which each resource file has been appropriately localized.

The tool used by localization teams to edit resource files varies by resource type. Nib files are typically edited using the Interface Builder application. Other resource files can be edited with an appropriate editor. For strings files, you can use most text editors in OS X. Whenever possible though, use an editor that can save text in Unicode format, such as the TextEdit application. String files saved in Unicode format can be used in a running application directly, while other file formats must be converted to Unicode before they can be used.

For more information about bundles, the structure of bundles (including the structure of iPhone applications), and how you use the bundle interfaces to locate resources, see Bundle Programming Guide.