Why is msgid_plural necessary in gettext translati

2019-07-15 07:17发布

问题:

I've read the GNU Gettext manual about Translating plural forms and see its example:

 #, c-format
 msgid "One file removed"
 msgid_plural "%d files removed"
 msgstr[0] "%d slika je uklonjena"
 msgstr[1] "%d datoteke uklonjenih"
 msgstr[2] "%d slika uklonjenih"

Why is msgid_plural different from msgid, and doesn't that defeat the purpose of having translations be aware of plural forms?

I'd think that I could do something like this (for English):

 #, c-format
 msgid "X geese"
 msgstr[0] "%d goose"
 msgstr[1] "%d geese"

 #, c-format
 msgid "sentence_about_geese_at_the_lake"
 msgstr[0] "There is one goose at the lake."
 msgstr[1] "There are %d geese at the lake."

(using just one msgid).

Then in my code, I'd have something like:

<?php echo $this->translate('X geese', $numberA); ?> 
<?php echo $this->translate('sentence_about_geese_at_the_lake', $numberB); ?> 

If $numberA is 3, it would say "3 geese."

If $numberB is 0, the next line would say "There are 0 geese at the lake."

(because for English, the rule is (n != 1), so plural is used for any number that equals 0 or greater than 1).

It seems redundant for me to be required to specify 2 msgids for the same collection of phrases.

Thanks for your help!

回答1:

One of the ideas behind gettext is that the msgid is extracted from source files to create POT files, which are used as base for translations stored in PO files, and later compiled to MO files. A msgid is also used if no suitable translation is found.

A msgid is not a "key" that is non-readable by users; it is a real phrase that can be used in the program. So when in your code you request a translation for a plural (pseudocode here):

ngettext("One file removed", "%d files removed", file_count)

...these two strings will be used a) to extract messages from the source code; these messages will serve as guide for translators b) as the default strings when no suitable translation is found for the current locale.

That's why a plural string has two msgid: to show how they are defined in the source program (for translators) and to be used as default (when no translation exists).

In other localization systems, like Android String Resources or Rails YAML files, it works like you imagined -- the equivalent to a msgid is a single "key" even for plurals, but then the real phrase is not used in the source code, and defining translations is a two-steps action even for the original language.