2010-07-16 13 views
35

C'è un modo per impostare una lingua predefinita da utilizzare quando la lingua dell'interfaccia utente del dispositivo non è supportata da un'app?Localizzazione delle stringhe in iOS: lingua predefinita (fallback)?

Esempio: La mia app è localizzata in inglese e tedesco:

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

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

Ora, se eseguire l'applicazione su un dispositivo con lingua dell'interfaccia utente impostata Italian l'applicazione utilizzerà le stringhe chiave POWER_TO_THE_PEOPLE_BTN e POWER_PLUG_BTN.

Ci deve essere un modo per specificare un linguaggio di default (fallback) da utilizzare in tal caso nell'applicazione.

Dall'esempio precedente dovrebbe essere chiaro che l'utilizzo della stringa inglese come chiave non funzionerà.

L'unica opzione che vedo ora è utilizzare NSLocalizedStringWithDefaultValue anziché NSLocalizedString.

risposta

13

Forse questo dovrebbe aiutare? - iPhone: localization/internationalization default strings file

È necessario eseguire il fallback in inglese per impostazione predefinita. Ho appena trasferito il mio telefono in una lingua in cui la mia app non è localizzata e il testo era tutto in inglese, come previsto.

Importante: come @hyperspasm commentato: Ad ampliare/riformulare questo, la lingua di fallback è il linguaggio che è stato recentemente scelto dall'utente nelle impostazioni del dispositivo, che è rappresentata anche in bundle dell'app.

+17

La lingua di fallback è la prima lingua in '[NSLocale preferredLanguages]' supportata dall'app. Non è sempre inglese Se cambi la lingua nelle impostazioni, si sposterà in cima alla lista. – Felix

+4

Per espandere/riformulare questo, la lingua di fallback è la lingua scelta più recentemente dall'utente in Impostazioni, anch'essa rappresentata nel pacchetto dell'app. – hyperspasm

+1

Juan Pablo, grazie per la modifica –

18

Per evitare tutte quelle lungo la sintassi e più avere più descrittivo nome var per i traduttori, ho derivato il mio metodo di supporto L() per la traduzione e ricadendo a Inglese

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

mio Localizable.strings sarebbe simile a questa

"SOME_ACTION_BUTTON" = "Do action"; 

Quindi, nel mio codice, userei L(@"SOME_ACTION_BUTTON") per ottenere la stringa corretta

Tho A un certo punto la chiave è più lunga della traduzione stessa HELP_BUTTON_IN_NAV_BAR = 'Help' ma mi risparmia molto tempo spiegando che cosa è a chi mi sta aiutando a fare la traduzione

+0

Ho aggiunto, ma mi dispiace ora. Avevo impostato il mio telefono per scegliere una lingua in questo ordine: svedese, francese, inglese. Non avevo localizzazione per lo svedese, quindi volevo che ricadesse in inglese, ma invece è tornato sul francese. Vedi la mia soluzione. – Siamaster

2

Un modo rapido per farlo senza sostituire alcun metodo è "prevalente" la NSLocalizedString definisce e utilizza i metodi che lo Apple uses definisce per sostituirlo e aggiunge la logica di fallback aggiuntiva nel metodo "sovrascritto".

#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

Grazie per aver condiviso. Mi piace la tua soluzione fornita. È un modo intelligente di utilizzare il sistema fallback iOS in cui restituisce la chiave se non trova la stringa ....: P :) – Jona

+0

Can u Post versione Swift di questo codice –

1

ho creato categoria NSBundle+FallbackLanguage per supportare la lingua fallback, è possibile verificare sul github folder. Devi solo specificare l'array di lingue supportate nell'implementazione.

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

Funziona perfettamente! – user1007522

+1

Ho fatto un riff su questo in modo che ricada indietro per stringa e non per lingua. È possibile che mi sia sfuggito del tutto, naturalmente, ma sembra funzionare in pratica. https://github.com/drosenstark/categories –

+0

Questo non viene chiamato.Ho creato la categoria su NSBundle e passato l'array del linguaggio supportato. –

14

È necessario fare in modo che il valore della CFBundleDevelopmentRegion in Info.plist è la regione di lingua che si desidera fallback a. (Ad esempio "en")

+1

questa dovrebbe essere la risposta corretta in questo momento. – j2emanue

+0

Questa è (attualmente) l'unica soluzione corretta a parte le stampelle (potrebbe essere adatta al momento) suggerita dagli altri. Per maggiori dettagli consulta questo articolo: http://maniak-dobrii.com/understanding-ios-internationalization/ –

+2

Questo non sembra funzionare più, testato un dispositivo con lingua finlandese disponibile solo nelle impostazioni. L'app contiene traduzioni in finlandese e in inglese, 'en' è definito nel file Info.plist per la chiave' CFBundleDevelopmentRegion', tuttavia le chiavi che non esistono nei file '.string 'finlandesi non rientrano nella versione inglese. –

1

mia soluzione grazie alla 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; 
} 

Usage:

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

Questa soluzione doesn' t prendere in considerazione l'ordine di preferenza degli utenti. Invece, ricadrà sempre su ciò che si ha sotto Base se la prima lingua degli utenti non è localizzata. Anche se una chiave specifica non è localizzata per la lingua corrente, ma esiste nella localizzazione di base, si otterrà la localizzazione di base.

Aggiornamento:

Dal iOS 9, regione è incluso nei locali della lingua. Ho aggiornato il codice per gestirlo.

0

Basato sulla soluzione di Bodus (thx btw.) Ho creato questa categoria perché è necessario anche il "fallbackString". Quindi devo controllare la lingua selezionata corrente del dispositivo e confrontarla con le mie lingue che voglio supportare. Basta importare l'intestazione e puoi utilizzare la macro predefinita di apple

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

Funziona bene su iOS 9.xe 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 risposta a Swift 4, funziona come un fascino su 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) 
} 
Problemi correlati