Blog

iOS localization tricks for Storyboard and NIB files

01 Nov, 2014

Localization in iOS from Interface Builder designed UI has never been without any problems. The right way of doing localization is by having multiple Strings files. Duplicating Nib or Storyboard files and then changing the language is not an acceptable method. Luckily Xcode 5 has improved this for Storyboards by introducing Base Localization, but I’ve personally come across several situations where this didn’t work at all or when it seemed buggy. Also Nib (Xib) files without ViewController don’t support it.
In this post I’ll show a couple of tricks that can help with the Localization of Storyboard and Nib files.

Localized subclasses

When you use this method, you create specialized subclasses of view classes that handle the localization in the awakeFromNib() method. This method is called for each view that is loaded from a Storyboard or Nib and all properties that you’ve set in Interface Builder will be set already.
For UILabels, this means getting the text property, localizing it and setting the text property again.
Using Swift, you can create a single file (e.g. LocalizationView.swift) in your project and put all your subclasses there. Then add the following code for the UILabel subclass:
[objc]
class LocalizedLabel : UILabel {
override func awakeFromNib() {
if let text = text {
self.text = NSLocalizedString(text, comment: "")
}
}
}
[/objc]
Now you can drag a label onto your Storyboard and fill in the text in your base language as you would normally. Then change the Class to LocalizedLabel and it will get the actual label from you Localizable.strings file.
Screen Shot 2014-10-31 at 22.45.46
Screen Shot 2014-10-31 at 22.46.56
No need to make any outlets or write any code to change it!
You can do something similar for UIButtons, even though they don’t have a single property for the text on a button.
[objc]
class LocalizedButton : UIButton {
override func awakeFromNib() {
for state in [UIControlState.Normal, UIControlState.Highlighted, UIControlState.Selected, UIControlState.Disabled] {
if let title = titleForState(state) {
setTitle(NSLocalizedString(title, comment: ""), forState: state)
}
}
}
}
[/objc]
This will even allow you to set different labels for the different states like Normal and Highlighted.

User Defined Runtime Attributes

Another way is to use the User Defined Runtime Attributes. This method requires slightly more work, but has two small advantages:

  1. You don’t need to use subclasses. This is nice when you already use another custom subclass for your labels, buttons and other view classes.
  2. Your keys in the Strings file and texts that show up in the Storyboard don’t need to be the same. This works well when you use localization keys such as myCoolTableViewController.header.subtitle. It doesn’t look very nice to see those everywhere in your Interface Builder labels and buttons.

So how does this work? Instead of creating a subclass, you instead add a computed property to an existing view class. For UILabels you use the following code:
[objc]
extension UILabel {
var localizedText: String {
set (key) {
text = NSLocalizedString(key, comment: "")
}
get {
return text!
}
}
}
[/objc]
Now you can add a User Defined Runtime Attribute with the key localizedText to your UILabel and have the Localization key as its value.
Screen Shot 2014-10-31 at 23.05.18
Screen Shot 2014-10-31 at 23.06.16
Also here if you want to make this work for buttons, it becomes slightly more complicated. You will have to add a property for each state that needs a label.
[objc]
extension UIButton {
var localizedTitleForNormal: String {
set (key) {
setTitle(NSLocalizedString(key, comment: ""), forState: .Normal)
}
get {
return titleForState(.Normal)!
}
}
var localizedTitleForHighlighted: String {
set (key) {
setTitle(NSLocalizedString(key, comment: ""), forState: .Highlighted)
}
get {
return titleForState(.Highlighted)!
}
}
}
[/objc]

Conclusion

Always try and pick the best solution for your problem. Use Storyboard Base Localization if that works well for you. If it doesn’t, use the approach with subclasses if you don’t need to use another subclass and if you don’t care about using your base location strings as localization keys. Else, use the last approach with User Defined Runtime Attributes.

guest
9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Randy Weinstein
Randy Weinstein
7 years ago

Great article. Is there a way to view rendered localized text property content for localized controls inside Interface Builder or do you have to build/run on a device/simulator with the language/region settings you want to review?
Thanks,
Randy

Tobias Wiedow
Tobias Wiedow
7 years ago

Great article!
One improvement when somebody wants to use the User Defined Runtime Attributes:
Instead of defining User Defined Runtime Attributes where you have to enter the same key and type and to switch inspector views all the time you can use a great new feature of Xcode 6: @IBInspectable. Just annotate the new variable in your UIView extension with @IBInspectable and edit the value right from the attributes inspector without entering key and type.
Cheers,
Tobi

Holub
Holub
7 years ago

There is an interesting service that provides sdk and online update for ios apps translation: http://localize.io
You can manage you localisation files without the need to think about which version of the app you’re updating. You also don’t need to recompile the app each time you add a new language.

randomdude
randomdude
6 years ago

Nice! this is very good, thank you very much.
Expanding on the same subject, how would you handle a situation where a label, and not a button, needs to have two states depending on a variable in a singelton class?
I see a few options, but none seem good;
1. program the required logic into the Extension UILabel
2. Somehow use another runtime property with some generic logic in extension uilabel
3. ????
what would you recommend?

blurkidi
blurkidi
6 years ago

In case somebody is interested, Polyglot is based on this concept. It defines class extensions to define IBInspectable attributes to easily localize common UI controls:
https://github.com/negusoft/Polyglot

Jose
Jose
6 years ago

What is `titleForState`, error for me

Asi
Asi
5 years ago

This is the best idea that iv’e found in the net.

Explore related posts