2010-05-15 8 views
7

J'ai une chaîne localisée qui doit prendre quelques variables. Cependant, dans la localisation, il est important que l'ordre des variables puisse changer d'une langue à l'autre.Comment créer une chaîne localisée formatée?

Donc, ce n'est pas une bonne idée:

NSString *text = NSLocalizedString(@"My birthday is at %@ %@ in %@", nil); 

Dans certaines langues, quelques mots viennent avant les autres, alors que dans d'autres, il est inverse. Je manque d'un bon exemple pour le moment.

Comment puis-je fournir des variables NAMED dans une chaîne formatée? Y a-t-il un moyen de le faire sans quelques remplacements de cordes self-made lourds? Même certaines variables numérotées comme {% @ 1}, {% @ 2}, etc. suffiraient ... existe-t-il une solution?

Répondre

12

C'est pourquoi NSLocalizedString prend deux paramètres. Utilisez le deuxième paramètre pour inclure un commentaire décrivant la signification du langage natif des variables. Ensuite, les traducteurs peuvent les réorganiser en utilisant la construction $ +. Voir le Notes for Localizers d'Apple.

Cependant, vous ne pouvez pas ignorer les paramètres dans une langue. Par exemple, si vous avez 3 paramètres en anglais et 4 en français et que vous n'avez pas besoin du troisième en anglais, vous ne pouvez pas formater comme %[email protected] %[email protected] and %[email protected]. Vous pouvez seulement ignorer le dernier.

3

J'ai résolu cela dans un projet il y a quelques semaines en construisant mon propre système de gabarit simple avec NSScanner. La méthode utilise un système de gabarit qui trouve des variables avec la syntaxe ${name}. Les variables sont fournies à la méthode via un NSDictionary.

- (NSString *)localizedStringFromTemplateString:(NSString *)string variables:(NSDictionary *)variables { 
    NSMutableString *result = [NSMutableString string]; 
    // Create scanner with the localized string 
    NSScanner *scanner = [[NSScanner alloc] initWithString:NSLocalizedString(string, nil)]; 
    [scanner setCharactersToBeSkipped:nil]; 

    NSString *output; 

    while (![scanner isAtEnd]) { 
     output = NULL; 
     // Find ${variable} templates 
     if ([scanner scanUpToString:@"${" intoString:&output]) { 
      [result appendString:output]; 

      // Skip syntax 
      [scanner scanString:@"${" intoString:NULL]; 

      output = NULL; 

      if ([scanner scanUpToString:@"}" intoString:&output]) { 
       id variable = nil; 
       // Check for the variable 
       if ((variable = [variables objectForKey:output])) { 
        if ([variable isKindOfClass:[NSString class]]) { 
         // NSString, append 
         [result appendString:variable]; 
        } else if ([variable respondsToSelector:@selector(description)]) { 
         // Not a NSString, but can handle description, append 
         [result appendString:[variable description]]; 
        } 
       } else { 
        // Not found, localize the template key and append 
        [result appendString:NSLocalizedString(output, nil)]; 
       } 
       // Skip syntax 
       [scanner scanString:@"}" intoString:NULL]; 
      } 
     } 
    } 

    [scanner release]; 

    return result; 
} 

Avec un fichier localisent qui ressemble à ceci:

"born message" = "I was born in ${birthYear} on a ${birthWeekDay}. ${byebye}"; 
"byebye"  = "Cheers!"; 

Nous pouvons obtenir les résultats suivants ...

NSDictionary *variables = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1986], @"birthYear", @"monday", @"birthWeekDay", nil]; 
NSString *finalString [self localizedStringFromTemplateString:@"born message" variables:variables]; 
NSLog(@"%@", finalString); // "I was born in 1986 on a monday. Cheers!" 

Comme vous pouvez le voir, j'ai ajouté quelques fonctionnalités supplémentaires aussi. Premièrement, toutes les variables qui ne sont pas trouvées (${byebye} dans mon exemple) seront localisées et ajoutées aux résultats. Je l'ai fait parce que je charge des fichiers HTML à partir de mon ensemble d'applications et les exécute via la méthode localize (en faisant cela, je ne localise pas la chaîne d'entrée lors de la création du scanner). En outre, j'ai ajouté la possibilité d'envoyer d'autres choses que des objets NSString, pour une flexibilité supplémentaire.

Ce code est peut-être pas les plus performants ou plus jolies écrit, mais il fait le travail sans impact sur les performances notables :)

10

exemple Formaté chaîne localisée:

NSString *today = [MyHandWatch today]; 
NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"Today is %@", @""), today]; 

genstrings va générer cette ligne dans votre fichier Localizable.strings:

"Today is %@" = "Today is %@"; 
+0

ne fonctionne tout simplement pas, il returnes la même chaîne – user2159978

+0

@ user2159978 Est-ce vous avez vraiment juste copier la dernière ligne? Bien sûr, il va retourner la même chaîne ... –

Questions connexes