无需重启的程序化语言本地化 [英] Programmatic language localisation without restart

查看:17
本文介绍了无需重启的程序化语言本地化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用英语和阿拉伯语创建一个 iPhone 应用程序.我检查了语言切换器的国际化文档,但是要使其生效,我必须手动更改 iPhone 设置.我不想那样做.所以我的计划是在主屏幕上我将有两个按钮,分别是英语和阿拉伯语.如果用户点击阿拉伯语,我将有阿拉伯语文本,如果用户选择英语,应用程序将是英语.

I want to create an iPhone application with English and Arabic language. I checked the Internationalization document for language switcher, however to take that into effect I have to manually go and change the iPhone setting. I don't want to do that. So what I am planning is on home screen I will have two button as English and Arabic. If user click Arabic, I will have arabic text and if user select English, app will be in english.

任何想法/建议如何完成这项工作?

Any idea/ suggestion how to get this done?

注意:我不想手动去更改语言.

Note: I don't want to manually go and change the language.

根据@Jano,我在下面做了.

As per @Jano, I have done below.

创建了新项目.在本地化中添加了阿拉伯语.现在我有两个故事板和两个 InfoPlist.strings 文件.

Created new project. Added Arabic in Localization. Now I have two storyboard and two InfoPlist.strings file.

添加了 Localization.h 和 .m 文件,如答案所示.

Added Localization.h and .m file as shown in answer.

目录结构是MyProject-ar.lproj &MyProject-en.lproj

Directory structure is MyProject-ar.lproj & MyProject-en.lproj

Plist 的内容是 "myButton01" = "Back"; &"myButton01" = "ظهر";

Content of Plist are "myButton01" = "Back"; & "myButton01" = "ظهر";

First View Controller 有两个按钮,分别是英文和阿拉伯文.在这些按钮上调用操作.

First View Controller have two button as English and Arabic. Called action on those button.

- (IBAction)pressedEnglish:(id)sender {
    [Localization sharedInstance].fallbackLanguage = @"ar";
    [Localization sharedInstance].preferredLanguage = @"en";
    NSLog(@"pressed english");
}

- (IBAction)pressedArabic:(id)sender {
    [Localization sharedInstance].fallbackLanguage = @"en";
    [Localization sharedInstance].preferredLanguage = @"ar";
    NSLog(@"pressed arabic");
}

在第二个视图控制器中,我添加了一个按钮并命名为 myButton.现在在 viewDidLoad 中,我有

In second view controller, I added one button and gave name as myButton. Now in viewDidLoad, I have

[self.myButton setTitle:localize(@"myButton01") forState:UIControlStateNormal];

我希望这应该可以工作,但是当我运行项目时,我看到按钮为 myButton01

I hope this should be working, however when I run the project, I see button as myButton01

发生这种情况的任何原因?

Any reason why this is happening?

我遇到了 Edit 1 问题.我将 InfoPlist.strings 重命名为 Localizable.strings 并且它起作用了.但是,但是,无论我按什么按钮,我仍然会收到阿拉伯语文本.

I got Edit 1 problem. I renamed InfoPlist.strings to Localizable.strings and it worked. But but but, I am still getting Arabic text irrespective of whatever button I press.

在查找原因时,我发现是因为我们在 Localization.m

When finding reason, I found that it was because of below statement that we have in Localization.m

