gettext est un mécanisme permettant de traduire facilement un programme en plusieurs langue. La langue utilisé peut être choisie automatiquement à partir des valeurs des variables d'environnement (si disponible) ou sélectionnée depuis le programme.
Les variables d'environnement LANG et LC_ALL indiquent la langue à utiliser, et les variables LC_xxx indique un réglage particulier pour chaque paramètre (comme les dates, les nombres, la monnaie…). Ces variables sont les suivantes :
Les locales en cours peuvent être modifiées dans un terminal via “LC_xxx=<locale>”, par exemple “LC_ALL=fr_FR ; export LC_ALL” utilisera les paramètres pour la langue française.
Les locales utilisées peuvent être modifié dans un programme via setlocale() :
#include <locale.h> char *setlocale(int categorie, const char *locale); /* Exemple : */ setlocale(LC_ALL, "fr_FR");
Afin d'utiliser gettext, vous devez inclure <libintl.h>. Pour permettre à votre programme d'être utilisable dans plusieurs langues, vous devez changer toutes vos chaînes littérales en des appels à gettext(), dgettext(), etc :
printf("%s\n", gettext("Hello, world !"));
Les variantes de cette fonction sont :
Pour traduire un message, gettext cherche un fichier .mo pour la langue adéquate en se basant sur les locales en cours. La plupart du temps, ce fichier se trouve à “DIR_NAME/LOCALE/LC_CATEGORY/DOMAIN_NAME.mo”, où :
Les fonctions bindtextdomain(domainname, dirname) et textdomain(domainname) permettent respectivement de choisir le chemin à utiliser pour chercher les traductions associées à un domain, et à changer le domain par défaut pour les prochains appels aux fonctions xxgettext().
Notez également la présence d'une fonction bind_textdomain_codeset(domainname, codeset) permettant de choisir le codeset (character-set) utilisé par les chaînes retournées par les fonctions xxgettext().
Exemple :
#include <locale.h> #include <libintl.h> int main(void) { bindtextdomain("test", "."); textdomain("test"); setlocale(LC_MESSAGES, ""); /* "" indique que l'ont utilise les variables d'environnement */ printf("%s\n", gettext("Hello, world !")); /* la traduction de "Hello, world !" sera cherchée dans le fichier "./fr/LC_MESSAGES/test.mo" */ return 0; }
Vous pouvez générer un template contenant l'ensemble des chaînes à traduire de votre programme, portant habituellement l'extension .pot, en utilisant le programme xgettext :
xgettext src/*.c # scan tous les fichiers .c xgettext -D src # scan les fichiers du dossier src/
xgettext cherche les appels xxgettext() dans les fichiers-sources, dont il détermine le type grace à l'extension, et génère un fichier messages.po. Vous pouvez immédiatement renommer ce fichier pour lui donner l'extension .pot, et placer quelques informations pour vos traducteurs (ou vous même) dans le fichier.
Ensuite, pour traduire le programme dans une langue supplémentaire, vos traducteurs (ou vous-même) créez un nouveau fichier de traduction en utilisant msginit :
msginit --locale=fr_FR --input=messages.pot
Un fichier .po est créé ; vous devez l'éditer de façon à faire correspondre à chaque msgid le msgstr traduit dans la langue voulue. Une fois ce travail fini, vous pouvez générer le précieux fichier .mo contenant les chaînes traduites et utilisable directement par votre programme en utilisant msgfmt :
msgfmt -o fr/LC_MESSAGES/test.mo fr.po