2010-07-16 87 views
35

當設備UI語言不被應用程序支持時,是否有方法可以設置默認語言?本地化iOS中的字符串:默認(後備)語言?

例子: 我的應用程序本地化爲英語和德語:

// en.lproj: 
"POWER_TO_THE_PEOPLE_BTN" = "Power"; 
"POWER_PLUG_BTN" = "Power"; 

// de.lproj: 
"POWER_TO_THE_PEOPLE_BTN" = "Macht"; 
"POWER_PLUG_BTN" = "Spannung"; 

現在,如果我在設備上運行的應用程序設置爲Italian應用程序將使用鑰匙串POWER_TO_THE_PEOPLE_BTNPOWER_PLUG_BTN UI語言。

必須有指定在這種情況下使用應用程序默認(後備)語言的一種方式。

從上面的例子,應該清楚,使用英文字符串作爲一個鍵將無法正常工作。

我現在看到的唯一選擇是使用NSLocalizedStringWithDefaultValue而不是NSLocalizedString

回答

13

或許這是應該幫助嗎? - iPhone: localization/internationalization default strings file

應該是默認退回到英語。我剛剛將手機切換爲我的應用未本地化的語言,並且正如預期的那樣,文本全部是英文的。

重要:作爲@hyperspasm評價:爲了擴展/改寫這一點,回退語言是其最近由裝置設置的用戶所選擇的語言中,也被表示在應用程序的包。

+17

回退語言是應用程序支持的[NSLocale preferredLanguages]中的第一種語言。它並不總是英文。如果您在設置中更改語言,它將移至列表頂部。 – Felix 2013-12-03 18:20:58

+4

爲了擴大/改變這一點,後備語言是用戶最近在設置中選擇的語言,也是在應用程序包中表示的語言。 – hyperspasm 2014-10-12 15:28:24

+1

Juan Pablo,感謝編輯 – 2016-05-16 16:55:35

18

爲了避免那些冗長的語法和翻譯更具有更具描述性的變量名稱,我得出我自己的輔助方法L()翻譯和回落至英語

NSString * L(NSString * translation_key) { 
    NSString * s = NSLocalizedString(translation_key, nil); 
    if (![[[NSLocale preferredLanguages] objectAtIndex:0] isEqualToString:@"en"] && [s isEqualToString:translation_key]) { 
    NSString * path = [[NSBundle mainBundle] pathForResource:@"en" ofType:@"lproj"]; 
    NSBundle * languageBundle = [NSBundle bundleWithPath:path]; 
    s = [languageBundle localizedStringForKey:translation_key value:@"" table:nil]; 
    } 
    return s; 
} 

Localizable.strings看起來像這樣

"SOME_ACTION_BUTTON" = "Do action"; 

所以,在我的代碼,我會用L(@"SOME_ACTION_BUTTON")得到正確的字符串

芹苴呃有時候關鍵是比翻譯本身長HELP_BUTTON_IN_NAV_BAR = 'Help',但它節省了我很多時間來解釋誰是誰在幫助我做翻譯

+0

我加上了它,但我現在很後悔。我已經設置了我的手機,以便按此順序選擇一種語言:瑞典語,法語,英語。我沒有瑞典語的本地化服務,所以我希望它能夠回到英語,但是它卻回落到了法語。看我的解決方案。 – Siamaster 2016-07-27 10:09:45

2

一個快速的方法來做到這一點,而無需替換任何方法是「覆蓋」 NSLocalizedString定義並使用Apple uses爲此定義的方法替換它,並在「重寫」方法中添加附加的回退邏輯。

#undef NSLocalizedString 
#define NSLocalizedString(key, comment) [self localizedStringForKey:(key) replaceValue:(comment)] 

