When developing software professionally it is critical to consider maintainability or in this case how additional/changed requirements (and bug-fixes) over time may be made easier/harder by your programming practices. Often quick dangerous gains are possible that are fast to implement in the short-run but becomes incredible burdensome over time as it makes future changes more and more difficult and costly. One such example is the famous anti-pattern of using “copy-paste” programming which, when used systematically, is a frequent symptom of lack of competence, lack of experience or an insufficient development environment/language.
So imagine my horror when diving into iOS programming for IPhone/IPad and finding out that the way Apple want you to localize your GUI is by effectively using “copy-paste”. More precisely, when using storyboards to define the GUI in Xcode, Apples wants you maintain separate versions for each language (storyboards are Apple’s latest GUI development feature in Xcode for iOS 5+)
Each storyboard contains a combination of gui-elements definitions, gui layout, interactions and outlet-connections to code elements. In other words, storyboard files are pretty comprehensive and complex. Storyboards (measured by their XML representation) are also pretty large. In my current iOS app, it is the largest source file bar none.
Small divergences between storyboards representing the same GUI but in different human languages, can result in program failures or crashes. Hence, having many localized storyboards for the same App makes the GUI potion of the app much more expensive to develop, test and change/maintain in much the same way the copy-paste anti-pattern does for code.
So what to do for iOS GUI localization when using storyboards?
It is pretty simple actually if you start by ignoring all Apple documents/tutorials on localizing storyboards/nibs and:
- Make sure you do not specify any languages under Localization in the storyboard settings.
- Make sure your storyboard file is not placed under any of the *.lproj localization folders (move it back into a suitable folder like your source root folder if necesary).
- Replace all texts/titles in the storyboard with placeholders (eg. “X” -> “<X>”) so you can still see what is what when editing the storyboard yet also see if something is unlocalized when running the app.
- Create storyboard outlets to properties in your code for all control elements that contain text.
- Make sure the project has the needed *.lproj localization folders. Add any missing languages under Project/Info settings.
- Make sure each *.lproj localization folder has a file called Localizable.strings as described by Apple for localized texts.
- Add localized texts strings for all your texts/titles in your Localizable.strings files in the typical key-value fashion as described by Apple for localized texts.
- In the viewDidLoad method, set the titles of all GUI elements to strings loaded from resource files. For example to localize the text on a button having an outlet property called ibButton, add code like this: “ibButton.title = NSLocalizedString(@”myButton”, nil)“;
- Special case: The title used on the “Back” navigation item in navigation bars needs to be set in the controller before the controller which shows the navigation item. In the source controller use code like this: “self.navigationItem.backBarButtonItem.title = NSLocalizedString(@”back”, nil)“.
- Run the app and verify that all placeholder texts are replaced by actual localized texts.
That is it. With just one storyboard (per device) you can easily add and maintain (and test) support for any number of languages in your iOS user interface!