6

Tengo esta cadena formateada en la que estoy trabajando un traductor.Localización avanzada con Omisión de argumentos en Xcode

INGLÉS

 
"Check out the %[email protected] %[email protected] in %[email protected]: %[email protected]" = "Check out the %[email protected] %[email protected] in %[email protected]: %[email protected]" 

TRADUCCIÓN ALEMÁN

 
"Check out the %[email protected] %[email protected] in %[email protected]: %[email protected]" = "Hör Dir mal %[email protected] in %[email protected] an: %[email protected]"; 

Estos son pasados ​​a una llamada [NSString stringWithFormat:]:

////////////////////////////////////// 
// Share Over Twitter 
NSString *frmt = NSLocalizedString(@"Check out the %[email protected] %[email protected] in %[email protected]: %[email protected]", @"The default tweet for sharing sounds. Use %[email protected] for where the sound type (Sound, mix, playlist) will be, %[email protected] for where the audio name will be, %[email protected] for the app name, and %[email protected] for where the sound link will be."); 
NSString *urlString = [NSString stringWithFormat:@"sounds/%@", SoundSoundID(audio)]; 
NSString *url = ([audio audioType] == UAAudioTypeSound ? UrlFor(urlString) : APP_SHORTLINK); 
NSString *msg = [NSString stringWithFormat: 
       frmt, 
       [[Audio titleForAudioType:[audio audioType]] lowercaseString], 
       [NSString stringWithFormat:@"\"%@\"", AudioName(audio)], 
       APP_NAME, 
       url]; 
returnString = msg; 

Con el resultado deseado y real de:

INGLÉS

 
desired: "Check out the sound "This Sound Name" in My App Name: link_to_sound" 
actual: "Check out the sound "This Sound Name" in My App Name: link_to_sound" 

GERMAN

 
desired: "Hör Dir mal "This Sound Name" in My App Name an: link_to_sound" 
actual: "Hör Dir mal sound in "This Sound Name" an: My App Name" 



EL PROBLEMA El problema es que estaba bajo el supuesto de que mediante el uso de la variable numerado en la -[NSString stringWithFormat:], Yo podría hacer eso ngs como este, donde la variable %[email protected] se omite por completo. Si observa, la traducción al alemán de la cadena de formato no utiliza el primer argumento (%[email protected]), pero sigue apareciendo ("sonido") en la cadena de salida.

¿Qué estoy haciendo mal?

Respuesta

7

Esto no es un error. Los argumentos numerados no son parte del estándar C, pero forman parte de IEEE Std 1003.1, que dice lo siguiente (énfasis mío):

El formato puede contener especificaciones de conversión de argumentos numerados (es decir, "% n $" y " * m $ "), o especificaciones de conversión de argumento sin numerar (es decir,% y *), pero no ambas. La única excepción a esto es que %% se puede mezclar con el formulario "% n $". Los resultados de mezclar especificaciones de argumento numeradas y no numeradas en una cadena de formato no están definidas. Cuando se usan especificaciones de argumento numeradas, especificar el argumento Nth requiere que todos los argumentos iniciales, desde el primero hasta el (n-1) th, se especifiquen en la cadena de formato.
+0

Parece que lo que estaba haciendo mal es hacer una suposición sobre la omisión de las variables numeradas. – coneybeare

+0

Es interesante que esto funciona bien en Android/Java; debe ser su implementación (¿inválida?) – Opus1217

0

Parece un error para mí. Creo que deberías presentar un error.

El motor de formateo de CFString es independiente de fprintf, por lo que podría haber algunas diferencias. Por ejemplo,

printf("a %3$s\n", "b", "c", "d"); // prints "a d" 
NSLog(@"a %3$s\n", "b", "c", "d"); // prints "a b" 

Debe suministrar todos los especificadores anteriores debido a que el ancho de un argumento no tiene por qué ser fijo, por ejemplo de

printf("%2$llx %1$llx\n", 1LL, 2LL); // prints "2 1" 
printf("%2$llx\n", 1LL, 2LL);  // prints "200000000" !! 
NSLog(@"%2$llx %1$llx\n", 1LL, 2LL); // prints "2 1" 
NSLog(@"%2$llx\n", 1LL, 2LL);  // prints "1" 

iPhone OS printf saltos de 4 bytes en 1 especificador faltante, y el formateador de CFString omite 0 bytes.


Las soluciones son:

  1. reorganizar su índices, por ejemplo

    "Check out the %[email protected] %[email protected] in %[email protected]: %[email protected]" 
    "Hör Dir mal %[email protected] in %[email protected] an: %[email protected]"; 
    

    o

  2. utilizar el formato

    [@"%1$10p%2$10p%3$10p%4$10p" stringByAppendingString:frmt] 
    

    para obligar a todos los argumentos que se utilizarán, y luego cortar a cabo los primeros 40 caracteres con -substringFromIndex:, o

  3. convertir todos ObjC objetos en cadenas de C (char*) y usa snprintf.

  4. Escriba su propio motor de formateo.
+0

Esperaba evitar estas soluciones y enviar los archivos a los traductores. booooo – coneybeare

+0

¿Puedes explicarme qué está haciendo el número 2? – coneybeare

+0

He intentado implementar una 5ta opción, aquí: http://stackoverflow.com/questions/2946649/nsstringwithformat-swizzled-to-allow-missing-format-numbered-args que es esencialmente como el número 4, pero no tanto de mi propio motor como una anulación – coneybeare