The officially recommended method for XIB/Storyboard localization is to create .xib and .storyboard files inside xx.lproj (where xx is the two letter language ID) for each localization you want to support.
This creates a problem because you have multiple files that in many cases share the same UI, that are prone to change. If you wanted to re-design the UI for one view, you'll have to do it multiple times (worse if you entered the localizable string values in the xib itself). This goes against the DRY principle.
It seems way more efficient to call NSLocalizedString()
where you need it, and just use one XIB or Storyboard for one base localization.
So, why should(n't) I create localized XIB/Storyboard files?
you can automate a lot of it with
ibtool
. this is a decent introduction: http://www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/Every place I look says that you have to replicate the entire xib file for each localization instance, even though you really only wanted to rip the text out and replicate the text in a different language for each localization instance.
If anyone knows of a method to replicate only the user visible text of an xib (in a different language) without replicating the entire xib file for each language, please let us know.
You can make a category on UILabel, UIButton etc. like this:
and after that on your xib file use User Defined Runtime Attributes to link the UILabel (or UIButton etc.) to a key saved in your Localizable.strings file
This way you can have all your strings in one file and you do not have to create a separate xib for each language.
I was looking for the exactly answer given by Flax, marked as right, but I needed it in Swift. So I translated into it. Thanks Flax.
That works for Swift 2.1
Flax's solution works well, one thing to note is that if you have
UILabels
orUIButtons
which are are contained inUICollectionViewCells
inUICollectionViews
(or similar) and these collections change frequently in the current view, eg due to user action or being populated by an asynchronous request, then to keep the labels updated with the correct localization strings you can call the localization function inviewDidLayoutSubviews
instead ofviewDidLoad
(which is called only once):As can be seen from this code, I keep the localization method in a static helper class (as the other chap suggested):
Would have added this as a comment to the above solution, but I ain't got no 'rep!