Cette section explique comment implémenter le support natif d'une langue dans un programme ou dans une bibliothèque qui fait partie de la distribution PostgreSQL. Actuellement, cela s'applique uniquement aux programmes C.
Ajouter le support NLS à un programme
Le code suivant est inséré dans la séquence initiale du programme :
#ifdef ENABLE_NLS #include <locale.h> #endif ... #ifdef ENABLE_NLS setlocale(LC_ALL, ""); bindtextdomain("nomprog
", LOCALEDIR); textdomain("nomprog
"); #endif
(nomprog
peut être choisi tout à fait librement).
Partout où un message candidat à la traduction est trouvé,
un appel à gettext()
doit être inséré.
Par exemple :
fprintf(stderr, "panic level %d\n", lvl);
devra être changé avec :
fprintf(stderr, gettext("panic level %d\n"), lvl);
(gettext
est défini comme une opération nulle si NLS
n'est pas configuré).
Cela peut engendrer du fouillis. Un raccourci habituel consiste à utiliser :
#define _(x) gettext(x)
Une autre solution est envisageable si le programme effectue la plupart de ses
communications via une fonction ou un nombre restreint de fonctions, telle
ereport()
pour le moteur. Le fonctionnement interne de
cette fonction peut alors être modifiée pour qu'elle appelle
gettext
pour toutes les chaînes en entrée.
Un fichier nls.mk
est ajouté dans le répertoire des
sources du programme. Ce fichier sera lu comme un makefile. Les affectations
des variables suivantes doivent être réalisées ici :
CATALOG_NAME
Le nom du programme tel que fourni lors de l'appel à
textdomain()
.
GETTEXT_FILES
Liste des fichiers contenant les chaînes traduisibles, c'est-à-dire
celles marquées avec gettext
ou avec une
solution alternative. Il se peut que cette liste inclut pratiquement
tous les fichiers sources du programme. Si cette liste est trop longue,
le premier « fichier » peut être remplacé par un +
et le deuxième mot représenter un fichier contenant un nom de fichier par
ligne.
GETTEXT_TRIGGERS
Les outils qui engendrent des catalogues de messages pour les
traducteurs ont besoin de connaître les appels de
fonction contenant des chaînes à traduire. Par défaut, seuls les appels
à gettext()
sont reconnus. Si _
ou d'autres identifiants sont utilisés, il est nécessaire de les lister ici.
Si la chaîne traduisible n'est pas le premier argument,
l'élément a besoin d'être de la forme func:2
(pour
le second argument).
Si vous avez une fonction qui supporte les messages au format pluriel,
l'élément ressemblera à func:1,2
(identifiant les arguments singulier et pluriel du message).
Ajouter un fichier po/LINGUAS
, qui contiendra la liste
des traductions fournies -- initialement vide.
Le système de construction s'occupera automatiquement de construire et installer les catalogues de messages.
Voici quelques lignes de conduite pour l'écriture de messages facilement traduisibles.
Ne pas construire de phrases à l'exécution, telles que :
printf("Files were %s.\n", flag ? "copied" : "removed");
L'ordre des mots d'une phrase peut être différent dans d'autres langues.
De plus, même si gettext()
est correctement appelé sur chaque fragment,
il pourrait être difficile de traduire séparément les fragments. Il est
préférable de dupliquer un peu de code de façon à ce que chaque message à
traduire forme un tout cohérent. Seuls les nombres, noms de fichiers et
autres variables d'exécution devraient être insérés au moment de
l'exécution dans le texte d'un message.
Pour des raisons similaires, ceci ne fonctionnera pas :
printf("copied %d file%s", n, n!=1 ? "s" : "");
parce que cette forme présume de la façon dont la forme plurielle est obtenue. L'idée de résoudre ce cas de la façon suivante :
if (n==1) printf("copied 1 file"); else printf("copied %d files", n):
sera source de déception. Certaines langues ont plus de deux formes avec des règles particulières. Il est souvent préférable de concevoir le message de façon à éviter le problème, par exemple ainsi :
printf("number of copied files: %d", n);
Si vous voulez vraiment construire un message correctement pluralisé,
il existe un support pour cela, mais il est un peu étrange. Quand vous
générez un message d'erreur primaire ou détaillé dans
ereport()
, vous pouvez écrire quelque-chose comme
ceci :
errmsg_plural("copied %d file", "copied %d files", n, n)
Le premier argument est le chaîne dans le format approprié pour la forme
au singulier en anglais, le second est le format de chaîne approprié pour
la forme plurielle en anglais, et le troisième est la valeur entière
déterminant la forme à utiliser. Des arguments additionnels sont formatés
suivant la chaîne de formatage comme d'habitude. (Habituellement, la
valeur de contrôle de la pluralisation sera aussi une des valeurs à
formater, donc elle sera écrite deux fois.) En anglais, cela n'importe
que si n
est égale à 1 ou est différent de 1,
mais dans d'autres langues, il pourrait y avoir plusieurs formes de
pluriel. Le traducteur voit les deux formes anglaises comme un groupe
et a l'opportunité de fournir des chaînes de substitution supplémentaires,
la bonne étant sélectionnée suivant la valeur à l'exécution de
n
.
Si vous avez besoin de pluraliser un message qui ne va pas directement à
errmsg
ou errdetail
, vous devez
utiliser la fonction sous-jacente ngettext
. Voir la
documentation gettext.
Lorsque quelque chose doit être communiqué au traducteur, telle que la façon
dont un message doit être aligné avec quelque autre sortie, on pourra faire
précéder l'occurrence de la chaîne d'un commentaire commençant par
translator
, par exemple :
/* translator: This message is not what it seems to be. */
Ces commentaires sont copiés dans les catalogues de messages de façon à ce que les traducteurs les voient.