Cocoa: Internationalization (i18n) and Localization (L10n)

A multilingual application

  • Binary and resources (interface, images, sounds..) are separated
  • For every language there's a resources folder containing:
    • NIB files
    • Localized text used by the binary (Localizable.strings)

Add a localization

  • click on the NIB file and press command-i
  • Under “general”, click on “Add Localization”, enter a name (ex: German)

Localize strings in your source code

Use keys in your code

NSString *NSLocalizedString(NSString *key, NSString *comment)

Example: (will look for the localized text in default Localizable.strings)

NSString *toDisplay = NSLocalizedString(@"explode_soon", @"Explain that the computer is going to explode");

Put genuine strings in Localizable.strings

  • generate .strings file from your source files
# generate a new file: Localizable.strings, with keys in alphabetical order
$ genstrings *.m
  • move it into a resource folder
  • drag it to your Xcode project window under the “Resources” group (you have to do that just for one resource folder)

Useful python script for any modification

diffstrings.py

Compare two .strings file (display deleted and added keys). Example:

$ ./diffstrings.py English.lproj/Localizable.strings Localizable.strings
*** Deleted keys ***
message.undo.flag_operations
message.3.error.duplicated_entries %@
message.2.warning

*** Added keys ***
message.1.info.importing %@
category.default.new

Localize strings in NIB files

Method 1

  • Copy the reference NIB
  • Localize the copy (open it with InterfaceBuilder and localize texts)

Pb: every modification if the reference NIB will also have to be done to other NIBs (adding an outlet, a button..) and you'll have to make sure not to forget any text in the NIB..tedious.

Method 2

First:

  • Extract text from reference NIB to .strings file
nibtool -L French.lproj/MainMenu.nib > MainMenu.strings
  • Localize .strings file
  • Generate localized NIB file from reference NIB and localized .strings
nibtool -d English.lproj/MainMenu.strings French.lproj/MainMenu.nib -W English.lproj/MainMenu.nib
  • Keep somewhere the localized and non-localized .strings files

For any modifications to the reference NIB:

  • Extract text from reference NIB to .strings file
  • Merge .strings file to previous localized .strings file, translate new text
  • Generate localized NIB file from reference NIB and new localized .strings file
nibName=DetailsWindow
nibtool -d English.lproj/${nibName}.strings French.lproj/${nibName}.nib -W English.lproj/${nibName}.nib
  • Keep somewhere the new localized and non-localized .strings files

Pb: there shouldn't be any difference accross NIBs but text. In particular, every element (button, text field) should have the same size accross the NIB files. So, make them big enough in the reference NIB!

Note: in the code above, the French NIB is the reference.

Notes

  • You can build your software using your first language first. Then you can add English and other languages localizations.
  • It's good to build the interface using a language like French, so you will make big enough buttons and text fields. English words are usually shorter.
  • It's also good to write the code using English for variables names and comments, if you intend to open the source code in the future.

Reference

Apple Developer Connection: Introduction to Internationalization Programming Topics

Stone Design: Internationalizing Cocoa Applications

Stepwise: Internationalizing Cocoa applications

Feedback

If you're involved in localization projects and are interested in tools that can help you better manage the string translation process, you might want to check out the online platform https://poeditor.com/
It can automate the translation workflow a lot due to being equipped with API andTranslation Memory, and offering a platform for collaborative work.
Kokakol
Aug 25, 2014
#1