首页 文章

在iOS中本地化字符串:默认(后备)语言?

提问于
浏览
36

有没有办法设置在应用程序不支持设备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 的设备上运行该应用程序,该应用程序将使用键字符串 POWER_TO_THE_PEOPLE_BTNPOWER_PLUG_BTN .

必须有一种方法来指定应用程序在这种情况下使用的默认(回退)语言 .

从上面的例子中可以清楚地看出,使用英文字符串作为键是行不通的 .

我现在看到的唯一选择是使用 NSLocalizedStringWithDefaultValue 而不是 NSLocalizedString .

8 回答

  • 13

    也许这应该有帮助吗? - iPhone: localization / internationalization default strings file

    默认情况下它应该回退到英语 . 我刚刚将手机切换到我的应用程序未本地化的语言,文本全部是英文的,正如预期的那样 .

    Important: as @hyperspasm评论说:要展开/重新定义,回退语言是用户最近在设备设置中选择的语言,也在应用程序的包中表示 .

  • 2

    为了避免所有那些冗长的语法,并为翻译者提供更具描述性的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") 来获取正确的字符串

    虽然某个时候关键比翻译本身更长 HELP_BUTTON_IN_NAV_BAR = 'Help' 但它节省了我很多时间来解释对谁帮助我做翻译的问题

  • 1

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

  • 16

    我的解决方案感谢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开始,区域包含在语言区域设置中 . 我更新了代码以处理它 .

  • 1

    在不替换任何方法的情况下执行此操作的快速方法是"overriding" NSLocalizedString定义并使用Apple uses用于此定义的方法来替换它并在"overridden"方法中添加额外的回退逻辑 .

    #undef NSLocalizedString
    #define NSLocalizedString(key, comment) [self localizedStringForKey:(key) replaceValue:(comment)]
    
    + (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];
    
        return localizedString;
    }
    
  • 2

    我已创建类别 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.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
    
  • 0

    在Swift 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)
    }
    
  • 18

    基于Bodus解决方案(thx btw . )我创建了这个类别,因为你也需要“fallbackString” . 所以我必须检查设备当前选择的语言,并将其与我想支持的语言进行比较 . 只需导入 Headers ,您就可以使用Apple默认宏

    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
    

相关问题