The following discussion is perhaps a little bit colored. As said
above we implemented GNU gettext
following the Uniforum
proposal and this surely has its reasons. But it should show how we
came to this decision.
First we take a look at the developing process. When we write an
application using NLS provided by gettext
we proceed as always.
Only when we come to a string which might be seen by the users and thus
has to be translated we use gettext("...")
instead of
"..."
. At the beginning of each source file (or in a central
header file) we define
#define gettext(String) (String)
Even this definition can be avoided when the system supports the
gettext
function in its C library. When we compile this code the
result is the same as if no NLS code is used. When you take a look at
the GNU gettext
code you will see that we use _("...")
instead of gettext("...")
. This reduces the number of
additional characters per translatable string to 3 (in words:
three).
When now a production version of the program is needed we simply replace the definition
#define _(String) (String)
by
#include <libintl.h> #define _(String) gettext (String)
and include the header `libintl.h'. Additionally we run the program `xgettext' on all source code file which contain translatable strings and we are gone. We have a running program which does not depend on translations to be available, but which can use any that becomes available.
The same procedure can be done for the gettext_noop
invocations
(see section Special Cases of Translatable Strings). First you can define gettext_noop
to a
no-op macro and later use the definition from `libintl.h'. Because
this name is not used in Suns implementation of `libintl.h',
you should consider the following code for your project:
#ifdef gettext_noop # define N_(Str) gettext_noop (Str) #else # define N_(Str) (Str) #endif
N_
is a short form similar to _
. The `Makefile' in
the `po/' directory of GNU gettext knows by default both of the
mentioned short forms so you are invited to follow this proposal for
your own ease.
Now to catgets
. The main problem is the work for the
programmer. Every time he comes to a translatable string he has to
define a number (or a symbolic constant) which has also be defined in
the message catalog file. He also has to take care for duplicate
entries, duplicate message IDs etc. If he wants to have the same
quality in the message catalog as the GNU gettext
program
provides he also has to put the descriptive comments for the strings and
the location in all source code files in the message catalog. This is
nearly a Mission: Impossible.
But there are also some points people might call advantages speaking for
catgets
. If you have a single word in a string and this string
is used in different contexts it is likely that in one or the other
language the word has different translations. Example:
printf ("%s: %d", gettext ("number"), number_of_errors) printf ("you should see %d %s", number_count, number_count == 1 ? gettext ("number") : gettext ("numbers"))
Here we have to translate two times the string "number"
. Even
if you do not speak a language beside English it might be possible to
recognize that the two words have a different meaning. In German the
first appearance has to be translated to "Anzahl"
and the second
to "Zahl"
.
Now you can say that this example is really esoteric. And you are right! This is exactly how we felt about this problem and decide that it does not weight that much. The solution for the above problem could be very easy:
printf (gettext ("number: %d"), number_of_errors) printf (number_count == 1 ? gettext ("you should see %d number") : gettext ("you should see %d numbers"), number_count)
We believe that we can solve all conflicts with this method. If it is difficult one can also consider changing one of the conflicting string a little bit. But it is not impossible to overcome.
Translator note: It is perhaps appropriate here to tell those English speaking programmers that the plural form of a noun cannot be formed by appending a single `s'. Most other languages use different methods. So you should at least use the method given in the above example.
But I have been told that some languages have even more complex rules.
A good approach might be to consider methods like the one used for
LC_TIME
in the POSIX.2 standard.
Go to the first, previous, next, last section, table of contents.