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