10

我想%@ there are up to %i sun hours用适当的复数形式翻译字符串。

%@包含一天,%i太阳小时。

这是我的Localizable.stringsdict文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>%@ there are up to %i sun hours</key>
        <dict>
            <key>NSStringLocalizedFormatKey</key>
            <string>%#@hours@</string>
            <key>hours</key>
            <dict>
                <key>NSStringFormatSpecTypeKey</key>
                <string>NSStringPluralRuleType</string>
                <key>NSStringFormatValueTypeKey</key>
                <string>i</string>
                <key>zero</key>
                <string>%@ there are no sun hours</string>
                <key>one</key>
                <string>There is one sun hour %@ </string>
                <key>other</key>
                <string>%@ there are up to %i sun hours</string>
            </dict>
        </dict>
    </dict>
</plist>

这就是我所说的:

[NSString stringWithFormat:NSLocalizedString(@"%@ there are up to %i sun hours", nil), dayString, sunHours];

无论NSInteger我作为第二个参数传入什么,翻译都将始终使用“其他”模板。NSStringLocalizedFormatKey当我使用像%@ %#@hours@它正在工作的键时,我将其缩小到错误。

不过,我希望字符串参数成为本地化的一部分。有没有办法做到这一点?

4

3 回答 3

8

根据我所做的实验,您需要更改参数的顺序。似乎只有第一个可以用作替换规则的控制值。

这本词典

<key>%i hours %@</key>
<dict>
    <key>NSStringLocalizedFormatKey</key>
    <string>%#@hours@</string>
    <key>hours</key>
    <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>i</string>
        <key>zero</key>
        <string>%2$@ there are no sun hours</string>
        <key>one</key>
        <string>There is one sun hour %2$@ </string>
        <key>other</key>
        <string>%2$@ there are up to %1$d sun hours</string>
    </dict>
</dict>

结合

[NSString stringWithFormat:NSLocalizedString(@"%i hours %@", nil), sunHours, dayString];

为我产生预期的结果。请注意,我已将参数索引添加到替换字符串中,以便正确放置值。

看起来文档在描述此功能时过于雄心勃勃。例如,标题为“OS X 10.9 发行说明”的文档中给出的示例(尽管该链接适用于 iOS),暗示您应该能够打开第二个参数:

我们通过将整个参数列表应用于每个替换的格式说明符来允许递归格式。

@"%d in %d files are selected" = @"%2$#@d_in_d_files_are_selected@"

配置字典可以包含

"d_in_d_files_are_selected" = {

    "NSStringFormatSpecTypeKey" = "NSStringPluralRuleType"; // plural type
    "NSStringFormatValueTypeKey" = "d"; // int argument

    "zero" = "There is no file";
    "one" = "There is a file, and %1$#@it_is_selected@";
    "other" = "%1$d in %2$d files are selected"; 
};

但是根据那里的指南构建字典并没有给出规定的结果。(请注意,随后给出的示例 XML 与该字典不匹配。)

可能有一些我误读的东西,(或者可能有一个错误),但我无法确切地知道发生了什么。现在,我将把它保留为“更改参数顺序将解决您的问题”。

于 2015-09-01T05:59:27.987 回答
5

在解决了我需要根据第二个参数/变量进行复数的问题后,我还找到了解决您问题的方法,而无需更改参数的顺序或使用代理规则链接。感谢其他发帖者的回答和解决方案,这使我进行了实验并更好地理解.stringsdict.

我认为我的情况与你的情况很接近,但更容易一些,并且可以帮助你更好地理解字符串格式和规则是如何应用的,所以让我从我的例子开始。

我的情况

我需要构造一个类似1 of 1 item selectedor的字符串1 of 5 items selected

let countWithSelectionFormat = NSLocalizedString("%ld of %ld item(s) selected", comment: "Number of items with selection")
let countString = String.localizedStringWithFormat(countWithSelectionFormat, selectedCount, totalCount)

字符串格式%ld of %ld item(s) selected在这里只是一个占位符,一个别名。它在 中被忽略Localizable.strings,因为它已在 中首先找到Localizable.stringsdict。它仅用作 中规则的键Localizable.stringsdict,但实际上并不用于构造字符串:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>%ld of %ld item(s) selected</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%ld of %#@totalItems@ selected</string>
        <key>totalItems</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>ld</string>
            <key>one</key>
            <string>%ld item</string>
            <key>other</key>
            <string>%ld items</string>
        </dict>
    </dict>
