本地化iOS中的字符串:默认(后备)语言?
当设备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_BTN
和POWER_PLUG_BTN
UI语言。
必须有指定在这种情况下使用应用程序默认(后备)语言的一种方式。
从上面的例子,应该清楚,使用英文字符串作为一个键将无法正常工作。
我现在看到的唯一选择是使用NSLocalizedStringWithDefaultValue
而不是NSLocalizedString
。
或许这是应该帮助吗? - iPhone: localization/internationalization default strings file
应该是默认退回到英语。我刚刚将手机切换为我的应用未本地化的语言,并且正如预期的那样,文本全部是英文的。
重要:作为@hyperspasm评价:为了扩展/改写这一点,回退语言是其最近由装置设置的用户所选择的语言中,也被表示在应用程序的包。
为了避免那些冗长的语法和翻译更具有更具描述性的变量名称,我得出我自己的辅助方法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'
,但它节省了我很多时间来解释谁是谁在帮助我做翻译
我加上了它,但我现在很后悔。我已经设置了我的手机,以便按此顺序选择一种语言:瑞典语,法语,英语。我没有瑞典语的本地化服务,所以我希望它能够回到英语,但是它却回落到了法语。看我的解决方案。 – Siamaster 2016-07-27 10:09:45
一个快速的方法来做到这一点,而无需替换任何方法是“覆盖” 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;
}
感谢分享。我喜欢你提供的解决方案。这是一个聪明的方式使用iOS糟糕的回退系统,如果它没有找到字符串,它会返回密钥....:P :) – Jona 2014-09-08 18:14:01
可以吗?发布此代码的迅捷版 – 2017-11-02 10:12:38
我创建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
This works fine! – user1007522 2015-06-05 07:44:27
我在这方面做了一个即兴编排,所以它按照字符串而不是按语言回落。当然,我完全可能错过了这一点,但它似乎在实践中起作用。 https://github.com/drosenstark/categories – 2015-11-13 04:02:55
这不会被调用。我已经在NSBundle上创建了类别并通过了支持的语言数组。 – 2016-01-27 07:14:18
你需要确保CFBundleDevelopmentRegion在你的Info.plist的价值是,你想退回到的语言区域。 (例如, “EN”)
这个时间点应该是正确的答案。 – j2emanue 2015-04-02 17:40:57
这是(目前)除了拐杖之外唯一正确的解决方案(目前可能适合),其他人建议。有关详细信息,请参阅以下文章:http://maniak-dobrii.com/understanding-ios-internationalization/ – 2015-09-26 20:43:58
这似乎不再适用,仅在设置中测试了芬兰语可用的设备。该应用程序具有芬兰语和英语翻译,在Info.plist中为'CFBundleDevelopmentRegion'键定义了'en',但芬兰语'.string'文件中不存在的键不会回退到英语版本。 – 2016-12-16 09:49:33
我的解决方案感谢https://*.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开始,区域包含在语言环境中。我更新了代码来处理这个问题。
基于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
@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)
}
回退语言是应用程序支持的[NSLocale preferredLanguages]中的第一种语言。它并不总是英文。如果您在设置中更改语言,它将移至列表顶部。 – Felix 2013-12-03 18:20:58
为了扩大/改变这一点,后备语言是用户最近在设置中选择的语言,也是在应用程序包中表示的语言。 – hyperspasm 2014-10-12 15:28:24
Juan Pablo,感谢编辑 – 2016-05-16 16:55:35