Усовершенствованная локализация с пропуском аргументов в Xcode - PullRequest
6 голосов
/ 31 мая 2010

У меня есть эта форматированная строка, над которой у меня работает переводчик.

АНГЛИЙСКИЙ

"Check out the %1$@ %2$@ in %3$@: %4$@" = "Check out the %1$@ %2$@ in %3$@: %4$@"

НЕМЕЦКИЙ ПЕРЕВОД

"Check out the %1$@ %2$@ in %3$@: %4$@" = "Hör Dir mal %2$@ in %3$@ an: %4$@";

Они передаются на [NSString stringWithFormat:] вызов:

//////////////////////////////////////
// Share Over Twitter
NSString *frmt = NSLocalizedString(@"Check out the %1$@ %2$@ in %3$@: %4$@", @"The default tweet for sharing sounds. Use %1$@ for where the sound type (Sound, mix, playlist) will be, %2$@ for where the audio name will be, %3$@ for the app name, and %3$@ 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;

С желаемым и фактическим результатом:

АНГЛИЙСКИЙ

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"

НЕМЕЦКИЙ

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"



ПРОБЛЕМА Проблема в том, что я исходил из того, что, используя пронумерованную переменную в -[NSString stringWithFormat:], я мог бы делать такие вещи, когда переменная %1$@ полностью опущена. Если вы заметили, немецкий перевод строки формата вообще не использует первый аргумент (%1$@), но он («звук») все еще появляется в выходной строке.

Что я делаю не так?

Ответы [ 2 ]

7 голосов
/ 01 июня 2010

Это не ошибка. Нумерованные аргументы не являются частью стандарта C, но являются частью стандарта IEEE Std 1003.1, в котором говорится следующее (выделено мое):

Формат может содержать либо спецификации преобразования нумерованных аргументов (то есть "% n $" и "* m $"), либо спецификации преобразования ненумерованных аргументов (то есть% и *), но не оба. Единственным исключением является то, что %% можно смешивать с формой «% n $». Результаты смешивания нумерованных и ненумерованных спецификаций аргументов в строке формата не определены. Когда используются спецификации нумерованных аргументов, для указания N-го аргумента необходимо, чтобы все ведущие аргументы, от первого до (N-1) -го, были указаны в строке формата.
0 голосов
/ 31 мая 2010

Похоже, ошибка для меня. Я думаю, вы должны сообщить об ошибке .

Механизм форматирования CFString не зависит от fprintf, поэтому могут быть некоторые различия. Например,

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

Вам необходимо указать все предыдущие спецификаторы, поскольку ширину аргумента не нужно фиксировать, например,

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 пропускает 4 байта на 1 отсутствующий спецификатор, а форматировщик CFString пропускает 0 байтов.


Решения:

  1. Изменить ваши индексы, например,

    "Check out the %4$@ %1$@ in %2$@: %3$@"
    "Hör Dir mal %1$@ in %2$@ an: %3$@";
    

    или

  2. использовать формат

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

    для принудительного использования всех аргументов, а затем выделите первые 40 символов с помощью -substringFromIndex: или

  3. Преобразуйте все объекты ObjC в строки C (char*) и используйте snprintf.

  4. Напишите свой собственный движок форматирования.
...