在iOS中本地化string:默认(回退)语言?

有没有一种方法来设置应用程序不支持设备UI语言时使用的默认语言?

示例:我的应用程序被本地化为英语和德语:

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

现在,如果我在UI设置为Italian的设备上运行应用程序,应用程序将使用键stringPOWER_TO_THE_PEOPLE_BTNPOWER_PLUG_BTN

在这种情况下,必须有一种方法来指定应用程序使用的默认(后备)语言。

从上面的例子中,应该清楚的是,使用英文string作为关键是行不通的。

我现在看到的唯一select是使用NSLocalizedStringWithDefaultValue而不是NSLocalizedString

也许这应该有帮助? – iPhone:本地化/国际化默认string文件

它应该回落到英语默认情况下。 我刚刚把我的手机换成了我的应用程序没有本地化的语言,正如预期的那样,文本全部是英文的。

重要提示:正如@hyperspasm所评论的那样:为了扩展/重写这个,后备语言是用户在设备设置中最近select的语言,也是在应用程序包中表示的语言。

为了避免所有那些冗长的语法和更多的具有更多描述性的var名称的翻译,我导出了我自己的辅助方法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")来获取正确的string

虽然有时键比翻译本身长HELP_BUTTON_IN_NAV_BAR = 'Help'但是这节省了我大量的时间来解释帮助我翻译的人是什么

您需要确保Info.plist中的CFBundleDevelopmentRegion的值是您想要回退的语言区域。 (例如“en”)

一个快速的方法来做到这一点,而不是取代任何方法是“重写”NSLocalizedString定义和使用苹果用这个定义的方法取代它,并在“重写”方法中添加额外的回退逻辑。

 #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; } 

我创build了类别NSBundle+FallbackLanguage以支持备用语言,您可以在github文件夹中查看它。 您只需在实现中指定支持的语言的数组。

一个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.m

 #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 

我的解决scheme感谢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); 

该解决scheme不考虑用户的偏好顺序。 相反,如果用户的第一语言不是本地化的,它总是会回退到你在Base下的东西。 另外如果一个特定的键没有被当地语言本地化,但是它存在于基本的本地化中,你将会得到基本的本地化。

更新:

从iOS 9开始,区域被包含在语言区域中。 我更新了代码来处理这个问题。

基于Bodus解决scheme(thx btw。)我创build了这个类别,因为你也需要“fallbackString”。 所以我必须检查设备的当前所选语言,并将其与我想支持的语言进行比较。 只需导入标题,您可以使用苹果默认macros

 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