Подтвердить что ты не робот

Локализация строк в 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.

Должен быть способ указать стандартный (резервный) язык, который будет использоваться приложением в этом случае.

В приведенном выше примере должно быть ясно, что использование английской строки в качестве ключа не будет работать.

Единственное, что я вижу сейчас, это использовать NSLocalizedStringWithDefaultValue вместо NSLocalizedString.

4b9b3361

Ответ 1

Возможно, это должно помочь? - iPhone: файл строк по умолчанию/интернационализации по умолчанию

По умолчанию он должен вернуться на английский. Я только что переключил свой телефон на язык, на котором мое приложение не локализовано, и текст был написан на английском языке, как и ожидалось.

Важно:, как прокомментировал @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', но это сэкономит мне много времени, объясняя, что это касается того, кто помогает мне делать перевод

Ответ 3

Вам нужно убедиться, что значение CFBundleDevelopmentRegion в вашем Info.plist - это языковой регион, к которому вы хотели бы вернуться. (например, "en" )

Ответ 4

Быстрый способ сделать это без замены каких-либо методов - "переопределить" определение NSLocalizedString и использовать методы, которые Apple использует для этого определения, чтобы заменить его и добавить дополнительную резервную логику в методе "переопределить".

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

Ответ 5

Мое решение благодаря fooobar.com/questions/149576/...

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, если пользовательский язык не локализован. Кроме того, если конкретный ключ не локализован для текущего языка, но он существует в базовой локализации, вы получите базовую локализацию.

Update:

Так как iOS 9, область включена в локали языка. Я обновил код для его обработки.

Ответ 6

@Bogus ответ в Swift 4, работает как шарм на 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)
}

Ответ 7

Я создал категорию 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

Ответ 8

Основываясь на решении Bodus (спасибо 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