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