Storyboard/XIB and localization best practice

2020-02-03 05:23发布

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?

11条回答
你好瞎i
2楼-- · 2020-02-03 06:16

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/

查看更多
▲ chillily
3楼-- · 2020-02-03 06:17

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.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2020-02-03 06:24

You can make a category on UILabel, UIButton etc. like this:

#import "UILabel+Localization.h"

@implementation UILabel (Localization)

- (void)setLocalizeKey:(NSString*)key
{
    self.text = NSLocalizedString(key, nil);
}

@end

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

user defined runtime attributes

This way you can have all your strings in one file and you do not have to create a separate xib for each language.

查看更多
戒情不戒烟
5楼-- · 2020-02-03 06:25

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.

    func replaceTextWithLocalizedTextInSubviewsForView(view: UIView) {

    for v in view.subviews {

        if v.subviews.count > 0 {
            self.replaceTextWithLocalizedTextInSubviewsForView(v)
        }

        if (v.isKindOfClass(UILabel)) {
            let myLabel: UILabel = v as! UILabel
            myLabel.text = NSLocalizedString(myLabel.text!, comment: "Text to translate.")
            myLabel.sizeToFit()
        }

        if (v.isKindOfClass(UIButton)) {
            let myButton: UIButton = v as! UIButton
            myButton.setTitle(NSLocalizedString((myButton.titleLabel?.text)!, comment: "Text to translate.") as String, forState: .Normal)
            myButton.sizeToFit()
        }
    }
}

That works for Swift 2.1

查看更多
放我归山
6楼-- · 2020-02-03 06:27

Flax's solution works well, one thing to note is that if you have UILabels or UIButtons which are are contained in UICollectionViewCells in UICollectionViews (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 in viewDidLayoutSubviews instead of viewDidLoad (which is called only once):

- (void)viewDidLayoutSubviews
{
    [LocalizationHelper replaceTextWithLocalizedTextInSubviewsForView:self.view];
}

As can be seen from this code, I keep the localization method in a static helper class (as the other chap suggested):

@implementation LocalizationHelper

+(void) replaceTextWithLocalizedTextInSubviewsForView:(UIView*)view
{
    for (UIView* v in view.subviews)
       ... <code from above> ...
}
@end

Would have added this as a comment to the above solution, but I ain't got no 'rep!

查看更多
登录 后发表回答