Localization for UITextView in storyboard

2019-07-03 19:58发布

问题:

So I have an application with different buttons, labels and some Text Views in storyboard where I entered the text directly in the storyboard. I enabled base localization and added a couple of languages.

This generated storyboards for Base (English) and the other languages with a list of items objectIDs. I translated everything, and the labels and buttons (ALL OF THEM) work and show in the language I set the device to.

The text fields however keep showing the initial English text no matter which language I set... Are there any extra steps involved for Text View?

回答1:

So, I did some research, and it seems that in order for this to work correctly, the text for the UITextView needs to be set programmatically.

Source: Devforums.apple

Quote:

as I understand it, strings such as the text property of a text view/field have to be set in code using NSLocalizedString. The first 1/2 hour of WWDC 2013 video session #219 Making Your App World Ready covers this if you have the time to watch it

So, it seems that the workaround (if you don't want to set the text programmatically) is to convert the strings file into a storyboard before shipping the app. This does seem to work as intended and shows the UITextView properly localized.

EDIT: Found another workaround that allows to keep .strings file.

In - (void)viewDidLoad:

for(UIView* v in self.view.subviews)
{
    if([v isKindOfClass:[UITextView class]])
    {
        UITextView* txv = (UITextView*)v;
        NSString *loctxt = [txv.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        txv.text = NSLocalizedString(loctxt, @"");
    }
}

This produces a Percent Escapes encoded string from whatever is inside the storyboard, like this:

Hello%20World

In your Localizable.strings file, you use the above as the key, and this will produce the localized text in the app at runtime for the selected locale, like this:

"Hello%20World" = "Hallo Welt";

The Percent escaping takes care of all escape characters in the base string.



回答2:

If anyone is still interested, I have solved this problem a different way, this will allow you to still use the SAME .Strings file that is generated by Xcode for storyboards.

There are two parts to this solution:

In the .m file for your view add this code:

- (void)viewDidLoad
{
    [super viewDidLoad];
    for(UIView* view in self.view.subviews)
    {
        if([view isKindOfClass:[UITextView class]] && view.restorationIdentifier)
        {
            UITextView* textView = (UITextView*)view;
            NSString *textViewName = [NSString stringWithFormat:@"%@.text",textView.restorationIdentifier];
            textView.text = NSLocalizedStringFromTable(textViewName, @"Main", nil);
           //change this to be the same as the name of your storyboard ^^^
        }
    }
    // Do any additional setup after loading the view.
}

and in your storyboard in the identity inspector copy the "Object ID" to the "Restoration ID" field.

This will apply the new localized text to all of your UITextViews on screen load and will allow you to use the already generated strings files.



回答3:

As my comment on Dmitry's answer cannot be formatted nicely, I repeat this as an answer here. The Swift version of his solution looks like this:

override func viewDidLoad() {
    super.viewDidLoad()
    for view in self.view.subviews {
        if let tv = view as? UITextView, ident = view.restorationIdentifier {
            tv.text = NSLocalizedString("\(ident).text", tableName: "Main", comment: "")
        }
    }
    // Do any additional setup after loading the view.
}

(Note that in Swift, NSLocalizedString replaces several Objective-C macros, one of them being NSLocalizedStringFromTable)

P.S.: Unfortunately, in iOS 10 this seems not to work any more. Instead, the call gives back the id that was supplied as first parameter (e.g. "abc-xy-pqr.text"). Any ideas?



回答4:

I made my own Categories for the components.

For example, a button:

#import <UIKit/UIKit.h>
@interface LocalizedButton : UIButton
@end

#import "LocalizedButton.h"

@implementation LocalizedButton

- (id)initWithCoder:(NSCoder *)aDecoder {
    NSLog(@"Loading LocalizedButton: initWithCoder");
    if ((self = [super initWithCoder:aDecoder])){
        [self localizeButton];
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame{
    NSLog(@"Loading LocalizedButton: initWithFrame");
    self = [super initWithFrame:frame];
    if (self) {
       [self localizeButton];
    }
    return self;
}

-(void) localizeButton{
    self.titleLabel.adjustsFontSizeToFitWidth = YES;
    NSString* text = NSLocalizedString(self.titleLabel.text, nil);
    [self setTitle:text forState:UIControlStateNormal];
    [self setTitle:text forState:UIControlStateHighlighted];
    [self setTitle:text forState:UIControlStateDisabled];
    [self setTitle:text forState:UIControlStateSelected];
}

@end

You can se the complete code on: https://github.com/exmo/equizmo-ios/blob/master/Quiz/LocalizedButton.m



回答5:

The Swift solution of https://stackoverflow.com/users/1950945/stefan works for me on iOS 10.2 when I replace the "Main" with the correct id (e.g. "MainStoryboard") which references the localized file id.storyboard (e.g. "MainStoryboard.storyboard")