2010-07-16 9 views
35

¿Hay alguna manera de establecer un idioma predeterminado para usar cuando el idioma de la IU del dispositivo no es compatible con una aplicación?Localizar cadenas en iOS: ¿idioma predeterminado (de respaldo)?

Ejemplo: Mi aplicación se localiza en Inglés y alemán:

// en.lproj: 
"POWER_TO_THE_PEOPLE_BTN" = "Power"; 
"POWER_PLUG_BTN" = "Power"; 

// de.lproj: 
"POWER_TO_THE_PEOPLE_BTN" = "Macht"; 
"POWER_PLUG_BTN" = "Spannung"; 

Ahora, si me quedo la aplicación en un dispositivo con el lenguaje de interfaz de usuario configurado en Italian la aplicación va a utilizar las cadenas principales POWER_TO_THE_PEOPLE_BTN y POWER_PLUG_BTN.

Debe haber una forma de especificar un idioma predeterminado (de respaldo) para ser utilizado por la aplicación en tal caso.

A partir del ejemplo anterior, debe quedar claro que no funcionará el uso de la cadena en inglés como clave.

La única opción que veo ahora es usar NSLocalizedStringWithDefaultValue en lugar de NSLocalizedString.

Respuesta

13

Quizás esto debería ayudar? - iPhone: localization/internationalization default strings file

Debería volver al inglés de forma predeterminada. Acabo de cambiar mi teléfono a un idioma en el que mi aplicación no está traducida, y el texto estaba en inglés, como se esperaba.

Importante: como @hyperspasm comentó: Para ampliar/reformular esto, el idioma de reserva es el idioma que fue recientemente elegido por el usuario en la configuración del dispositivo, que también está representado en el paquete de la aplicación.

+17

El idioma alternativo es el primer idioma en '[NSLocale preferredLanguages]' que admite la aplicación. No es siempre inglés. Si cambia el idioma en la configuración, se moverá a la parte superior de la lista. – Felix

+4

Para expandir/reformular esto, el idioma alternativo es el idioma que el usuario eligió más recientemente en Configuración, que también está representado en el paquete de la aplicación. – hyperspasm

+1

Juan Pablo, gracias por la edición –

18

Para evitar todos aquellos largos sintaxis y más que tenían el nombre var más descriptivo para traductores, Derivé mi propio método de ayuda L() para la traducción y cayendo de nuevo a Inglés

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

Mi Localizable.strings se vería así

"SOME_ACTION_BUTTON" = "Do action"; 

Así que en mi código, me gustaría utilizar L(@"SOME_ACTION_BUTTON") para obtener la cadena correcta

Tho ugh alguna vez la clave es más larga que la propia traducción HELP_BUTTON_IN_NAV_BAR = 'Help' pero me ahorra mucho tiempo explicar lo que es para quien me está ayudando a hacer la traducción

+0

Lo he añadido, pero lo lamento ahora. Había configurado mi teléfono para elegir un idioma en este orden: sueco, francés, inglés. No tenía ninguna localización para el sueco, así que quise que retrocediera al inglés, pero en su lugar cayó en francés. Ver mi solución. – Siamaster

2

Una forma rápida de hacerlo sin reemplazar ningún método es "anular" el NSLocalizedString define y usa los métodos que Apple uses definen para reemplazarlo y agregar la lógica de repliegue adicional en el método "reemplazado".

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

Gracias por compartir. Me gusta su solución provista. Es una forma inteligente de usar iOS Crappy Fallback System donde devuelve la clave si no encuentra la cadena ....: P :) – Jona

+0

¿Puede publicar la versión Swift de este código? –

1

He creado la categoría NSBundle+FallbackLanguage para apoyar idioma de reserva, se puede encontrar esta información en la github folder. Solo necesita especificar la matriz de idiomas admitidos en la implementación.

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 
+1

¡Esto funciona bien! – user1007522

+1

Hice un riff sobre esto por lo que retrocede por cadena y no por idioma. Es posible que no entendiera el punto por completo, por supuesto, pero parece funcionar en la práctica. https://github.com/drosenstark/categories –

+0

Esto no se llama.Creé la categoría en NSBundle y pasé la matriz de idiomas admitida. –

14

Usted necesita asegurarse de que el valor de CFBundleDevelopmentRegion en su Info.plist es la región lenguaje que le gustaría vuelve a los. (Por ejemplo, "en")

+1

esta debería ser la respuesta correcta en este momento. – j2emanue

+0

Esta es (actualmente) la única solución correcta aparte de las muletas (podría ser adecuada en este momento) sugeridas por los demás. Para obtener más información, consulte este artículo: http://maniak-dobrii.com/understanding-ios-internationalization/ –

+2

Parece que ya no funciona, probó un dispositivo con idioma finlandés disponible solo en la configuración. La aplicación tiene traducciones finlandesas e inglesas, 'en' se define en Info.plist para la clave' CFBundleDevelopmentRegion', pero las claves que no existen en los archivos '.string' finlandeses no se sustituyen por versiones en inglés. –

1

Mis solución gracias a 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; 
} 

Uso:

#import "Global.h" 
printf(LString(@"MyKey").UTF8String); 

Esta solución doesn ' t tomar en consideración el orden de preferencia de los usuarios. En lugar de eso, siempre será una alternativa a lo que tienes en Base si el primer idioma de los usuarios no está localizado. Además, si una clave específica no está traducida para el idioma actual, pero existe en la ubicación básica, obtendrá la localización base.

Actualización:

Desde IOS 9, la región está incluido en las configuraciones regionales de idioma. Actualicé el código para manejar eso.

0

Basado en la solución de Bodus (por cierto) Creé esta categoría porque también necesita el "cable de respaldo". Así que tengo que verificar el idioma seleccionado actual del dispositivo y compararlo con mis idiomas que quiero admitir. Solo importe el encabezado y puede usar manzanas macro predeterminada

NSString *myString = NSLocalizedString(@"My Ub0rstring", nil); 

Funciona bien en iOS 9.x y 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 
1

@Bogus respuesta en Swift 4, funciona como un encanto en 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) 
} 
Cuestiones relacionadas