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

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

问题描述

我想用英语和阿拉伯语创建一个iPhone应用程序。我检查了国际化文档的语言切换器,但要实现这一点,我必须手动去改变iPhone设置。我不想那样做。所以我计划在主屏幕上我将有两个按钮作为英语和阿拉伯语。如果用户点击阿拉伯语,我会有阿拉伯语文本,如果用户选择英语,应用程序将是英文。



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



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






编辑1



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



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



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



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



Plist的内容是myButton01=返回 ; & myButton01=ظهر;



First View Controller有两个按钮,分别为英文和阿拉伯文。对这些按钮调用操作。

   - (IBAction)pressedEnglish:(id)sender {
[Localization sharedInstance]。 fallbackLanguage = @ar;
[Localization sharedInstance] .preferredLanguage = @en;
NSLog(@按英语);
}

- (IBAction)pressedArabic:(id)sender {
[Localization sharedInstance] .fallbackLanguage = @en;
[Localization sharedInstance] .preferredLanguage = @ar;
NSLog(@压阿拉伯语);
}

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



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



我希望这应该有效,但是当我运行项目时,我看到按钮为 myButton01



出现这种情况的原因是什么?






编辑2



我有编辑1 问题。我将 InfoPlist.strings 重命名为 Localizable.strings 并且它有效。但是,但是,无论我按什么按钮,我仍然会收到阿拉伯语文本。



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

 静态本地化* shared = nil; 
dispatch_once(& pred,^ {
shared = [[Localization alloc] init];
shared.fallbackLanguage = @en;
shared.preferredLanguage = @ar ;

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



我需要做哪些更改才能按照按下的按钮更改它。

解决方案

您想要从应用UI中设置应用程序的语言,而忽略设备上的用户偏好。这很不寻常,但是这里你去......



首先在目录结构上写下所有语言字符串,如下所示:

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

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



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



文件将具有以下格式的key =值:

 button.back= ظهر; 

在您的代码中,用密钥替换任何可本地化的字符串。示例:

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

通常你会使用 NSLocalizedString(@key,@fallback )但是由于你想忽略iPhone的设置,我在上面写了一个 localize(@key)宏,它将具有以下实现: / p>

Localization.h

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

@interface Localization:NSObject

@property(nonatomic,retain)NSBundle * fallbackBundle ;
@property(非原子,保留)NSBundle * preferredBundle;

@property(非原子,复制)NSString * fallbackLanguage;
@property(非原子,复制)NSString * preferredLanguage;

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

- (NSString *)pathForFilename:(NSString *)文件名类型:(NSString *)类型;

+(本地化*)sharedInstance;

@end

Localization.m

  #importLocalization.h

@implementation本地化

+(本地化*)sharedInstance
{
static dispatch_once_t pred;
静态本地化* shared = nil;
dispatch_once(& pred,^ {
shared = [[Localization alloc] init];
[shared setPreferred:@enfallback:@ar];
});
返回共享;
}

- (void)setPreferred:(NSString *)首选后备:(NSString *)后备
{
self.fallbackLanguage = fallback;
self.preferredLanguage = preferred;
NSString * bundlePath = [[NSBundle mainBundle] pathForResource:@LocalizableofType:@stringsinDirectory:nil forLocalization:self.fallbackLanguage];
self.fallbackBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
bundlePath = [[NSBundle mainBundle] pathForResource:@LocalizableofType:@stringsinDirectory:nil forLocalization:self.preferredLanguage];
self.preferredBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];
}

- (NSString *)pathForFilename:(NSString *)文件名类型:(NSString *)类型
{
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(@缺少文件:%@。%@,文件名,类型);
返回路径;
}

- (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;
}
返回结果;
}

@end

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

  [[Localization sharedInstance] setPreferred:@ar 后备:@en]; 

Github上的示例项目



如果本地化不起作用



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

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

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



如果它仍然不起作用,请检查您是否在复制文件阶段复制Localizable.strings文件你的目标。请注意,当你在那里添加Localizable.strings文件时,有时它们会显示为红色,继续执行直到文件显示为黑色,然后删除红色文件(hacky我知道,责备Xcode)。




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.


Edit 1

As per @Jano, I have done below.

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

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

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

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

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");
}

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];

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

Any reason why this is happening?


Edit 2

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.

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.

解决方案

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.

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];

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:

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

Localization.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"];

Sample project at Github.

If localisation doesn't work

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

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.

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天全站免登陆