Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String parameter in pluralized NSLocalizedString

I want to translate the string %@ there are up to %i sun hours with proper pluralization.

%@ contains a day, %i the sun hours.

This is my Localizable.stringsdict file:

<?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>

and this is how I call it:

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

No matter what NSInteger I pass in as the second argument the translation will always be with the "other" template. I narrowed it down to the NSStringLocalizedFormatKey being wrong, when I use a key like %@ %#@hours@ it's working.

I want the string parameter to be part of the localization, though. Is there a way to do this?

like image 603
Cornelius Avatar asked Aug 31 '15 22:08

Cornelius


1 Answers

Based on the experimenting I've done, you need to change the order of your arguments. It seems that only the first can be used as the controlling value for the substitution rule.

This dictionary

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

combined with

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

produces the expected results for me. Note that I've added the argument indexes to the replacement strings so that the values are placed properly.

It looks like the docs are over-ambitious in their description of this functionality. The example given in the document titled "OS X 10.9 Release Notes" (though the link is for iOS) for example, implies that you should be able to switch on the second argument:

We're allowing the recursive formatting by applying the entire argument list to each substituted format specifier.

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

The configuration dictionary can contain

"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"; 
};

But constructing a dictionary according to the guidelines there doesn't give the stated result. (And note the sample XML given immediately afterwards doesn't match this dictionary.)

There may be something I'm misreading, (or there may be a bug), but I haven't been able to suss out exactly what's going on. For now, I'm going to leave this as "changing the argument order will fix your problem".

like image 185
jscs Avatar answered Sep 17 '22 23:09

jscs