Next Previous Contents

14.2 gettext usage

This section explains how to code for proper messages localization by gettext package.

PO file updating

You should keep the surprise/po/${LANG}.po source files for message translations up to date. By make -C surprise/po update-po you will always update all PO files by examining all *.c source files (usually modified when time passes). Please do this update-po before starting any message translation.

If you add new file that uses translation macros, you must call autogen at first -- because it composes the list of files that should be indexed. It doesn't do any M4 expansion etc., so if you want to translate a string, you must write the _("...") or N_("...") directly near the string. The only exceptions are params.m4 and files -- autogen is modified to insert params.c and error_chket.h files into altough they don't exist yet. These generated files will contain N_("...") macro calls generated by M4/com_err.

Then you should edit your file surprise/po/${LANG}.po where ${LANG} is the language you are appropriate for. You should always search for two defects:

Although in classical editor (VIM etc.) the search is pretty easy, you will find more comfort in PO mode implemented in GNU Emacs editor. Please look into Texinfo manual for gettext package for more PO mode information.

When you are starting to implement new language translations, you should update ALL_LINGUAS variable in surprise/ file accordingly. The surprise/po/${LANG}.po file header can be by copying it adapted from its mates.

Writing correctly translatable C code

Although _(variable) syntax is usually identical to gettext(variable), you should always use _(variable) syntax in Surprise project as this macro automatically expands to appropriate dgettext() call for libsurprise based code. As a further note I must declare a specific requirement for _("string") before gettext("strings") as otherwise translatable strings detection may fail and you will remain with incorrect (incomplete) PO file.

As _(anything) syntax will result in real function call, you may not use it in places where executable code is not permitted. Typical example is plain C global variable or structures defined in declarations. Such _("string") usages would result in GCC error message `initializer element is not constant'. (Please note that C++ supports such code but Surprise project is written for compatibility reasons in non-++, plain C.) In C you must use N_("string") code in these cases - translatable string detection will find this string correctly although you have to use explicit _(variable) construct in ALL places where you want to access such N_(...) initialized variables.

Example showing the most effective use of _(...) vs. N_(...) directives:

#include "generic.h" /* take care of localization definitions/declarations */

struct x {
  int num;
  char *val;

struct x Global={ 4, N_("foo") };

int main(void)
static struct x Static={ 4, N_("foo") };
struct x Local={ 5, _("bar") };
char *String=_("foobar");


Filesystem implementators have to respect dupl_parameter() and dupl_parameter_gettext() accordingly. When they are initially duplicating parameters from code-declared ones, *_getext variant should be used. In the case of possible duplication of already generated memory-based structures, pure (non-*_gettext) variant is appropriate, of course. This paragraph accordingly applies also to dupl_pars() and dupl_pars_gettext() functions.

Text domain use

`text domain' used in the following text corresponds to `.po', `.mo' or `.gmo' files (exact suffix depending on compilation stage). This file contains translation of all messages contained in the program using it, these files are all named according to their language. When this text domain file(s) get out of date, missing translation strings are still displayed but in their original english form.

Whole Surprise is now made as a single text domain named `surprise'. Both libsurprise part and all code of clients use this one text domain. When libsurprise will start to get more third-party clients with separated development from libsurprise, it will be apropriate to split this text domain.

locale_init() call is appropriate only for use from packages using text domain `surprise', e.g. Surprise clients. Whole `libsurprise' does not use actually set default domain, it always accesses its messages by explicit text domain use. You can use `libsurprise' from third-party software without any fear about localization - libsurprise will accept your setlocale(3) settings and it is not concerned about the text domain actually in default use.

locale_init() should be called only from programs where all their strings are translated in the range of `surprise' text domain. It is used by Surprise clients to save code size by using convenient default text domain `surprise'.

Next Previous Contents