ios - applelanguages



程序化語言本地化,無需重啟 (1)

我想用英語和阿拉伯語創建一個iPhone應用程序。 我檢查了語言切換器的國際化文件,但是要實現這一點,我必須手動去改變iPhone的設置。 我不想這樣做。 所以我正在計劃在主屏幕上,我將有兩個按鈕,如英語和阿拉伯語。 如果用戶點擊阿拉伯文,我會有阿拉伯文字,如果用戶選擇英文,應用程序將是英文的。

任何想法/建議如何做到這一點?

注意:我不想手動去改變語言。

編輯1

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

創建新項目。 在本地化中添加阿拉伯語。 現在我有兩個故事板和兩個InfoPlist.strings文件。

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

目錄結構是MyProject-ar.lprojMyProject-en.lproj

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

First View Controller有兩個按鈕,分別是英文和阿拉伯文。 在這些按鈕上調用操作。

- (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 ,我有

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

我希望這應該工作,但是當我運行該項目,我看到按鈕作為myButton01

為什麼會發生這種情況?

編輯2

我得到了Edit 1問題。 我將InfoPlist.stringsInfoPlist.stringsLocalizable.strings ,它工作。 但是,但是,我仍然得到阿拉伯文本,不管我按什麼按鈕。

在找到原因的時候,我發現這是因為我們在Localization.m有下面的語句

static Localization *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

為每個支持的附加語言創建一個附加的目錄和相應的雙字母代碼。

如果這些文件被識別為國際資源,他們將會這樣呈現:

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

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

在您的代碼中,用鍵替換任何可本地化的字符串。 例:

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

通常你會使用NSLocalizedString(@"key",@"fallback")但是因為你想忽略iPhone的設置,所以我寫了一個localize(@"key")宏,

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

這將使用查找阿拉伯文件中的關鍵字符串,如果關鍵字丟失,它將查找阿拉伯文件。 如果您想要另一種方式,請從您的按鈕處理程序執行以下操作:

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

Github的示例項目

如果本地化不起作用

如果本地化不起作用,請使用plutil命令行工具來驗證文件的格式。 它應該輸出: Localizable.strings: OK 。 例:

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

國際化編程主題> 本地化字符串資源中介紹了此格式。 您可以選擇添加// single-line/* multi-line */註釋。 對於非拉丁語言,建議使用UTF-16對Localized.strings進行編​​碼。 您可以在XCode的檢查器窗格中的編碼之間進行轉換。

如果仍然無效,請檢查是否在目標的“複製文件”階段中復制Localizable.strings文件。 請注意,當你在那裡添加Localizable.strings文件時,它們有時會以紅色顯示,直到文件出現黑色,然後刪除紅色(我知道,我知道,怪罪Xcode)。





internationalization