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

Fah*_*kar 2 objective-c internationalization ios

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

\n\n

有什么想法/建议如何完成这项工作吗?

\n\n

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

\n\n
\n\n

编辑1

\n\n

根据@Jano,我已经完成了下面的工作。

\n\n

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

\n\n

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

\n\n

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

\n\n

Plist 的内容是"myButton01" = "Back";&"myButton01" = "\xd8\xb8\xd9\x87\xd8\xb1";

\n\n

第一个视图控制器有两个按钮:英语和阿拉伯语。在这些按钮上调用操作。

\n\n
- (IBAction)pressedEnglish:(id)sender {\n    [Localization sharedInstance].fallbackLanguage = @"ar";\n    [Localization sharedInstance].preferredLanguage = @"en";\n    NSLog(@"pressed english");\n}\n\n- (IBAction)pressedArabic:(id)sender {\n    [Localization sharedInstance].fallbackLanguage = @"en";\n    [Localization sharedInstance].preferredLanguage = @"ar";\n    NSLog(@"pressed arabic");\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n

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

\n\n

发生这种情况有什么原因吗?

\n\n
\n\n

编辑2

\n\n

我遇到Edit 1问题了。我重命名InfoPlist.stringsLocalizable.strings并且它有效。但是但是,无论我按什么按钮,我仍然会收到阿拉伯文本。

\n\n

在查找原因时,我发现这是因为我们在下面的声明中Localization.m

\n\n
static Localization *shared = nil;\ndispatch_once(&pred, ^{\n    shared = [[Localization alloc] init];\n    shared.fallbackLanguage = @"en";\n    shared.preferredLanguage = @"ar";\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

我需要做哪些更改才能使其按照按下的按钮进行更改。

\n

Jan*_*ano 5

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

\n\n

首先将所有语言字符串写入目录结构中,如下所示:

\n\n
i18n/en.lproj/Localizable.strings\ni18n/ar.lproj/Localizable.strings\n
Run Code Online (Sandbox Code Playgroud)\n\n

为每种支持的附加语言创建一个附加目录,其中包含相应的两个字母代码。

\n\n

如果文件被识别为 i18n 资源,它们将如下所示:\n在此输入图像描述

\n\n

文件的 key=value 格式如下:

\n\n
"button.back" = "\xd8\xb8\xd9\x87\xd8\xb1";\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
[self.stateBtn setTitle:localize(@"button.back") forState:UIControlStateNormal];\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

本地化.h

\n\n
#ifndef localize\n#define localize(key) [[Localization sharedInstance] localizedStringForKey:key]\n#endif\n\n@interface Localization : NSObject\n\n@property (nonatomic, retain) NSBundle* fallbackBundle;\n@property (nonatomic, retain) NSBundle* preferredBundle;\n\n@property (nonatomic, copy) NSString* fallbackLanguage;\n@property (nonatomic, copy) NSString* preferredLanguage;\n\n-(NSString*) localizedStringForKey:(NSString*)key;\n\n-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type;\n\n+(Localization*)sharedInstance;\n\n@end\n
Run Code Online (Sandbox Code Playgroud)\n\n

本地化.m

\n\n
#import "Localization.h"\n\n@implementation Localization\n\n+(Localization *)sharedInstance\n{\n    static dispatch_once_t pred;\n    static Localization *shared = nil;\n    dispatch_once(&pred, ^{\n        shared = [[Localization alloc] init];\n        [shared setPreferred:@"en" fallback:@"ar"];\n    });\n    return shared;\n}\n\n-(void) setPreferred:(NSString*)preferred fallback:(NSString*)fallback \n{\n    self.fallbackLanguage = fallback;\n    self.preferredLanguage = preferred;\n    NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:self.fallbackLanguage];\n    self.fallbackBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];\n    bundlePath = [[NSBundle mainBundle] pathForResource:@"Localizable" ofType:@"strings" inDirectory:nil forLocalization:self.preferredLanguage];\n    self.preferredBundle = [[NSBundle alloc] initWithPath:[bundlePath stringByDeletingLastPathComponent]];\n}\n\n-(NSString*) pathForFilename:(NSString*)filename type:(NSString*)type\n{\n    NSString *path = [self.preferredBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.preferredLanguage];\n    if (!path) path = [self.fallbackBundle pathForResource:filename ofType:type inDirectory:nil forLocalization:self.fallbackLanguage];\n    if (!path) NSLog(@"Missing file: %@.%@", filename, type);\n    return path;\n}\n\n-(NSString*) localizedStringForKey:(NSString*)key\n{\n    NSString* result = nil;\n    if (_preferredBundle!=nil) {\n        result = [_preferredBundle localizedStringForKey:key value:nil table:nil];\n    }\n    if (result == nil) {\n        result = [_fallbackBundle localizedStringForKey:key value:nil table:nil];\n    }\n    if (result == nil) {\n        result = key;\n    }\n    return result;\n}\n\n@end\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将使用在阿拉伯语文件中查找密钥字符串,如果密钥丢失,它将在阿拉伯语文件中查找。如果您想要其他方式,请从按钮处理程序中执行以下操作:

\n\n
[[Localization sharedInstance] setPreferred:@"ar" fallback:@"en"];\n
Run Code Online (Sandbox Code Playgroud)\n\n

Github 上的示例项目

\n\n

如果本地化不起作用

\n\n

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

\n\n
$ plutil -lint Localizable.strings\nLocalizable.strings: OK\n
Run Code Online (Sandbox Code Playgroud)\n\n

此格式在国际化编程主题 >本地化字符串资源中进行了描述。您可以选择添加// single-line/* multi-line */评论。对于非拉丁语言,\xe2\x80\x99s 建议使用 UTF-16 编码 Localized.strings。您可以在 XCode 的检查器窗格中在编码之间进行转换。

\n\n

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

\n\n

复制文件

\n