代码之家  ›  专栏  ›  技术社区  ›  coneybeare

Xcode中省略参数的高级本地化

  •  6
  • coneybeare  · 技术社区  · 15 年前

    我有一个格式化的字符串,我有一个翻译工作。

    英语

    "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 回复  |  直到 15 年前
        1
  •  7
  •   dreamlax    15 年前

    这不是错误。编号的参数不是C标准的一部分,而是IEEE Std 1003.1的一部分,它表示以下内容(Emphasis Mine):

    格式可以包含带编号的参数转换规范(即,“%n$”和“*m$”)或无编号的参数转换规范(即,%和*),但不能同时包含两者。唯一的例外是,%可以与“%n$”窗体混合。格式字符串中混合有编号和无编号参数规范的结果未定义。 当使用带编号的参数规范时,指定第n个参数需要在格式字符串中指定从第一个到第(n-1)个的所有前导参数。
        2
  •  0
  •   kennytm    15 年前

    在我看来像个虫子。我想你应该提交一个bug .

    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操作系统 printf 在缺少说明符的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:

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

    4. 编写自己的格式化引擎。
    推荐文章