Blog headline image

Generating Localized XIBs Automatically as Part of Your Xcode Build

August 23rd, 2012 by ‐ No Comments

As often, Apple’s documentation is rather terse on how to use their most elegant solution for localizing user interfaces. The two example command lines in the developer documentation kind of get the point across. But beware – of course there is zero support for this scheme in Xcode. If you don’t have an extremely complex setup, there is a simple solution. So we thought we’d best share it. 

The solution is based on a fairly moderate assumption: that you keep your xibs and strings files in the “.lproj” directories as recommended by Apple.

Using ibtool, the workflow is quite straightforward:

  • Create your user interface using Interface Builder as usual, and using your standard development language (we’ll assume English for the sake of example).
  • In Xcode, localize the xib file, and assign it to the English locale. This will move the xib to the “en.lproj” subfolder.
  • Use ibtool to generate a strings file from the xib you created in the previous step.
  • Add the strings file to your project in Xcode, and make it localised, and assign it to the English locale, too. It will be moved to the “en.lproj” subfolder, too.
  • Add all the localizations that you want to provide besides English to your Xcode project.
  • Copy the strings file from the “en.lproj” subfolder to all other “.lproj” subfolders.

Now your structure should look similar to this:

    .../MyProject/
                  ...    # source files etc.
                  en.lproj/
                           MyProject.xib
                           MyProject.strings

                  de.lproj/
                           MyProject.strings

                  es.lproj/
                           MyProject.strings

Now you can ship the non-English strings files to the translation service. In the meantime, you can set up your Xcode project to create the missing xib files for you during the build. To get this, you’ll add a new shell script build phase. Be sure to add it before any copy bundle resources or similar steps. We suggest adding it as number two, right below the target dependencies. Here is what it looks like:

No need to worry, here is your copy/paste source:

##
# adjust settings here
##
src_locale="en"                   # this is the language you design in
target_locales="de es fr"         # these are the translations you provide
xib_file="MyProject.xib"          # the name of your XIB interface builder file
strings_file="MyProject.strings"  # the name of your strings file
##
# no customizations below this line
##
# Extract source locale strings (use this to check if you added new strings to your xibs)
echo -n "Updating "$src_locale" strings file... "
ibtool --generate-strings-file $src_locale.lproj/$strings_file $src_locale.lproj/$xib_file
echo "done"
# Generate localized interfaces
for locale in $target_locales ; do
    echo -n "Generating "$locale" interface... "
    if [ -d "$locale.lproj" ] ; then
        if [ -f "$locale.lproj/$strings_file" ] ; then
            ibtool --strings-file $locale.lproj/$strings_file --write $locale.lproj/$xib_file $src_locale.lproj/$xib_file
            echo "done"
        else
            echo "strings file "$locale.lproj"/"$strings_file" not found in locale dir "$locale".lproj - skipping "$locale" locale"
        fi
    else
        echo "locale dir "$locale".lproj not found - skipping "$locale" locale"
    fi
done
##
# end of script
##

Make adjustments in the top section as needed for your project. Also, if you have several xib files, the script can easily be extended.

If you tell Xcode what the in- and output files of your script are, it will be able to clean up properly for you when do a clean build, make informed decisions on when to rebuild/uncache/… what after you made changes. So we strongly suggest you add the files to the lists at the bottom of your build phase as shown in the picture on the right. Note that the $(SRCROOT) variable reference is different from what Xcode will prefill for you when you press the little “+” signs.

Now, when the strings files come back from the translators, copy them over the corresponding non-English versions in the “.lproj” subfolders. Be sure to diff against the original, English strings file to make sure they did not fiddle with any text outside the quotes.

After installing the translated strings files, and with our script build phase in place, you can just hit build. This will complete the ibtool workflow we commenced above:

  • First our script will re-generate the English strings file from the original English xib file. In case you made any changes in Interface Builder, the English strings file will show up as modifed (“M”) in Xcode’s project navigator. This is to be sure you’re pointed to the fact that there are changes that still need to be translated.
  • Then, it will take the English xib file, and have ibtool do a search-and-replace operation on it using the translated strings file, and save the result as a new, translated xib file. This is repeated for all languages you want to provide.
  • This concludes the work of our little script.
  • In the remaining build process, as we configured our xib to be localized, Xcode will recognize the various xib files, compile them to nib files, and copy them to the right locations in the final bundle.

That’s all. Now you will notice newly generated xib files in the “.lproj” subfolders:

    .../MyProject/
                  ...    # source files etc.
                  en.lproj/
                           MyProject.xib
                           MyProject.strings

                  de.lproj/
                           MyProject.xib             [?]
                           MyProject.strings         [M]

                  es.lproj/
                           MyProject.xib             [?]
                           MyProject.strings         [M]

Note that the new xib files have not been added to version control (“?”). This is as intended, and you should not add the non-English language xib files to version control! They are auto-generated on every build, hence there is no point in committing them.

It’s a pity that Apple don’t provide such simple stuff as build rules provisioned in Xcode. Or at least document the process better. We hope that our little trick will help you getting going with making your apps multilingual. By the way, if you’re using storyboards, that’s just fine. ibtool knows how to deal with these, too.