xcode 故事板/XIB 和本地化最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8846402/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 22:59:13  来源:igfitidea点击:

Storyboard/XIB and localization best practice

xcodelocalizationxib

提问by Morrowless

The officially recommended methodfor 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.

正式推荐的方法进行XIB /故事板的定位是创造的.xib和.storyboard文件内xx.lproj(其中xx是两个字母的语言ID)为您想支持的每个本地化。

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.

这会产生一个问题,因为您有多个文件,在许多情况下,这些文件共享相同的 UI,并且易于更改。如果您想为一个视图重新设计 UI,则必须多次进行(如果您在 xib 本身中输入可本地化的字符串值,则更糟)。这违背了 DRY 原则。

It seems way more efficient to call NSLocalizedString()where you need it, and just use one XIB or Storyboard for one base localization.

NSLocalizedString()在需要的地方调用似乎更有效,并且只需使用一个 XIB 或 Storyboard 进行基本本地化。

So, why should(n't) I create localized XIB/Storyboard files?

那么,为什么应该(不)创建本地化的 XIB/Storyboard 文件?

回答by Leszek Szary

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

您可以在 UILabel、UIButton 等上创建一个类别,如下所示:

#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

然后在您的 xib 文件上使用用户定义的运行时属性将 UILabel(或 UIButton 等)链接到保存在 Localizable.strings 文件中的键

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.

通过这种方式,您可以将所有字符串放在一个文件中,而不必为每种语言创建单独的 xib。

回答by Flax

For just changing text labels I did something like this

只是为了改变文本标签,我做了这样的事情

+(void) replaceTextWithLocalizedTextInSubviewsForView:(UIView*)view
{
    for (UIView* v in view.subviews)
    {
        if (v.subviews.count > 0)
        {
            [self replaceTextWithLocalizedTextInSubviewsForView:v];
        }

        if ([v isKindOfClass:[UILabel class]])
        {
            UILabel* l = (UILabel*)v;
            l.text = NSLocalizedString(l.text, nil);
            [l sizeToFit];
        }        

        if ([v isKindOfClass:[UIButton class]])
        {
            UIButton* b = (UIButton*)v;
            [b setTitle:NSLocalizedString(b.titleLabel.text, nil) forState:UIControlStateNormal];
        }        
    }    
}

call this function in your viewDidLoad:like this:

viewDidLoad:像这样调用这个函数:

[[self class] replaceTextWithLocalizedTextInSubviewsForView:self.view];

[[self class] replaceTextWithLocalizedTextInSubviewsForView:self.view];

It saved me a lot of work declaring and connecting IBOutlets when all you want is localized labels.

当您只需要本地化标签时,它为我节省了大量声明和连接 IBOutlets 的工作。

回答by styl0r

Flax's solution works well, one thing to note is that if you have UILabelsor UIButtonswhich are are contained in UICollectionViewCellsin 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 viewDidLayoutSubviewsinstead of viewDidLoad(which is called only once):

亚麻的解决方案效果很好,有一点要注意的是,如果你有UILabels或者UIButtons被包含在UICollectionViewCellsUICollectionViews(或类似),这些藏品在目前看来,由于用户操作频繁变化,例如或异步请求被填充,然后使用正确的本地化字符串更新标签,您可以在其中调用本地化函数viewDidLayoutSubviews而不是viewDidLoad(仅调用一次):

- (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!

本来可以将其添加为对上述解决方案的评论,但我没有“代表!

回答by Mike K

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/

您可以使用ibtool. 这是一个不错的介绍:http: //www.bdunagan.com/2009/03/15/ibtool-localization-made-easy/

回答by O. Boujaouane

As explained by Leszek S you can create a category.

正如 Leszek S 所解释的,您可以创建一个类别。

Here I'll give you an example in swift 3 with extension for UILabel and UIButton:

在这里,我将在 swift 3 中为您提供一个带有 UILabel 和 UIButton 扩展的示例:

  1. First of all create a "StringExtension.swift" file
  2. Add on it this code:

    extension String { func localized() -> String { let bundle = Bundle.main return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "") } }

  3. Then create another new file with the name you want (for example) "LocalizableObjectsExtensions.swift"

  4. Add on it an extension for UIButton and one for UILabel like this (of course you can create extension for what you want, UITextField...):

    extension UIButton { var localizedText: String { set (key) { setTitle(key.localized(), for: .normal) } get { return titleLabel!.text! } } }

    extension UILabel { var localizedText: String { set (key) { text = key.localized() } get { return text! } } }

  5. Now go in your Storyboard and for your button and/or you label that you want localize just add in the identity inspector of you object this:

  1. 首先创建一个“ StringExtension.swift”文件
  2. 添加此代码:

    extension String { func localized() -> String { let bundle = Bundle.main return NSLocalizedString(self, tableName: nil, bundle: bundle, value: "", comment: "") } }

  3. 然后使用您想要的名称创建另一个新文件(例如)“ LocalizableObjectsExtensions.swift

  4. 在它上面添加一个 UIButton 扩展和一个 UILabel 扩展,像这样(当然你可以为你想要的东西创建扩展,UITextField...):

    extension UIButton { var localizedText: String { set (key) { setTitle(key.localized(), for: .normal) } get { return titleLabel!.text! } } }

    extension UILabel { var localizedText: String { set (key) { text = key.localized() } get { return text! } } }

  5. 现在进入你的故事板,对于你的按钮和/或你想要本地化的标签,只需在你对象的身份检查器中添加:

enter image description here

在此处输入图片说明

FYI: here Key Path it's the name of the function you added in your extensions (UIlabel and UIButton) and Value is the name of the key that you want translate automatically which is in your Localizable.stringsfile. For example in your Localizable.strings (French)you have the key/value "ourOffers" = "NOS OFFRES";

仅供参考:这里的 Key Path 是您在扩展(UIlabel 和 UIButton)中添加的函数的名称,Value 是您想要自动翻译的键的名称,它位于Localizable.strings文件中。例如在你的Localizable.strings (French)你有键/值 "ourOffers" = "NOS OFFRES";

Now build & Run. Your Object will be translated in the language of your device if you have the key/value in your Localizable.string. Enjoy :)