+ (NSString *)localizedStringForKey:(NSString *)key replaceValue:(NSString *)comment { 
    NSString *fallbackLanguage = @"en"; 
    NSPath *fallbackBundlePath = [[NSBundle mainBundle] pathForResource:fallbackLanguage ofType:@"lproj"];  
    NSBundle *fallbackBundle = [NSBundle bundleWithPath:fallbackBundlePath]; 
    NSString *fallbackString = [fallbackBundle localizedStringForKey:key value:comment table:nil];  
    NSString *localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:fallbackString table:nil]; 

    return localizedString; 
} 
+0

感謝分享。我喜歡你提供的解決方案。這是一個聰明的方式使用iOS糟糕的回退系統,如果它沒有找到字符串,它會返回密鑰....:P :) – Jona 2014-09-08 18:14:01

+0

可以嗎?發佈此代碼的迅捷版 – 2017-11-02 10:12:38

1

我創建NSBundle+FallbackLanguage類支持回退語言,你可以檢查出來的github folder。您只需在實現中指定支持的語言的數組。

一個NSBundle + FallbackLanguage.h

#import <Foundation/Foundation.h> 

#undef NSLocalizedString 
#define NSLocalizedString(key, comment) [[NSBundle mainBundle] localizedStringForKey:(key) replaceValue:(comment)] 

@interface NSBundle (FallbackLanguage) 

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

@end 

一個NSBundle + FallbackLanguage。米

#import "NSBundle+FallbackLanguage.h" 

@implementation NSBundle (FallbackLanguage) 

- (NSString *)localizedStringForKey:(NSString *)key replaceValue:(NSString *)comment {   
    NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0]; 
    NSString *localizedString; 

    if ([@[@"en", @"de", @"fr"] containsObject:language]){ 
     localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:@"" table:nil]; 
    } 
    else{ 
     NSString *fallbackLanguage = @"en"; 
     NSString *falbackBundlePath = [[NSBundle mainBundle] pathForResource:fallbackLanguage ofType:@"lproj"]; 
     NSBundle *fallbackBundle = [NSBundle bundleWithPath:falbackBundlePath]; 
     NSString *fallbackString = [fallbackBundle localizedStringForKey:key value:comment table:nil]; 
     localizedString = fallbackString; 
    } 

    return localizedString; 
} 

@end 
+1

This works fine! – user1007522 2015-06-05 07:44:27

+1

我在這方面做了一個即興編排,所以它按照字符串而不是按語言回落。當然,我完全可能錯過了這一點,但它似乎在實踐中起作用。 https://github.com/drosenstark/categories – 2015-11-13 04:02:55

+0

這不會被調用。我已經在NSBundle上創建了類別並通過了支持的語言數組。 – 2016-01-27 07:14:18

14

你需要確保CFBundleDevelopmentRegion在你的Info.plist的價值是,你想退回到的語言區域。 (例如, 「EN」)

+1

這個時間點應該是正確的答案。 – j2emanue 2015-04-02 17:40:57

+0

這是(目前)除了柺杖之外唯一正確的解決方案(目前可能適合),其他人建議。有關詳細信息,請參閱以下文章:http://maniak-dobrii.com/understanding-ios-internationalization/ – 2015-09-26 20:43:58

+2

這似乎不再適用,僅在設置中測試了芬蘭語可用的設備。該應用程序具有芬蘭語和英語翻譯,在Info.plist中爲'CFBundleDevelopmentRegion'鍵定義了'en',但芬蘭語'.string'文件中不存在的鍵不會回退到英語版本。 – 2016-12-16 09:49:33

1

我的解決方案感謝https://stackoverflow.com/a/25928309/3664461

Global.h

NSString * LString(NSString * translation_key); 

Global.m

