2010-05-15 17 views
7

Tengo una cadena localizada que necesita tomar algunas variables. Sin embargo, en la localización es importante que el orden de las variables pueda cambiar de un idioma a otro.¿Cómo crear una cadena localizada formateada?

Así que esto no es una buena idea:

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

En algunos lenguajes de algunas palabras se presentan ante los demás, mientras que en otros es inversa. Me falta un buen ejemplo en este momento.

¿Cómo proporcionaría las variables NAMED en una cadena formateada? ¿Hay alguna manera de hacerlo sin algunos sustitutos de cadena pesados ​​hechos a sí mismos? Incluso algunas variables numeradas como {% @ 1}, {% @ 2}, etc. serían suficientes ... ¿hay alguna solución?

Respuesta

12

Esta es la razón por NSLocalizedString toma dos parámetros. Use el segundo parámetro para incluir un comentario que describa el significado del idioma nativo de las variables. Luego, los traductores pueden reordenarlos usando la construcción de $ + número. Vea el Notes for Localizers de Apple.

Sin embargo, no puede omitir los parámetros en un idioma. Por ejemplo, si tiene 3 parámetros en inglés y 4 en francés y no necesita el tercero en inglés, no puede formatear como %[email protected] %[email protected] and %[email protected]. Solo puedes omitir el último.

3

Resolví esto en un proyecto hace unas semanas creando mi propio sistema de plantilla simple con NSScanner. El método usa un sistema de plantilla que encuentra variables con la sintaxis ${name}. Las variables se suministran al método a través de 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; 
} 

Con Localizar un archivo con este aspecto:

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

Podemos lograr los siguientes resultados ...

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!" 

Como se puede ver, he añadido algunas funcionalidades extra también. En primer lugar, cualquier variable que no se encuentre (${byebye} en mi ejemplo) se localizará y se adjuntará a los resultados. Hice esto porque cargué en archivos HTML de mi paquete de aplicaciones y los ejecuté a través del método de localización (al hacer eso, no localizo la cadena de entrada al crear el escáner). Además, agregué la capacidad de enviar otras cosas aparte de los objetos NSString, para obtener más flexibilidad.

Este código puede que no sea el mejor rendimiento o más bonito escrito, pero hace el trabajo sin ningún impacto en el rendimiento notables :)

10

con formato de cadena localizada ejemplo:

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

genstrings generarán esta línea en su archivo Localizable.strings:

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

simplemente no funciona, se returnes la misma cadena – user2159978

+0

@ user2159978 Did ¿Realmente solo copias la última línea? POR SUPUESTO, devolverá la misma cuerda ... –

Cuestiones relacionadas