</dict>
</plist>

实际的字符串格式在 中列出NSStringLocalizedFormatKey,它是%ld of %#@totalItems@ selected。这里第一个参数selectedCount是通过 using 传递的%ld(没有使它成为变量并列出它的规则)。第二个参数totalCount%#@totalItems@变量及其返回1 item或的规则解析,例如5 items,从而构造正确的字符串。

如果您需要更改某些语言的输出中参数的顺序,您可以使用%2$#@totalItems@, %1$ld selectedas NSStringLocalizedFormatKey

如果需要,您还可以引入第二个变量(和规则)%2$#@totalItems@, %1$#@selectedItems@:.


你的情况

我的 Swift 代码与您在 Objective-C 中的代码基本相同:

let stringFormat = NSLocalizedString("On %@ there are up to %ld sun hours", comment: "")
let string = String.localizedStringWithFormat(stringFormat, dayString, sunHours)

Localizable.stringsdict

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>On %@ there are up to %ld sun hours</key>
    <dict>
        <key>NSStringLocalizedFormatKey</key>
        <string>%#@day@%#@hours@</string>
        <key>day</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>d</string>
            <key>other</key>
            <string></string>
        </dict>
        <key>hours</key>
        <dict>
            <key>NSStringFormatSpecTypeKey</key>
            <string>NSStringPluralRuleType</string>
            <key>NSStringFormatValueTypeKey</key>
            <string>ld</string>
            <key>zero</key>
            <string>On %1$@ there are no sun hours</string>
            <key>one</key>
            <string>There is one sun hour on %1$@</string>
            <key>other</key>
            <string>On %1$@ there are up to %2$ld sun hours</string>
        </dict>
    </dict>
</dict>
</plist>

NSStringLocalizedFormatKey我使用 2 个变量:%#@day@%#@hours@.

day变量和规则用于“消耗”第一个参数,dayString我们在这里不需要任何输出(固定在句子的开头)。我在这里使用了格式值类型d(如%d整数),因为我们不需要并且我们无法解析字符串来选择适用的复数规则。我们只使用所需的other规则,它返回一个空字符串。出于同样的原因,字符串格式中的day和变量之间没有空格。hours

hours变量捕获第二个参数sunHours,它的规则负责构建实际的输出字符串(在这种情况下是整个句子)。因为我必须从第二个变量的规则中引用两个参数,所以我分别使用%1$@and%2$ld来引用dayStringsunHours参数。因此,您也可以以任何组合和顺序使用您的变量。

这给出了预期的结果:

String.localizedStringWithFormat(stringFormat, dayString, 0) // On Monday there are no sun hours
String.localizedStringWithFormat(stringFormat, dayString, 1) // There is one sun hour on Monday
String.localizedStringWithFormat(stringFormat, dayString, 5) // On Monday there are up to 5 sun hours

参考:

这两个示例都使用 Swift 5、Xcode 10.2.1、macOS 10.14.5 进行了测试,目标是 macOS 10.12。

于 2019-07-01T22:13:26.600 回答
4

从 macOS SDK 10.12/Xcode 8.3 开始,这仍然是一个问题,NSStringLocalizedFormatKey忽略参数编号并使用第一个参数来确定d_in_d_files_are_selected. 但。复数规则格式中的嵌套编号引用确实有效,因此例如"one" = "There is one file, and %2$#@it_is_selected@";将正确使用第二个参数来选择复数规则。这意味着,如果您使用单个other规则创建格式代理,则无需重新排列格式字符串即可实现您想要的行为:

<key>%@ there are up to %i sun hours</key>
<dict>
    <key>NSStringLocalizedFormatKey</key>
    <string>%#@proxy@</string>
    <key>proxy</key>
    <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>i</string>
        <key>other</key>
        <string>%2$#@hours@</string>
    </dict>
    <key>hours</key>
    <dict>
        <key>NSStringFormatSpecTypeKey</key>
        <string>NSStringPluralRuleType</string>
        <key>NSStringFormatValueTypeKey</key>
        <string>i</string>
        <key>zero</key>
        <string>%1$@ there are no sun hours</string>
        <key>one</key>
        <string>There is one sun hour %1$@ </string>
        <key>other</key>
        <string>%1$@ there are up to %2$i sun hours</string>
    </dict>
</dict>

请注意,要使其正常工作,您必须明确使用最终格式字符串 ( "%1$@ there are up to %2$i sun hours") 中的参数编号。

于 2017-05-11T19:39:17.887 回答