I18n C++ hello world with plurals

2020-07-24 04:30发布

问题:

Complete C++ i18n gettext() “hello world” example has C++ code that works for a simple fixed string. I am now looking for an example program that works with plurals. This example code displays six lines. Only one is correct in English. It does not handle the plurals correctly.

cat >helloplurals.cxx <<EOF
// hellopurals.cxx
#include <libintl.h>
#include <locale.h>
#include <iostream>
#include <stdio.h>
int main (){
    setlocale(LC_ALL, "");
    bindtextdomain("helloplurals", ".");
    textdomain( "helloplurals");
    for (int ii=0; ii<5; ii++)
        printf (gettext("Hello world with %d moon.\n"), ii);
}
EOF
g++ -o helloplurals helloplurals.cxx
./helloplurals

GNU gettext() for plural forms describes various ways that languages handle plurals for example:

  • Korean - no pluals
  • English - two forms, singular used for one only
  • French - two forms, singular used for zero and one
  • Polish - three forms, special case for one and some numbers ending in 2, 3, or 4

My expectation is that the code will be able to work (given message catalogs) specifically for all of the above cases and several more variations not listed here. The correct output when it is executed with English would be:

Hello world with 0 moons.
Hello world with 1 moon.
Hello world with 2 moons.
Hello world with 3 moons.
Hello world with 4 moons.

回答1:

I'm not sure what you want. If it is slight modification of your example that give your wanted output, just replace the printf line by

printf(ngettext("Hello world with %d moon\n", "Hello world with %d moons\n", ii), ii);

but as it is a trivial modification of unwind's answer and the gettext documentation has the very similar example,

printf (ngettext ("%d file removed", "%d files removed", n), n);

I wonder if it is really what you wanted. If you want to use gettext with a more C++ syntax, you'll have to look for libraries like Boost::Format.



回答2:

First, gettext() is not magical. It does not somehow contain a global dictionary of all words in all languages.

All it does is look up a message's translation in your application's message database, so this example assumes there is such a file (where gettext() can find it, this can be somewhat tricky).

Next, you're using it wrong. The page you linked to describes the ngettext() function, which is what you're going to have to use in order to get a translation that varies with a count.

Your call should look something like this:

printf("%s", ngettext("moon", "moons", ii));

This lets gettext decide which form to use, based on the count parameter.



回答3:

Well did you actually make a .po file for the different plural forms? See the description of the gettext workflow on Wikipedia. Also read all of the the gettxt documentation about plural forms in particular the examples of .po files containing plural forms.