7

我有这个格式化的字符串,我正在让翻译工作。

英语

"查看 %3$@ 中的 %1$@ %2$@:%4$@" = "查看 %3$@ 中的 %1$@ %2$@:%4$@"

德语翻译

"查看 %3$@ 中的 %1$@ %2$@: %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;

具有以下期望和实际结果:

英语

所需:“在我的应用名称中查看声音“此声音名称:link_to_sound”
实际:“查看我的应用名称中的声音“此声音名称:link_to_sound”

德语

所需:“我的应用名称”中的“Hör Dir mal“此声音名称”an:link_to_sound”
实际:““此声音名称”中的 Hör Dir mal 声音 an:我的应用程序名称”



问题 问题是我假设通过在 中使用编号变量-[NSString stringWithFormat:],我可以做这样的事情,其中%1$@​​变量被完全省略。如果您注意到,格式字符串的德语翻译根本不使用第一个参数 ( %1$@),但它(“声音”)仍然出现在输出字符串中。

我究竟做错了什么?

4

2 回答 2

7

这不是错误。编号参数不是 C 标准的一部分,而是 IEEE Std 1003.1 的一部分,它说以下(强调我的):

该格式可以包含编号的参数转换规范(即“%n$”和“*m$”)或未编号的参数转换规范(即 % 和 * ),但不能同时包含两者。唯一的例外是 %% 可以与 "%n$" 形式混合使用。在格式字符串中混合编号和未编号的参数规范的结果是未定义的。当使用编号参数规范时,指定第 N 个参数需要在格式字符串中指定从第一个到第 (N-1) 个的所有前导参数。
于 2010-06-01T01:51:36.460 回答
0

对我来说似乎是一个错误。我认为你应该提交一个错误.

CFString 的格式化引擎独立于fprintf's,因此可能存在一些差异。例如,

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 OSprintf在 1 个缺失的说明符上跳过 4 个字节,而 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]
    

    强制使用所有参数,然后用-substringFromIndex:, 或删除前 40 个字符

  3. 将所有 ObjC 对象转换为 C 字符串 ( char*) 并使用snprintf.

  4. 编写自己的格式化引擎。
于 2010-05-31T16:27:47.053 回答