static Localization *shared = nil;
dispatch_once(&pred, ^{
    shared = [[Localization alloc] init];
    shared.fallbackLanguage = @"en";
    shared.preferredLanguage = @"ar";

问题出在最后两行.由于我们已将阿拉伯语设置为首选语言,因此我总是看到阿拉伯语文本.

The problem is at last two lines. As we have set Arabic as preferredLanguage, I am always seeing the arabic text.

我需要做哪些更改,以便可以根据按下的按钮进行更改.

What changes will I need to do so that I can have it as changeable as per button pressed.

推荐答案

您想从应用程序 UI 设置应用程序的语言,而忽略设备上的用户首选项.这很不寻常,但你去吧......

You want to set the language of the app from the app UI ignoring the user preference on the device. This is unusual, but here you go...

首先将所有语言字符串写在这样的目录结构中:

First write all your language strings on a directory structure like this:

i18n/en.lproj/Localizable.strings
i18n/ar.lproj/Localizable.strings

为每种支持的其他语言创建一个带有相应两个字母代码的附加目录.

Create an additional directory with the corresponding two letter code for each additional language supported.

如果文件被识别为 i18n 资源,它们将如下所示:

If the files are recognized as i18n resources, they will be presented like this:

文件将有一个键=值,格式如下:

Files will have a key=value with the following format:

"button.back" = "ظهر";

在您的代码中,将任何可本地化的字符串替换为键.示例:

In your code, replace any localizable string with the key. Example:

[self.stateBtn setTitle:localize(@"button.back") forState:UIControlStateNormal];

通常你会使用 NSLocalizedString(@"key",@"fallback") 但因为你想忽略 iPhone 设置,我写了一个 localize(@"key") 上面的宏将具有以下实现:

Usually you would use NSLocalizedString(@"key",@"fallback") but since you want to ignore iPhone settings, I wrote a localize(@"key") macro above that will have the following implementation:

本地化.h

#ifndef localize
#define localize(key) [[Localization sharedInstance] localizedStringForKey:key]
#endif

@interface Localization : NSObject

@property (nonatomic, retain) NSBundle* fallbackBundle;
@property (nonatomic, retain) NSBundle* preferredBundle;

@property (nonatomic, copy) NSString* fallbackLanguage;
@property (nonatomic, copy) NSString* preferredLanguage;

-(NSString*) localizedStringForKey:(NSString*)key;

-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type;

+(Localization*)sharedInstance;

@end

本地化.m

#import "Localization.h"

@implementation Localization

+(Localization *)sharedInstance
{
    static dispatch_once_t pred;
    static Localization *shared = nil;
    dispatch_once(&pred, ^{
        shared = [[Localization alloc] init];
        [shared setPreferred:@"en" fallback:@"ar"];
    });
    return shared;
}

-(void) setPreferred:(NSString*)preferred fallback:(NSString*)fallback 
{
    self.fallbackLanguage = fallback;
    self.preferredLanguage = preferred;
    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:self.fallbackLanguage];
    self.fallbackBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
    bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:self.preferredLanguage];
    self.preferredBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
}

-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type
{
    NSString *path = [self.preferredBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.preferredLanguage];
    if (!path) path = [self.fallbackBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.fallbackLanguage];
    if (!path) NSLog(@"Missing file: %@.%@", filename, type);
    return path;
}

-(NSString*) localizedStringForKey:(NSString*)key
{
    NSString* result = nil;
    if (_preferredBundle!=nil) {
        result = [_preferredBundle localizedStringForKey:key value:nil table:nil];
    }
    if (result == nil) {
        result = [_fallbackBundle localizedStringForKey:key value:nil table:nil];
    }
    if (result == nil) {
        result = key;
    }
    return result;
}

@end

这将使用在阿拉伯语文件中查找键字符串,如果缺少键,它将在阿拉伯语文件中查找.如果您希望以另一种方式使用,请从您的按钮处理程序中执行以下操作:

This will use lookup the key strings in the arabic file, and if the key is missing, it will look in the arabic file. If you want it the other way, do the following from your button handlers:

[[Localization sharedInstance] setPreferred:@"ar" fallback:@"en"];

Github 上的示例项目.

如果本地化不起作用,请使用 plutil 命令行工具来验证文件的格式.它应该输出:Localizable.strings: OK.示例:

If localisation doesn't work, use the plutil command line tool to verify the format of the file. It should output: Localizable.strings: OK. Example:

$ plutil -lint Localizable.strings
Localizable.strings: OK

国际化编程主题中描述了这种格式> 本地化字符串资源.您可以选择添加 //单行/* 多行 */ 注释.对于非拉丁语言,建议将 Localized.strings 编码为 UTF-16.您可以在 XCode 的检查器窗格中进行编码之间的转换.

This format is described in Internationalization Programming Topics > Localizing String Resources. You can optionally add // single-line or /* multi-line */ comments. For non latin languages it’s recommended to encode Localized.strings in UTF-16. You can convert between encodings in the inspector pane of XCode.

如果仍然无法正常工作,请检查您是否在目标的复制文件阶段复制了 Localizable.strings 文件.请注意,当您在其中添加 Localizable.strings 文件时,有时它们会显示为红色,一直这样做直到文件显示为黑色,然后删除红色的文件(我知道,怪不得 Xcode).

If it still doesn't work, check that you are copying the Localizable.strings file in the Copy files phase of your target. Note that when you add Localizable.strings files there, sometimes they appear in red, keep doing it until a file appears in black, then delete the red ones (hacky I know, blame Xcode).

这篇关于无需重启的程序化语言本地化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