User:Marcoos/Plurals Support

From MozillaWiki
Jump to: navigation, search

Note: this is just my proposed solution for the problem.

Problem description

In English you only have one singular and one plural form of a noun:

1 file
2 files
5 files

In other languages often more than one form is needed, for example in Polish:

1 plik
2 pliki
5 plików

Currently the languages with multiple plural forms work around it like this:

2 pliki(-ów)
5 pliki(-ów)

or like this:

Liczba plików: 5
(Number of files: 5)

Neither of these workarounds is nice.

Affected languages

ar, cs, ga-IE, hr, lt, lv, pl, ru, si, sk, ua

(feel free to add your language)

Gettext approach

GNU Gettext has multiple plurals support.

Gettext .po format allows many plural forms like this:

msgid "1 file"
msgid_plural "%count files"
msgstr[0] "1 plik"
msgstr[1] "%count pliki"
msgstr[2] "%count plików"

where the string ID is chosen using a special, language specific formula, which, for example, for Polish is:

"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;"

and for English:

"Plural-Forms: nplurals=2; plural=n==1 ? 0 : 1;"

Thanks to this expression, the correct forms are chosen for each value of n, e.g. for Polish: 1 plik, 2-4 pliki, 5-21 plików, 22-24 pliki, 25-31 plików, 32-34 pliki, 35-41 plików, ..., 110-121 plików, 122-124 pliki.

Proposed solution

As shown in bug 177097, .properties can be easily extended to allow gettext-like approach.

The proposed solution is to have the Plural-Forms expression in intl.properties:

intl.pluralForms.expression = n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

and the plural-dependant string in .properties as xxxx.0, xxxx.1, xxxx.2 etc.

Then, if a number is passed as an additional argument for getFormattedString (and probably also some lower-level functions for the C++ code as well), it would calculate the value of pluralForms.expression for that number and choose the correct string.

Example

The previous file/plik example would look like this then:

en-US

@intl.properties:

intl.pluralForms.expression = n==1 ? 0 : 1;

@example.properties:

numberOfFiles.0 = %S file
numberOfFiles.1 = %S files

pl

@intl.properties:

intl.pluralForms.expression = n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;

@example.properties:

numberOfFiles.0 = %S plik
numberOfFiles.1 = %S pliki
numberOfFiles.2 = %S plików

Example JS code

// show an alert telling the user how many files are open:
var foo = examplePropsStringBundle.getFormattedString("numberOfFiles", [ filesCount ], filesCount );
alert(foo);

Prototype

This patch for bug 177097 has a proof-of-concept implementation of the extended getFormattedString and a XPI testcase.

Wanna see a screenshot? Here.