views:

304

answers:

3

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>
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.
A: 

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.

flodin
The first link in the question has the sequence for creating the messages catalogs. Here I am looking for example C++ code.
C.W.Holeman II
+1  A: 

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.

unwind
Added message catalog note to the question. The code in the question is intended to be a concrete starting point. The documentation I have found for the gettext() group of functions is lacking clear examples for plurals
C.W.Holeman II
Note, this is not good idea to take a word from context and translate it, especially for plural forms. You should take the hole sentance, because other forms may depend on "number of moons"
Artyom
+2  A: 

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.

AProgrammer
How does this support languages which have three or more forms such as Polish?
C.W.Holeman II
The catalog contains the language rules; the default rules applied by ngettext if you don't have a catalog are the english one (and so it you try to use it with a french or polish text, you'll have an incorrect output).
AProgrammer
If you use just gettext() there is no number passed to allow the catalog to kick in. If ngettext() is used then a number is passed that can be used with the catalog rules and messages. The multiple English messages passed are only for the case where a catalog is not used which works fine for English.Thanks.Would you expand your answer to cover all of this?
C.W.Holeman II