microsoft / LocalizedStringKit

Generate .strings files directly from your code
MIT License
291 stars 13 forks source link

plural and stringsdict support #4

Closed Artoria2e5 closed 1 year ago

Artoria2e5 commented 4 years ago

People familiar with other systems will almost immediately recognize this English-as-key approach as similar to gettext, a Unix translation facility from the late 1980s. Such a comparison will almost immediately raise a question: where is the plural facility?

If I am not mistaken, the current form of the python tool only generates strings files, which has no capacity to handle plural stuff (NSStringPluralRuleType). For truly international programs, this is often needed since plural rules vary widely among languages. Please consider putting plural support on your TODO list.

(Python has a builtin plistlib library that makes dealing with plists less of a headache. You will still need to come up with a way to select the NSStringFormatValueTypeKey used for the plural though.)

dalemyers commented 4 years ago

You are absolutely correct on this. It's an issue we are well aware of and something we do have plans for in the future. We have nothing concrete at this point though.

Artoria2e5 commented 4 years ago

What we want is a way to represent the multiple plural substitutions in one string. There actually is a string format system called ICU MessageFormat that does the whole sort of stuff, and we can simplify its plural syntax to something like:

Localized("{ eggs, d, one: An egg, other: %{} eggs } in { drawers, x, one: a drawer, other: %{} drawers }", "Comment here...");

In Python we can parse this {VAR, FMT, one: ONE, other: OTHER} sort of stuff. The example is meant to yield the following plist structure:

{
    "SomeKey" = {
        NSStringLocalizedFormatKey = "%1$#@eggs@ in %2$#@drawers@";
        eggs = {
            NSStringFormatSpecTypeKey = NSStringPluralRuleType;
            NSStringFormatValueTypeKey = d;
            one = "An egg";
            other = "%d eggs";
        };
        drawers = {
            NSStringFormatSpecTypeKey = NSStringPluralRuleType;
            NSStringFormatValueTypeKey = x;
            one = "a drawer";
            other = "%x drawers";
        };
    };
}

(No, I am not typing the new XML plist by hand. Old style for the win.)

The documentation for ngettext documents the interactions with string format that we should look out for. A lot of it is about how to use the POSIX %n$fmt format to specify ordering.

Artoria2e5 commented 4 years ago

If I get this right, I can do this in the dotstrings module as an extra transformation step. After extraction by XCode it can run the parser, get the parsed entries, turn some into dict entries, and emit the new dict.

levinli303 commented 1 year ago

@dalemyers I'm planning to add support for stringsdict in a way that is more consistent with how Apple does it. Using %#@ like "I ate %#@appleCount@ and %#@bananaCount@" with no change to the Objective-C API.

let str = Localized("I ate %#@appleCount@ and %#@bananaCount@", comment: "Comment for a string with cardinal numbers")
let localized = String.localizedStringWithFormat(str, 1, 2)

In localizedstringkit python code, we detect %#@...% pattern with regex from the scanner result, and generate stringsdict for these entries.