Preprocessing InfoPlist.strings files in Xcode

Posted on September 3, 2009 by Brian Webster
Filed Under Cocoa, Development | Comments Off

Xcode provides a handy feature called “Info.plist preprocessing” that allows you to specify placeholder values in your plist that are then automatically replaced by Xcode with values you specify in your build settings. The most common use of this is to place the current build’s version number in one or more appropriate places in the Info.plist file. This lets you change these kinds of values in one place, rather than having to track down every usage in the Info.plist and replacing them manually.

In addition to the Info.plist file itself, you can also have one or more localized InfoPlist.strings files included in your application bundle. There are some strings in the Info.plist (e.g. CFBundleGetInfoString) which are displayed directly to the user, and thus need to be localized. Putting these keys in InfoPlist.strings instead of directly into Info.plist allows you to have localized versions of these strings.

However, Xcode’s Info.plist preprocessing only covers the actual Info.plist file, and not the various InfoPlist.strings files you may have included in your application bundle. This means that if you have a version number or some such that you want to keep up to date in one of these strings, you have to resort to replacing them manually, which is both error prone and a pain in the ass. I was able to solve this problem for my own project, and thought I’d share the details here in case it came in useful to anyone (and in case I forgot how to set it up in a future project and needed some help from my past self :) )

To get things working, I enlisted the help of a neat little tool called wincent-strings-util, courtesy of Wincent Colaiuta. It performs several tasks, but one of them is specifically geared towards doing this kind of substitution in a .strings file. In my setup, I simply include a copy of the tool in my project repository, so no installation is required and the build “just works” wherever you check out the project.

To get the substitution to be done when doing a build in Xcode, I defined a new build rule in my target to use a custom script to handle Info.plist files. To do this:

  1. Choose “Edit Active Target” from the Project menu, click on the “Rules” tab, then click the “+” button down at the bottom of the window to add a new build rule.
  2. From the “Process:” pop-up menu, select “Source files with names matching:” and then “*/InfoPlist.strings” in the field next to the pop-up. When I first tried this, I entered simply “InfoPlist.strings”, but that didn’t work because the match is against the whole path of the file, and not just the filename, so the * is necessary to match any file named “InfoPlist.strings”.
  3. From the “using:” pop-up menu, select “Custom script:”, then enter the following script text:

    cd "${BUILT_PRODUCTS_DIR}" && ${SRCROOT}/DevFiles/wincent-strings-util --info "${INFOPLIST_PATH}" --strings ${INPUT_FILE_PATH} --output /tmp/${INPUT_FILE_NAME} --encode UTF-16LE

  4. Where it says “With output files”, click the “+” button and enter “/tmp/${INPUT_FILE_NAME}” for the output filename

You can click here for a screenshot showing the completed build rule setup. A couple things to note:

Finally, to actually do a substitution, simply put a key from your Info.plist into the InfoPlist.strings file, enclosed in chevron brackets («»). For example, I have the following entry in my InfoPlist.strings file:

“CFBundleGetInfoString” = “PlistEdit Pro version «CFBundleShortVersionString», Copyright 2004-2009 Fat Cat Software.”;

This will replace the «CFBundleShortVersionString» placeholder with the value stored under CFBundleShortVersionString in the main Info.plist file. I have my Info.plist preprocessing already set up to include the version number of the build for CFBundleShortVersionString, so this will propagate that to the InfoPlist.strings files, and my version number will display correctly in the Get Info window for all localizations.

Comments

Comments are closed.

Feed