Next: , Previous: , Up: Writing C   [Contents][Index]

5.8 Internationalization

GNU has a library called GNU gettext that makes it easy to translate the messages in a program into various languages. You should use this library in every program. Use English for the messages as they appear in the program, and let gettext provide the way to translate them into other languages.

Using GNU gettext involves putting a call to the gettext macro around each string that might need translation—like this:

printf (gettext ("Processing file '%s'..."), file);

This permits GNU gettext to replace the string "Processing file '%s'..." with a translated version.

Once a program uses gettext, please make a point of writing calls to gettext when you add new strings that call for translation.

Using GNU gettext in a package involves specifying a text domain name for the package. The text domain name is used to separate the translations for this package from the translations for other packages. Normally, the text domain name should be the same as the name of the package—for example, ‘coreutils’ for the GNU core utilities.

To enable gettext to work well, avoid writing code that makes assumptions about the structure of words or sentences. When you want the precise text of a sentence to vary depending on the data, use two or more alternative string constants each containing a complete sentences, rather than inserting conditionalized words or phrases into a single sentence framework.

Here is an example of what not to do:

printf ("%s is full", capacity > 5000000 ? "disk" : "floppy disk");

If you apply gettext to all strings, like this,

printf (gettext ("%s is full"),
        capacity > 5000000 ? gettext ("disk") : gettext ("floppy disk"));

the translator will hardly know that "disk" and "floppy disk" are meant to be substituted in the other string. Worse, in some languages (like French) the construction will not work: the translation of the word "full" depends on the gender of the first part of the sentence; it happens to be not the same for "disk" as for "floppy disk".

Complete sentences can be translated without problems:

printf (capacity > 5000000 ? gettext ("disk is full")
        : gettext ("floppy disk is full"));

A similar problem appears at the level of sentence structure with this code:

printf ("#  Implicit rule search has%s been done.\n",
        f->tried_implicit ? "" : " not");

Adding gettext calls to this code cannot give correct results for all languages, because negation in some languages requires adding words at more than one place in the sentence. By contrast, adding gettext calls does the job straightforwardly if the code starts out like this:

printf (f->tried_implicit
        ? "#  Implicit rule search has been done.\n",
        : "#  Implicit rule search has not been done.\n");

Another example is this one:

printf ("%d file%s processed", nfiles,
        nfiles != 1 ? "s" : "");

The problem with this example is that it assumes that plurals are made by adding ‘s’. If you apply gettext to the format string, like this,

printf (gettext ("%d file%s processed"), nfiles,
        nfiles != 1 ? "s" : "");

the message can use different words, but it will still be forced to use ‘s’ for the plural. Here is a better way, with gettext being applied to the two strings independently:

printf ((nfiles != 1 ? gettext ("%d files processed")
         : gettext ("%d file processed")),

But this still doesn’t work for languages like Polish, which has three plural forms: one for nfiles == 1, one for nfiles == 2, 3, 4, 22, 23, 24, ... and one for the rest. The GNU ngettext function solves this problem:

printf (ngettext ("%d files processed", "%d file processed", nfiles),

Next: , Previous: , Up: Writing C   [Contents][Index]