NSString *LString(NSString *translation_key) { 
    NSString *lString = nil; 
    NSString *languageCode = nil; 

    if ([UIDevice currentDevice].systemVersion.floatValue >= 9) { 
    NSString *localeIdentifier = [[NSLocale preferredLanguages] objectAtIndex:0]; 
    NSDictionary *localeDic = [NSLocale componentsFromLocaleIdentifier:localeIdentifier]; 
    languageCode = [localeDic objectForKey:@"kCFLocaleLanguageCodeKey"]; 
    } else { 
    languageCode = [[NSLocale preferredLanguages] objectAtIndex:0]; 
    } 

    NSString *path = [[NSBundle mainBundle] pathForResource:languageCode ofType:@"lproj"]; 
    if (path != nil) { 
    lString = NSLocalizedStringFromTableInBundle(translation_key, @"Localizable", 
              [NSBundle bundleWithPath:path], @""); 
    } 

    path = [[NSBundle mainBundle] pathForResource:@"Base" ofType:@"lproj"]; 
    lString = NSLocalizedStringFromTableInBundle(translation_key, @"Localizable", 
              [NSBundle bundleWithPath:path], @""); 
    } 
    return lString; 
} 

用法:

#import "Global.h" 
printf(LString(@"MyKey").UTF8String); 

該解決方案沒有按」考慮用戶偏好順序。相反,如果用戶的第一語言不是本地化的,它將始終回退到您在Base下的內容。 另外,如果某個特定的鍵未針對當前語言進行本地化,但它存在於基本本地化中,則您將獲得基本本地化。

更新:

從iOS 9開始,區域包含在語言環境中。我更新了代碼來處理這個問題。

0

基於Bodus解決方案(thx btw。)我創建了這個類別,因爲您也需要「fallbackString」。所以我必須檢查設備的當前所選語言,並將其與我想支持的語言進行比較。只需導入標題,您可以使用蘋果默認宏

NSString *myString = NSLocalizedString(@"My Ub0rstring", nil); 

適用於iOS 9.x和11.1。

的NSString + Helper.h

#import <Foundation/Foundation.h> 

#undef NSLocalizedString 
#define NSLocalizedString(key, comment) [NSString localizedStringForKey:(key) replaceValue:(comment)] 

@interface NSString (Helper) 

+ (NSString *)localizedStringForKey:(NSString *)key replaceValue:(NSString *)comment; 

@end 


的NSString + Helper.m

#import "NSString+Helper.h" 

@implementation NSString (Helper) 

+ (NSString *)localizedStringForKey:(NSString *)key replaceValue:(NSString *)comment 
{ 
    NSString *fallbackLanguage  = @"en"; 
    NSString *fallbackBundlePath = [[NSBundle mainBundle] pathForResource:fallbackLanguage ofType:@"lproj"]; 
    NSBundle *fallbackBundle  = [NSBundle bundleWithPath:fallbackBundlePath]; 
    NSString *fallbackString  = [fallbackBundle localizedStringForKey:key value:comment table:nil]; 
    NSString *localizedString  = [[NSBundle mainBundle] localizedStringForKey:key value:fallbackString table:nil]; 

    NSString *language    = [[NSLocale preferredLanguages] firstObject]; 
    NSDictionary *languageDic  = [NSLocale componentsFromLocaleIdentifier:language]; 
    NSString *languageCode   = [languageDic objectForKey:@"kCFLocaleLanguageCodeKey"]; 

    if ([languageCode isEqualToString:@"de"] || [languageCode isEqualToString:@"en"]) { 
     return localizedString; 
    } 
    else { 
     return fallbackString; 
    } 
} 

@end 
1
斯威夫特4

@Bogus答案,就像在iOS 11.1魅力:

public func NSLocalizedString(_ key: String, tableName: String? = nil, bundle: Bundle = Bundle.main, value: String = "", comment: String) -> String { 
    let fallbackLanguage = "en" 
    guard let fallbackBundlePath = Bundle.main.path(forResource: fallbackLanguage, ofType: "lproj") else { return key } 
    guard let fallbackBundle = Bundle(path: fallbackBundlePath) else { return key } 
    let fallbackString = fallbackBundle.localizedString(forKey: key, value: comment, table: nil) 
    return Bundle.main.localizedString(forKey: key, value: fallbackString, table: nil) 
}