DRY String Localization with Interface Builder

Great applications should have great localization. And users will appreciate an option to use beloved apps in their native language. There is no excuse for developers not to support interface localization even on early stages of the development process, especially when it’s so easy to do.

I prefer to design mostly with the Interface Builder. In this article I would like to share an approach I use in my projects to localize those resources.

Normally, when you try to localize a XIB file or storyboard, Xcode will happily clone the resource and you get stuck with duplicated view layouts. Yuck… That’s hardly a good option if you are trying to follow the DRY methodology 😕

Instead of doing that I suggest filling “at”-prefixed localization terms in the Interface Builder and replacing them with the localized values in viewDidLoad or awakeFromNib methods of the corresponding objects. Here is an example of how it looks like in the Interface Builder:

I use @ prefix for localization terms to allow mixing them with any real values as needed. Additionally, leading @@ sequence is replaced with a single @ in case you need to specify unlocalized string starting with the “at” symbol.

As it usually happens in Swift, we start with a protocol:

Followed by an extension containing some helpers to localize strings and apply localized values to properties:

Note: substring API is deprecated in Swift 4, should be replaced with dropFirst which also describes the original intent better.
Note: second localization helper should be upgraded to use the new KeyPath syntax when moving to Swift 4.

Ok, so far, so good. Now let’s start implementing some localization. The process itself is clearly recursive where each container asks its children to localize themselves:

Having implemented that, let’s add localization support for common controls required in most applications. The implementation is straightforward:

Notice that for UIButton title we use another helper function which applies localization for all possible control states.

Views are not the only objects we can configure with the Interface Builder. We should keep in mind the following objects too:

  • UIBarItem with it’s subclasses: UIBarButtonItem and UITabBarItem
  • UINavigationItem
  • Any other objects you decide to use in your app

Finally, we have to start the flow somewhere. I usually rely on the following events:

  • Localize title, navigationItem, tabBarItem and view in the viewDidLoad method of my UIViewController subclasses.
  • Localize contents of UITableViewCell and UICollectionViewCell subclasses in the corresponding awakeFromNib methods.

For the UIViewController here is a helper method to localize content, navigation and tab items:

Thanks for reading! Now it’s time to localize that pet project you’ve been working on 😉. Don’t forget to press 👏 if you did that or just found my article useful.