2010-07-16 102 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) 
}