现在构建并运行。如果您的 Localizable.string 中有键/值,您的对象将被翻译成您设备的语言。享受 :)

回答by Joe C

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.

我看到的每个地方都说你必须为每个本地化实例复制整个 xib 文件,即使你真的只想撕掉文本并为每个本地化实例复制不同语言的文本。

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.

如果有人知道只复制 xib 的用户可见文本(以不同的语言)而不复制每种语言的整个 xib 文件的方法,请告诉我们。

回答by Eric

Useful post, much easier than multiple XIBs. I extended the code to handle UISegmentedControl:

有用的帖子,比多个 XIB 容易得多。我扩展了代码来处理UISegmentedControl

if ([v isKindOfClass:[UISegmentedControl class]]) {
    UISegmentedControl* s = (UISegmentedControl*)v;
    for (int i = 0; i < s.numberOfSegments; i++) {
        [s setTitle:NSLocalizedString([s titleForSegmentAtIndex:i],nil) forSegmentAtIndex:i];
    }
}

回答by Marco

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.

我正在寻找 Flax 给出的准确答案,标记为正确,但我在 Swift 中需要它。所以我翻译成它。谢谢亚麻。

    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

这适用于 Swift 2.1

回答by WiseGuy

I came across this post and several others while trying to make xib localization easier for myself. I posted my method of including IBOutles for labels/buttons on this question, worked great for me, keeps all changes limited to the Localization.strings files.

我在尝试让自己更轻松地进行 xib 本地化时遇到了这篇文章和其他几篇文章。我在这个问题上发布了包含标签/按钮的 IBOutles 的方法,对我很有用,将所有更改限制在 Localization.strings 文件中。

https://stackoverflow.com/a/15485572/1449834

https://stackoverflow.com/a/15485572/1449834

回答by Seamore

I used a similar approach as Leszek Szary described for my views in Swift.

我使用了与 Leszek Szary 为我在 Swift 中的观点所描述的类似的方法。

Using a Boolean value as opposed to the localization keys, I added an "On/Off" drop down menu that determines whether the initial text values should be localized or not. This allows for the Storyboard to be kept clean without any extra upkeep.

使用布尔值而不是本地化键,我添加了一个“开/关”下拉菜单,用于确定是否应本地化初始文本值。这允许 Storyboard 保持清洁,而无需任何额外的维护。

Image1

图片1

When a value is selected, a single Runtime Attribute is added to the view and is used as a condition from within it's setter.

当一个值被选中时,一个单一的运行时属性被添加到视图中,并用作它的设置器中的条件。

Image2

图片2

Image3

图3

Here is the code from my .swift file which extends UIButton, UILabel, UITabBarItemand UITextField, including the text field placeholder and button control states:

下面是从延伸我.swift文件中的代码UIButtonUILabelUITabBarItem并且UITextField,包括文本字段占位符和按钮控制状态:

import UIKit

extension String {
    public var localize: String {
        return NSLocalizedString(self, comment: "")
    }
}

extension UIButton {
    @IBInspectable public var Localize: Bool {
        get { return false }
        set { if (newValue) {
            setTitle( title(for:.normal)?.localize,      for:.normal)
            setTitle( title(for:.highlighted)?.localize, for:.highlighted)
            setTitle( title(for:.selected)?.localize,    for:.selected)
            setTitle( title(for:.disabled)?.localize,    for:.disabled)
        }}
    }
}

extension UILabel {
    @IBInspectable public var Localize: Bool {
        get { return false }
        set { if (newValue) { text = text?.localize }}
    }
}

extension UITabBarItem {
    @IBInspectable public var Localize: Bool {
        get { return false }
        set { if (newValue) { title = title?.localize }}
    }
}

extension UITextField {
    @IBInspectable public var Localize: Bool {
        get { return false }
        set { if (newValue) {
            placeholder = placeholder?.localize
            text = text?.localize
        }}
    }
}

You could also use the new property to easily translate values that are set while your program is running like this:

您还可以使用新属性轻松转换程序运行时设置的值,如下所示:

let button = UIButton()

button.setTitle("Normal Text", for: .normal)
button.setTitle("Selected Text", for: .selected)

button.Localize = true