程序化语言本地化,无需重启

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

任何想法/build议如何做到这一点?

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


编辑1

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

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

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

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

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

First View Controller有两个button,分别是英文和阿拉伯文。 在这些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"); } 

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

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

我希望这应该工作,但是当我运行该项目,我看到button作为myButton01

为什么会发生这种情况?


编辑2

我得到了Edit 1问题。 我将InfoPlist.stringsInfoPlist.stringsLocalizable.strings ,它工作。 但是,但是,我仍然得到阿拉伯文本,不pipe我按什么button。

在find理由的时候,我发现这是因为我们在Localization.m有以下声明

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

问题是最后两行。 正如我们已经设置阿拉伯语为首选语言,我总是看到阿拉伯文本。

我需要做什么修改,以便按下button可以改变。

您希望从应用UI中设置应用的语言,而忽略设备上的用户首选项。 这是不寻常的,但在这里你走…

首先把所有的语言string写在一个目录结构上,如下所示:

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

为每个支持的附加语言创build一个附加的目录和相应的双字母代码。

如果这些文件被识别为国际资源,他们将会这样呈现: 在这里输入图像说明

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

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

在您的代码中,用键replace任何可本地化的string。 例:

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

通常你会使用NSLocalizedString(@"key",@"fallback")但是因为你想忽略iPhone的设置,所以我写了一个localize(@"key")macroslocalize(@"key") ,这个macros有以下的实现:

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 

这将使用查找阿拉伯文件中的关键string,如果关键字丢失,它将查找阿拉伯文件。 如果您想要另一种方式,请从您的button处理程序执行以下操作:

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

Github的示例项目 。

如果本地化不起作用

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

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

国际化编程主题> 本地化string资源中介绍了此格式。 您可以select添加// single-line/* multi-line */注释。 对于非拉丁语言,build议使用UTF-16对Localized.strings进行编码。 您可以在XCode的检查器窗格中的编码之间进行转换。

如果仍然无效,请检查是否在目标的“复制文件”阶段中复制Localizable.strings文件。 请注意,当你在那里添加Localizable.strings文件,有时它们会以红色显示,直到一个文件出现黑色,然后删除红色(我知道,我知道,怪罪Xcode)。

复制文件