standards: Internationalization
1
1 5.8 Internationalization
1 ========================
1
1 GNU has a library called GNU gettext that makes it easy to translate the
1 messages in a program into various languages. You should use this
1 library in every program. Use English for the messages as they appear
1 in the program, and let gettext provide the way to translate them into
1 other languages.
1
1 Using GNU gettext involves putting a call to the 'gettext' macro
1 around each string that might need translation--like this:
1
1 printf (gettext ("Processing file '%s'..."), file);
1
1 This permits GNU gettext to replace the string '"Processing file
1 '%s'..."' with a translated version.
1
1 Once a program uses gettext, please make a point of writing calls to
1 'gettext' when you add new strings that call for translation.
1
1 Using GNU gettext in a package involves specifying a "text domain
1 name" for the package. The text domain name is used to separate the
1 translations for this package from the translations for other packages.
1 Normally, the text domain name should be the same as the name of the
1 package--for example, 'coreutils' for the GNU core utilities.
1
1 To enable gettext to work well, avoid writing code that makes
1 assumptions about the structure of words or sentences. When you want
1 the precise text of a sentence to vary depending on the data, use two or
1 more alternative string constants each containing a complete sentences,
1 rather than inserting conditionalized words or phrases into a single
1 sentence framework.
1
1 Here is an example of what not to do:
1
1 printf ("%s is full", capacity > 5000000 ? "disk" : "floppy disk");
1
1 If you apply gettext to all strings, like this,
1
1 printf (gettext ("%s is full"),
1 capacity > 5000000 ? gettext ("disk") : gettext ("floppy disk"));
1
1 the translator will hardly know that "disk" and "floppy disk" are meant
1 to be substituted in the other string. Worse, in some languages (like
1 French) the construction will not work: the translation of the word
1 "full" depends on the gender of the first part of the sentence; it
1 happens to be not the same for "disk" as for "floppy disk".
1
1 Complete sentences can be translated without problems:
1
1 printf (capacity > 5000000 ? gettext ("disk is full")
1 : gettext ("floppy disk is full"));
1
1 A similar problem appears at the level of sentence structure with
1 this code:
1
1 printf ("# Implicit rule search has%s been done.\n",
1 f->tried_implicit ? "" : " not");
1
1 Adding 'gettext' calls to this code cannot give correct results for all
1 languages, because negation in some languages requires adding words at
1 more than one place in the sentence. By contrast, adding 'gettext'
1 calls does the job straightforwardly if the code starts out like this:
1
1 printf (f->tried_implicit
1 ? "# Implicit rule search has been done.\n",
1 : "# Implicit rule search has not been done.\n");
1
1 Another example is this one:
1
1 printf ("%d file%s processed", nfiles,
1 nfiles != 1 ? "s" : "");
1
1 The problem with this example is that it assumes that plurals are made
1 by adding 's'. If you apply gettext to the format string, like this,
1
1 printf (gettext ("%d file%s processed"), nfiles,
1 nfiles != 1 ? "s" : "");
1
1 the message can use different words, but it will still be forced to use
1 's' for the plural. Here is a better way, with gettext being applied to
1 the two strings independently:
1
1 printf ((nfiles != 1 ? gettext ("%d files processed")
1 : gettext ("%d file processed")),
1 nfiles);
1
1 But this still doesn't work for languages like Polish, which has three
1 plural forms: one for nfiles == 1, one for nfiles == 2, 3, 4, 22, 23,
1 24, ... and one for the rest. The GNU 'ngettext' function solves this
1 problem:
1
1 printf (ngettext ("%d files processed", "%d file processed", nfiles),
1 nfiles);
1