故事板中 UITextView 的本地化

Posted

技术标签:

【中文标题】故事板中 UITextView 的本地化【英文标题】:Localization for UITextView in storyboard 【发布时间】:2013-11-18 00:25:01 【问题描述】:

所以我有一个应用程序,在情节提要中有不同的按钮、标签和一些文本视图,我直接在情节提要中输入了文本。我启用了基本本地化并添加了几种语言。

这为基础(英语)和其他语言生成了故事板,其中包含项目 objectID 列表。 我翻译了所有内容,标签和按钮(全部)以我设置设备的语言工作和显示。

无论我设置哪种语言,文本字段都会一直显示初始英文文本... 文本视图是否涉及任何额外步骤?

【问题讨论】:

我刚刚遇到了完全相同的问题。使用本地化语言的字符串时,除了 UITextViews 在模拟器中一切正常。当我切换到 IB 故事板文件时,它确实按预期工作,顺便说一句。 Xcode5 和小牛队。 这里也一样。奇怪的问题!希望有人知道解决方法/修复方法...我也是 xxode 5/maverick... 刚刚在设备(iPhone5c 和 iPad)上测试过,同样的问题。所以它不仅仅是模拟器。 顺便说一句,您在哪里本地化了从右到左的语言?我还试图弄清楚如何自动更改给定语言环境的文本方向... 您应该将此作为新问题发布。 【参考方案1】:

所以,我做了一些研究,似乎为了使其正常工作,需要以编程方式设置 UITextView 的文本。

来源:Devforums.apple

引用:

据我了解,必须使用 NSLocalizedString 在代码中设置诸如文本视图/字段的文本属性之类的字符串。如果您有时间观看,WWDC 2013 视频会议 #219 让您的 App World Ready 的前 1/2 小时涵盖了这一点

因此,似乎解决方法(如果您不想以编程方式设置文本)是在发布应用程序之前将字符串文件转换为情节提要。这似乎确实按预期工作,并显示 UITextView 正确本地化。

编辑:找到另一个允许保留 .strings 文件的解决方法。

- (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, @"");
    

这会从情节提要中的任何内容生成 Percent Escapes 编码字符串,如下所示:

Hello%20World

在您的Localizable.strings 文件中,您使用上述作为键,这将在运行时为所选语言环境在应用程序中生成本地化文本,如下所示:

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

百分比转义处理基本字符串中的所有转义字符。

【讨论】:

编辑回复以添加允许保留 .strings 文件的解决方法【参考方案2】:

由于我对 Dmitry 答案的评论无法很好地格式化,我在此重复此作为答案。他的解决方案的 Swift 版本如下所示:

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.

(请注意,在 Swift 中,NSLocalizedString 替换了多个 Objective-C 宏,其中之一是 NSLocalizedStringFromTable

P.S.:不幸的是,在 ios 10 中,这似乎不再适用。相反,该调用返回作为第一个参数提供的 id(例如“abc-xy-pqr.text”)。有什么想法吗?

【讨论】:

restorationIdentifier 为我返回了nil。我只是将 Text View 的 Restoration Identifier 设置为它的 Object ID 并且它起作用了。【参考方案3】:

如果有人仍然感兴趣,我已经用不同的方式解决了这个问题,这将允许您仍然使用由 Xcode 为情节提要生成的 SAME .Strings 文件。

这个解决方案有两个部分:

在您的视图的 .m 文件中添加以下代码:

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

然后在身份检查器的情节提要中将“对象 ID”复制到“恢复 ID”字段。

这会将新的本地化文本应用于屏幕加载时的所有 UITextView,并允许您使用已生成的字符串文件。

【讨论】:

这是一个非常方便的解决方案。在 Swift 中,for 循环看起来像 for view in self.view.subviews if let tv = view as? UITextView, ident = view.restorationIdentifier let textViewName = String(format: "%@.text", ident); tv.text = NSLocalizedString(textViewName, tableName: "Main", comment: "") (请注意,在 Swift 中,NSLocalizedString 替换了几个 Obj-C 宏,其中一个是 NSLocalizedStringFromTable 不幸的是,在 iOS 10 中,这似乎不再起作用。相反,该调用返回作为第一个参数提供的 id(例如“abc-xy-pqr.text”)。有什么想法吗?【参考方案4】:

我为组件创建了自己的类别。

例如一个按钮:

#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

您可以在以下位置查看完整代码:https://github.com/exmo/equizmo-ios/blob/master/Quiz/LocalizedButton.m

【讨论】:

因此,您可以在 xcode 上使用字符串中的文本。只需选择类 LocalizedButton。 按钮?谁说过按钮?【参考方案5】:

https://***.com/users/1950945/stefan 的 Swift 解决方案适用于我在 iOS 10.2 上,当我将“Main”替换为引用本地化文件 id.storyboard(例如“MainStoryboard.storyboard”)的正确 ID(例如“MainStoryboard”)时

【讨论】:

以上是关于故事板中 UITextView 的本地化的主要内容,如果未能解决你的问题,请参考以下文章

未反映在本地化故事板中的基本故事板更改

iOS Swift 2.0 UITextView 根据文本冻结应用程序

UITextView 中不需要的滚动空间

UIScrollView 中的 Storyboard UITextview 和按钮

UITextView insertText 调用 shouldChangeTextInRange: replacementText:

在启用滚动的堆栈视图中扩展 UITextView