In this tutorial we walk through the steps needed in order to add localizations to an existing project that uses GNU Autotools as build system.
We start by taking a a slightly modified version of the Hello World example that comes with Automake sources. You can keep track of the changes to the source throughout this tutorial by following the commits to amhello-gettext on GitHub. We start with the following files:
$ ls -RF .: configure.ac Makefile.am README src/ ./src: main.c Makefile.am
The first step is copying some necessary
gettext infrastructure to your project. This is done running
gettexize in the root directory of your project. The command will create a bunch of new files and modify some existing files. Most of these files are auto-generated, so there is no need to add them to your version control. You should only add those files you create or modify manually.
You will need to add the following line to your
The version specified is the minimum required version of gettext your package can compile against.
po/Makevars and modify it as needed.
The next step is to copy over
gettext.h to your sources.
$ cp /usr/share/gettext/gettext.h src/
libintl.h, which is the header that provides the different translation functions.
gettext.h is a convenience wrapper around it which allows disabling
gettext if the
--disable-nls is passed the
./configure script. It is recommended to use
gettext.h in favor of
In order for
gettext to work, you need to trigger it in your
main(). This is done by adding the following lines to the
setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE);
You should also add
#include "gettext.h to the list of includes.
PACKAGE should be the name of your program, and is usually defined in
config.h file generated by either
autoheader. To define
LOCALEDIR we need to add the following line to
AM_CPPFLAGS = -DLOCALEDIR='"$(localedir)"'
AM_CPPFLAGS is already defined, just append to it the
Marking strings for translation
At this point, your program should compile with
gettext. But since we did not translate anything yet it will not do anything useful. Before translating we need to mark the translatable strings in the sources. Wrap each translatable string in
_(...), and add the following lines to each file that contains translatable strings:
#include "gettext.h" #define _(String) gettext (String)
Extracting string for translation
Before extracting the strings, we need to tell
gettext where to look. This is done by listing each source file with translatable strings in
po/POTFILES.in. So in our example
po/POTFILES.in should look like:
# List of source files which contain translatable strings. src/main.c
Afterwards the following command can be used to actually extract the strings to
po/amhello.pot (which should go in the version control):
make -C po/ update-po
If you haven’t ran
./configure yet you need to run
autoreconf --install && ./configure before running the above
To begin translating, you need to a
*.po file for your language. This is done using
cd po/ && msginit --locale he_IL.utf8
The locale should be specified as two-letter language code followed by two-letter country code. In my example, I’ve used Hebrew, hence it will create a
po/he.po file. To translate the program you edit the
.po file, using either a text editor or a dedicated program (see list of editors here).
After you updated the
.po file for your language, list the language in
po/LINGUAS (you need to create it). For example, in my case:
# Set of available languages he
Now you should be ready to compile and test the translation. Unfortunately,
gettext requires installing the program in order to properly load the message catalogs, so we need to call
./configure --prefix /tmp/amhello make make install
Now to check the translation simply run
/tmp/amhello/bin/hello (you might need to change
LANGUAGES depending on your locale to see the translation).
$ LANGUAGE=he /tmp/amhello/bin/hello שלום עולם!
Final note about bootstrapping. When people checkout your code from the version control, many autogenerated files will be missing. The simplest way to bootstrap the code into a state which you can simple call
./configure && make is by using
Will add any missing files and run all the autotools friends (
autoheader`, etc.) in the right order. Additionally it will callautopoint
which copies the necessarygettext
files that were generated when you calledgettextize` earlier in the tutorial. If your project is using
./autogen.sh script that call the autotools utilities manually, you should add a call to
autopoind --force before the call to
Finally, those are the files that end up version controlled in our example:
$ ls -RF .: configure.ac Makefile.am po/ README src/ ./po: amhello.pot he.po LINGUAS Makevars POTFILES.in ./src: gettext.h main.c Makefile.am