复数NSLocalizedString中的字符串参数

时间:2015-08-31 22:12:45

标签: ios objective-c localization pluralize

我想将字符串lloyd = { "name": "Lloyd", "homework": [90.0, 97.0, 75.0, 92.0], "quizzes": [88.0, 40.0, 94.0], "tests": [75.0, 90.0] } alice = { "name": "Alice", "homework": [100.0, 92.0, 98.0, 100.0], "quizzes": [82.0, 83.0, 91.0], "tests": [89.0, 97.0] } tyler = { "name": "Tyler", "homework": [0.0, 87.0, 75.0, 22.0], "quizzes": [0.0, 75.0, 78.0], "tests": [100.0, 100.0] } # Add your function below! def average(numbers): total = sum(numbers) total = float(total)/1 total = total/int(len(numbers)) return total def get_average(l_student): homework = average(l_student["homework"]) * 0.1 quizzes = average(l_student["quizzes"]) * 0.30 tests = average(l_student["tests"]) * 0.6 media = homework + quizzes + tests return media def get_letter_grade(score): if score >= 90: return "A" elif score >= 80: return "B" elif score >= 70: return "C" elif score >= 60: return "D" else: return "F" def get_class_average(students): results = [] for i in students: results = results.append(get_average(i)) return average(results) 翻译成适当的复数。

%@ 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错误。

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

3 个答案:

答案 0 :(得分:5)

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

这本词典

<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];

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

看起来这些文档在描述此功能时过于雄心勃勃。给出in the document titled "OS X 10.9 Release Notes"的示例(尽管链接适用于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与此词典不匹配。)

可能有一些我误读的错误,(或者可能存在错误),但我还没有能够确切地说明发生了什么。现在,我将离开这个&#34;更改参数顺序将解决您的问题&#34;。

答案 1 :(得分:2)

从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")中的参数编号。

答案 2 :(得分:0)

在解决了需要根据第二个参数/变量进行复数的问题之后,我也找到了解决您的问题的方法,而无需更改参数的顺序或使用代理规则链。感谢其他海报提供者的回答和解决方案,这些指导和解决方案使我得以进行实验并加深对.stringsdict的理解。

我认为我的案子很接近您,但要容易一些,可以帮助您更好地了解如何应用字符串格式和规则,所以让我从我的例子开始演示。

我的案子

我需要构造一个1 of 1 item selected1 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是使用%ld传递的(没有使其可变,也没有列出规则)。第二个参数totalCount%#@totalItems@变量及其规则解析,该变量返回1 item或例如5 items,从而构造正确的字符串。

如果您需要更改某些语言在输出中的参数顺序,则可以将%2$#@totalItems@, %1$ld selected用作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规则,该规则返回一个空字符串。出于相同的原因,字符串格式的dayhours变量之间没有空格。

hours变量捕获第二个参数sunHours,其规则负责构造实际的输出字符串(本例中为完整的句子)。由于必须从第二个变量的规则内部引用这两个参数,因此我分别使用%1$@%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

参考文献:

两个示例均使用针对macOS 10.12的Swift 5,Xcode 10.2.1,macOS 10.14.5进行了测试。