Learning Cocoa with Objective-C/Miscellaneous Topics/Localization

From WikiContent

< Learning Cocoa with Objective-C | Miscellaneous Topics
Revision as of 12:56, 7 March 2008 by Docbook2Wiki (Talk)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search
Learning Cocoa with Objective-C

If an application will be used in more than one part of the world, its resources should be customized, or localized, for the language, country, or cultural region. Cocoa provides a group of conventions and services, known as an internationalization architecture , that are flexible enough to enable multiple localizations of character strings, icons, user interfaces, and even context help packaged into your application. The localized resources appropriate to the user's preferences are dynamically loaded as needed.

The aim of Cocoa's localization architecture is to enable multilingual applications to be created without generating any new Objective-C code for each supported locale. Even if you don't have an immediate need for multilingual support in your application, it is always a good idea to keep the localization abilities of a Cocoa application in mind, so you can enable it when the need arises. With proper design, your application's source code won't have to be touched if and when it does need to be localized—minimizing the risk of introducing problems by modifying the code.

In this chapter, we'll take a look at how Cocoa's localization system works, how it depends on the user's language preferences, and how to structure your application's nib files and use of strings to take advantage of it.


Mac OS X Language Preferences

To see how Mac OS X supports different languages, try the following process:

  1. Open the TextEdit application (/Applications/TextEdit), and take a look at its user interface.
  2. Close TextEdit, and open the System Preferences application. Select the International preferences panel.
  3. Reorder your preferred language order by dragging Français to the top of the list, as shown in Figure 14-1.

    Figure 14-1. Changing language preferences

    Changing language preferences

  4. Open TextEdit again, and notice how the menu items are now in French rather than English, as shown in Figure 14-2.

    Figure 14-2. TextEdit running in French

    TextEdit running in French

  5. Quit TextEdit (File → Quit, or [[Image:Learning Cocoa with Objective-C_I_3_tt520.png|]]-Q), and then reset your language preferences to English.

What just happened here? By changing the System Preferences, TextEdit uses Mac OS X's and Cocoa's internationalization system to display the correct interface for the locale we specified. Under the hood, the system is using localized interface components stored within separate files and directories within the application's bundle.

Localizing Resources

In Chapter 13, we took a look at how Cocoa applications are packaged into application bundles. These bundles can contain multiple sets of resources, each set contained in a directory with an .lproj extension and identified by a combination of language and locale. The ability for bundles to hold all of the localized resources for an application, combined the ability for with bundle resource look-up routines to be aware of a user's language preferences, is what enables one version of an application to support multiple languages.

To get a feel for how localized resources are stored inside an application bundle, take a look at the contents of the Clock application.

  1. Use the Finder to locate the Clock application (/Applications/Clock).
  2. Control-click on the Clock application icon, and select Show Package Contents from the pop-up menu.
  3. Select View → List from the Finder menus, browse through the application as shown in Figure 14-3, and notice the files shown.

    Figure 14-3. Localized resources in the Clock application bundle

    Localized resources in the Clock application bundle

As you can see, the same files, Clock2.niband InfoPlist.strings, exist in various subfolders of the Resources folder. These subfolders, which have a language name or country code and a .lprojextension, contain the language-support files for the project.

Mac OS X defines localizations using three different conventions. Each convention allows a different degree of specificity.

A language name
Languages supported by Mac OS X include English, French, German, Japanese, Chinese, Spanish, Italian, Swedish, and Portuguese.
A language abbreviation
The language abbreviations, some of which are shown in Table 14-1, conform to the ISO 639 specification.

Table 14-1. Some common language abbreviations supported by Mac OS X

Language Country code or abbreviation
Chinese zh
Danish da
Dutch nl
English en
French Fr
Korean Ko
Polish Pl


