在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_BTN
和POWER_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