Miriam Ruiz
random thoughts on technology and life

{August 05, 2007}   Recipe: Internationalizing a C program with gettext

gettext is the GNU internationalization (i18n) library, and it is one of the most important standards in Free Software about i18n of programs. Translators are used to it, and there are really lots of useful tools to work with gettext data, so I’d recommend anyone to avoid trying to invent their own yet-another-gettext-but-not-quite-as-the-real-one. Gettext also works for Windows, so no excuse.

It’s really easier than it sounds. Here goes the quite recipe:

Add this to the headers of the C module in which you have your main() function:

#include "libintl.h"
#include "locale.h"
#define _(String) gettext (String)
#define _(String) String

And add this at the beginning of your main() function:

setlocale (LC_MESSAGES, "");
setlocale (LC_CTYPE, "");
setlocale (LC_COLLATE, "");
textdomain ("my-program");
bindtextdomain ("my-program", NULL);

That’s all for the initialization of gettext, lets go now with its usage from the rest of the modules. In each of them, you’d have to add this to the headers:

#include "libintl.h"
#define _(String) gettext (String)
#define _(String) String

After all that stuff, you should be able to i18n for whichever texts you want, just write _(“whatever”) instead of just “whatever”:


Don’t forget to compile your program with -DUSE_GETTEXT if you use the same #defines as I do, or at least to #define USE_GETTEXT somewhere. Now, lets go to the second part, generating the .pot templates, and installing the .mo translation modules in your system:

xgettext -k_ -o my-program.pot *.c *.h --from-code=iso-8859-1

If you prefer, you can create different .pot files for the different parts of your programs instead a really big one to help translators, and then joining all the .po files inside a single one before converting it to .mo with msgcat:

msgcat -o my-program.es.po my-program.part1.es.po my-program.part2.po my-program.part3.es.po

To compile the .po files into .mo, just do:

msgfmt my-program.es.po -o my-program.es.mo

Then, don’t forget to install it in the proper directory of your system:

cp my-program.es.mo /usr/share/locale/es/LC_MESSAGES/my-program.mo

Of course, you can tell your program to look for the .mo file in a different directory, even a relative one, instead. Just read the man pages, this is only a quick recipe on how to do it :)

Note: Please, use #include [smaller than]whatever.h[bigger than] instead of #include “whatever.h”, as I have put in my examples. My WordPress weblog seems to be having problems with the those symbols. That’s the magic of HTML.

Alexey Beshenov says:

Use &lt; to represent < and &gt; to represent >.

alvaro says:

Woh!, I save this post in a special site, I was searching for years, for a site that explains how to internializate a program, in a simple and clear form, without success. until now. congratulations.

Miry says:


I’ve tried that, Alexey, but WordPress just simply replaces them silently with < and > and it just doesn’t work. I guess it might have to do with using the WYSIWYG editor instead of the plain text one.

Henrique says:

Remember that it takes a bit more than just sprinkling _() around to properly l10n something.

1. You need to _() complete sentences. Most of the time, you should try to do it to the entire “dialog unit”. Fragments are useless for translation.

2. Plurals are not obvious. At all. Read the gettext documentation on how to deal with them, and how to _() them so that you can l10n it to languages with very different structures for the plural.

Leave a Reply


This is a personal webpage that belongs to Miriam Ruiz.
If you want to contact her, you can do at:

June 2018
« Nov    

La Lista de Sinde