You can easily find language abbreviations on the Web by searching for "iso 639". One resource is OASIS-OPEN (http://www.oasis-open.org/cover/iso639a.html).

A locale abbreviation
The locale abbreviations consist of a language abbreviation (see Table 14-1), followed by an underscore and a two letter code. These codes, some of which are shown in Table 14-2, conform to the ISO 3166 specification that can identify a regional variant of a language.

Table 14-2. Some regional language codes

Region Locale abbreviation
British English en_UK
American English en_US
Canadian French fr_CA
Tawainese Chinese zh_TW
Mainland China Chinese zh_CN


Again, you can easily find country abbreviates on the web by searching for "iso 3166". OASIS-OPEN has a resource at http://www.oasis-open.org/cover/country3166.html.

A common practice of developers is to use the traditional language name for those that exist, then to use the language abbreviation, and then—only when necessary—the regional variant abbreviation.

Localized Resource Search Algorithm

Cocoa's various resource-handling methods in the NSBundle class automatically return the filesystem location of the resource that best matches the user's language and regional preferences. These methods look for resources of the following types until a matching resource is found:

Global Resource
Files that are stored at the top level of the Resources directory in the bundle
User Region Specific Resource
Files that are stored in a regional directory (such as en_UK.lproj) under the Resources directory, as specified by the user's preferences
User Language Specific Resources
Files that are stored in a regional directory (such as English.lproj, da.lproj, or French.lproj), as specified by the user's preferences
Developer Region Specific Resource
Files that are in a regional directory (such as en_UK.lproj), as specified by the region in which the application was developed
Developer Language Specific Resource
Files that are in a language directory (such as English.lproj, da.lproj, or French.lproj), as specified by the region in which the application was developed

Note that global resources take precedence over localized resources. This allows a quick return of resources that never change between locales, without going through the rest of the search process. You shouldn't have a global version of a resource if you have localized versions, as the localized versions will always be masked by a global version.

Localizing Nib Files

Nib files are typically localized all at once. A person performing localization takes a nib file, translates all the user-visible strings, and makes any adjustments that are necessary, such as resizing controls so that the translated strings appear correctly.

To illustrate how to localize nib files, we will create an application interface that isn't hooked up to anything, but which contains various controls that we can localize. The following steps will guide you:

  1. Create a new Cocoa Application project in Project Builder (File → New Project → Application → Cocoa Application) named "Localization", and save it in your ~/LearningCocoa folder.
  2. Open the MainMenu.nib file in Interface Builder by double-clicking on its icon in the Resources folder of the Groups & Files pane in Project Builder.
  3. Using the various controls available on Interface Builder's palettes, lay out an interface that looks like Figure 14-4.

    Figure 14-4. Our Localization application's interface

    Our Localization application's interface

  4. Create a subclass of NSObject. Click on the Classes tab of the MainMenu.nib window, find NSObject, Control-click it, and select Subclass NSObject from the pop-up menu; name the subclass Controller.
  5. Create an outlet named statusField on the Controller object, using the Info window (Tools → Show Info, or Shift-[[Image:Learning Cocoa with Objective-C_I_3_tt523.png|]]-I).
  6. Create an action for the Controller subclass, named submit:.
  7. Create the files for the Controller subclass (Classes → Create Files for Controller).
  8. Instantiate the Controller subclass (Classes → Instantiate Controller).
  9. Control-drag a connection between the Controller object and the Not Submitted text field, and connect it to the statusField outlet in the Info window.
  10. Connect the Submit button to the submit: method of the Controller by Control-dragging a connection from the Submit button to the Controller object.
  11. Save the nib file ([[Image:Learning Cocoa with Objective-C_I_3_tt524.png|]]-S), close the MainMenu.nib window in Interface Builder, and then return to Project Builder.
  12. In Project Builder's Groups & Files panel, click the disclosure triangle beside the MainMenu.nib file, and select the English entry underneath it, as shown in Figure 14-5.

    Figure 14-5. Looking at the single localization of the MainMenu.nib file

    Looking at the single localization of the MainMenu.nib file

  13. Bring up the Info panel (Project → Show Info, or [[Image:Learning Cocoa with Objective-C_I_3_tt526.png|]]-I).
  14. Select Add Localized Variant from the Localization & Platforms pop-up menu. You will be prompted for a locale. Enter French, as shown in Figure 14-6.

    Figure 14-6. Adding a French localization of the MainMenu.nib file

    Adding a French localization of the MainMenu.nib file

  15. Close the Info window by clicking on the red close window button.
  16. You should see two localizations of the MainMenu.nib file in Project Builder.
  17. Double-click the French variant to open it in Interface Builder.
  18. Modify the various strings in the interface to match Figure 14-7. To type in the ç character, type Option-e, then e again (without the Option key). Notice that you'll have to resize the window and move things around to accommodate the longer text fields.

    Figure 14-7. Our interface in French

    Our interface in French

  19. Save the nib file ([[Image:Learning Cocoa with Objective-C_I_3_tt529.png|]]-S), and return to Project Builder.
  20. Build and run the application ([[Image:Learning Cocoa with Objective-C_I_3_tt530.png|]]-R) to verify that everything works.
  21. Quit the application ([[Image:Learning Cocoa with Objective-C_I_3_tt531.png|]] -Q).
  22. Launch the System Preferences application in the Dock, and click on the International button to open its preferences panel.
  23. Change your language preferences from English to Français by clicking on Français and dragging it to the top of the list in the Languages window.
  24. Run the application again to see the French interface run.
  25. Quit and return to the System Preferences; reset your preferred language to English by dragging it to the top of the list.

Localizing Strings

Not all strings used by a program are located in a nib file. Many strings, such as those that appear in dialog boxes, are usually encoded directly in source code. To localize these strings without requiring changes to the source, Cocoa provides a function to look up strings against a strings file directly from code. This function has the following signature:

NSLocalizedString(NSString *key, NSString *comment);

This function uses the localizedStringForKey: value : table : method of the NSBundle class to look up the strings out of the main application bundle. We will add a couple of .stringsfiles (and a bit of code that uses them) in our project to illustrate how this works.

  1. Add a new file, named Localizable.strings,to the project in Project Builder (File → New File → Empty File). Save it to the ~/LearningCocoa/Localization/English.lprojfolder. Make sure that it is in the Resources group, as shown in Figure 14-8.

    Figure 14-8. Adding a Localizable.strings file

    Adding a Localizable.strings file

  2. Edit the new file to have the following text:

    "Not Submitted" = "Not Submitted";
    "Accepted" = "Accepted";
  3. Bring up the Info panel (Project → Show Info, or [[Image:Learning Cocoa with Objective-C_I_3_tt535.png|]]-I).
  4. Select Add Localized Variant from the Localization & Platforms pop-up menu. You will be prompted for a localization. Enter French, and then close the Info window.
  5. Click on the disclosure triangle next to the Localizable.strings file. Beneath that, you will see two files: English, which we created in steps 1 and 2; and French, which we created in the previous step.
  6. Edit the French variant of the file to match the following text:

    "Not Submitted" = "Non soumis";
    "Accepted" = "Admis";
  7. Edit the submit: method of the Controller.mfile.
    - (IBAction)submit:(id)sender
        [statusField setStringValue:NSLocalizedString(@"Accepted", nil)];

    This code sets the value of our status field to the localized form of the Accepted string.

  8. Save the project (File → Save, or [[Image:Learning Cocoa with Objective-C_I_3_tt538.png|]]-S).
  9. Build and run ([[Image:Learning Cocoa with Objective-C_I_3_tt539.png|]]-R) the application. Test out the Submit button, and make sure that the status field changes.
  10. Quit the application, and set Français as your preferred language using System Preferences.
  11. Run the application again to see the French interface run. Click the Submit button.
  12. Quit and return your preferred language to English.


  1. Localize the Currency Converter project from Chapter 5 into the language of your choice. Use the Translation channel of Sherlock 3 if you need help translating the strings.
Personal tools