Using Gettext For Native Language Support
The GNU gettext C library provides basic NLS, allowing
a program's text messages to be translated.
GNU gettext is licensed with the GPL, not the LGPL, so any
programs using it must also be GPL'ed if they are distributed.
Modifying autoconf/automake For gettext
gettext is intended to be used in conjunction with the autoconf/automake
OS portability tools, and will not easily work without them. The programmer
should modify the autoconf configuration files in the top-level package
directory as follows:
In "configure.in," add the following lines:
ALL_LINGUAS=""
AM_GNU_GETTEXT
AC_OUTPUT([
intl/Makefile
po/Makefile.in
])
|
Your AC_OUTPUT section will list other files as well, but the above is
what is needed for gettext support. When support for a new language is
added to your package, add the language code to the ALL_LINGUAS macro.
For example, if your package has translations for German and French,
the line will read ALL_LINGUAS="de fr".
In "acconfig.h," add the following lines:
#undef PACKAGE
#undef VERSION
#undef HAVE_LIBSM
#undef HAVE_CATGETS
#undef HAVE_GETTEXT
#undef HAVE_LC_MESSAGES
#undef HAVE_STPCPY
#undef ENABLE_NLS
|
In the top-level "Makefile.am", add "intl" and "po" to SUBDIRS.
Setting Up gettext
Once you've set up autoconf and automake to work with gettext,
create the gettext support files:
From the top-level package directory, run "gettextize" once.
This creates the necessary support files for gettext, including copying
the gettext library into an "intl/" subdirectory, and setting up a
"po/" subdirectory to hold translation files. This way, gettext is
distributed with your package so users don't need to install it separately.
(The intl/ subdirectory will contain links, so if you use tar to archive
your distribution, give it the -h option. autoconf does this
automatically for "make dist".)
In the "intl/" subdirectory, run "make all-yes" once.
Create a file "po/POTFILES.in" listing all the source code files
that have translatable strings, and keep this file up-to-date. For example:
# Source files containing translatable strings:
lib/hello_msg.c
lib/hello_help.c
src/hello.c
|
Running make in the po/ directory will run xgettext to rebuild
the ".pot" file containing all translatable strings. This will normally
be done automatically from a make in the top-level directory, but
can also be done independently if desired.
Programming With gettext
To use gettext, the programmer should:
Edit each source code directory's Makefile.am to make sure
LIBS and INCLUDES include the following:
LIBS=-L../../intl -lintl
INCLUDES=-DLOCALEDIR=\"$(datadir)/locale\" -I../../intl
|
Replace "../../intl" with the location of your intl directory.
Add the following near the top of each source code file,
or in a common header file:
#include <libintl.h>
#define _(s) gettext(s)
#define gettext_noop(s) (s)
#define N_(s) gettext_noop (s)
|
The defines aren't absolutely necessary but they make the source code
cleaner. If you #include <gnome.h>, do not do the above,
as gnome.h will do it for you.
Include the following code early in each program's main() function:
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
|
PACKAGE is the package name and LOCALEDIR is the package's locale
directory, as specified in config.h and the make file respectively.
In certain cases the LC_ALL flag might not be correct. See the gettext
documentation and the locale(7) man page for details.
To ease translation, use whole, standalone strings when creating
messages, as opposed to building them from pieces. For example:
/* the wrong way */
printf("You have %d guess%s left.\n", nguesses, (nguesses == 1)? "" : "es");
/* the right way */
if (nguesses == 1)
printf("You have one guess left.\n");
else
printf("You have %d guesses left.\n", nguesses);
|
Wrap all translatable strings in each program with _(), including
output and error messages, user interface components like menu
names, and so forth. For example:
printf( _("You have %d guesses left.\n"), nguesses);
|
The only exception is for places where the output of a function isn't
acceptable, such as in static initializations; these should
be marked with N_() instead, and _() when they are actually used. For example:
static char **messages = {
N_("potato"),
N_("carrot"),
N_("onion")
};
...
printf( _("You guessed %s.\n"), _(messages[i]) );
|
See the gettext documentation for details on providing translation
files for other languages.
Security
Tools
|