[PHP] gettext

Résolu/Fermé
Yoan Messages postés 11795 Date d'inscription mardi 1 février 2005 Statut Modérateur Dernière intervention 10 décembre 2023 - 21 nov. 2008 à 00:38
Yoan Messages postés 11795 Date d'inscription mardi 1 février 2005 Statut Modérateur Dernière intervention 10 décembre 2023 - 24 nov. 2008 à 07:24
Bonjour à tous,

J'ai quelques questions quand-à l'utilisation de gettext pour internationaliser un site réalisé avec PHP :

1- Considérons qu'on veuille traduire une page en anglais (msgid anglais) vers le français :
$textdomain='messages';
putenv("LANGUAGE=fr_FR.utf8");
setlocale(LC_ALL,fr_FR.utf8);
bindtextdomain($textdomain,'locale');
textdomain($textdomain);
Doit-on disposer d'un fichier de langue (.po) anglais également ? Je m'attends à ce que la réponse soit non, mais dans ce cas-là, comment gère-t-on proprement le code ci-dessus ? Puisqu'aucun dossier fr_FR.utf8 n'existera, est-ce qu'on ne risque pas d'avoir une erreur ?

2- Comment se passe d'habitude l'ajout, la suppression ou la modification de textes dans la langue "native" ? Faut-il modifier les fichiers php, regénérer le fichier po, le retraduire (ou traduire juste ce qui a changé ?), recompiler le mo ? La démarche me laisse un peu perplexe. Il doit bien y avoir un moyen pour faire tout ça rapidement et sans annuler toute la traduction précédemment faite ;-)

Merci

2 réponses

asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
23 nov. 2008 à 16:04
Salut Yoan,

J'ai pas bien saisi la première question... le dossier je pense que tu as confondu fr_FR et en_GB pour le répertoire... bref, pas bien grave de toutes façons

Il faut savoir que si un traduction ne peut être réalisée, (peut importe la raison de cet echec) la chaine d'origine sera affichée (donc l'anglais dans ton cas.)

Ensuite pour merger, il faut utiliser msgmerge (ou le faire à la main, sur de gros volumes, msgmerge peut avoir un comportement anormal)

voici un exemple:
$ cat index.php
<?php
$textdomain='yoan';
putenv('LANGUAGE='.$_GET['locale']);
setlocale(LC_ALL,$_GET['locale']);
bindtextdomain($textdomain,'/usr/local/environments/env_01/httpd/htdocs/www/locales');

textdomain($textdomain);

echo '<h1>'._('title').'</h1>';
echo '<ul>';
echo '<li>'._('label one').'</li>';
echo '<li>'._('label two').'</li>';
echo '</ul>';
?>
$ xgettext -d yoan -o yoan.pot index.php
$ msginit -l en_GB -o yoan_en.po -i yoan.pot
$ msginit -l fr_FR -o yoan_fr.po -i yoan.pot
Le fichier yoan_en.po sera déjà rempli (msgid = msgstr), il faut completer le fichier yoan_fr.po et compiler:
$ msgfmt -c -v -o ../locales/fr_FR/LC_MESSAGES/yoan.mo yoan_fr.po
3 messages traduits.
$ msgfmt -c -v -o ../locales/en_GB/LC_MESSAGES/yoan.mo yoan_en.po
3 messages traduits.
Un petit test pour verifier...
Ensuite, on ajoute une ligne dans le fichier index.php
$ cat index.php
<?php
$textdomain='yoan';
putenv('LANGUAGE='.$_GET['locale']);
setlocale(LC_ALL,$_GET['locale']);
bindtextdomain($textdomain,'/usr/local/environments/env_01/httpd/htdocs/www/locales');

textdomain($textdomain);

echo '<h1>'._('title').'</h1>';
echo '<ul>';
echo '<li>'._('label one').'</li>';
echo '<li>'._('label two').'</li>';
echo '<li>'._('third label').'</li>';
echo '</ul>';
?>
$ xgettext -d yoan -o yoan-new.pot index.php
$ msgmerge -U yoan_en.po yoan-new.pot 
. terminé.
$ msgmerge -U yoan_fr.po yoan-new.pot 
. terminé.
le msgid "third label" a été ajouté aux deux fichiers et traduits dans aucun, tu peux le laisser vide pour l'anglais, et le traduire pour le français
$ msgfmt -c -v -o ../locales/en_GB/LC_MESSAGES/yoan.mo yoan_en.po 
3 messages traduits, 1 message non traduit.
$ msgfmt -c -v -o ../locales/fr_FR/LC_MESSAGES/yoan.mo yoan_fr.po
4 messages traduits.
et ça fonctionne :)


Maintenant, si tu modifies une chaine dans la langue native (IE: Dans le fichier index.php) il eput se passer deux chose dans le fichier mergé, soit la modification est radical et le message apparaitra comme un nouveau msgid (l'ancien sera commenté) soit la modification est minimale et une correspondance sera trouvée par gettext la traduiction sera conservée, et notée en fuzzy, c'est par exemple ce qui se passera si tu modifies label one en label 1 dans index.php, cela se traduira par la sortie suivante dans le fichier yoan_fr.po:
#: index.php:11
#, fuzzy
msgid "label 1" //Nouveau msgid
msgstr "libell&eacute; un" //ancienne traduction considérée comme fuzzy par gettext
A partir de là tu peux decider de fonctionner comme ça, et d'aller traduire les nouvelles chaines, et controller les chaines fuzzy. (La commande msgattrib permet de selectionner dans les fichiers *.po les msgid en fonction de leur états (fuzzy, traduits, non-traduits, etc.))

Le défaut, c'est que la detection des changements a ses limites, par exemple, si de label one tu passes à first label gettext va te passer ça en fuzzy, mais en mettant comme traduction troisième libellé, ce qui est du à la similarité entre third label et first label...

Tu peux aussi demander lors du merge a ne plus avoir de traduction fuzzy (option --no-fuzzy) dans ce cas toute nouvelle chaine sera considérée comme totalement nouvelle ;-)

A plus

6
Yoan Messages postés 11795 Date d'inscription mardi 1 février 2005 Statut Modérateur Dernière intervention 10 décembre 2023 2 327
23 nov. 2008 à 22:20
Yep,

Pour la première question tu y as répondu en fait. Je voulais savoir s'il fallait un .mo également pour la langue native. Je sais bien que s'il y a un problème c'est cette langue qui s'affiche mais je voulais faire ça proprement.

J'ai pas compris comment msginit a fait pour me remplir en faisant msgstr=msgid dans le PO anglais, comment a-t-il "su" que les msgid sont en anglais ?
Autre truc Je pige pas vraiment la différence entre un .pot et un .po. Il semble que le pot est un "modèle" dont les commentaires (language team etc) sont génériques puis remplis par le msginit, mais sinon c'est la même chose ?

Sinon ça marche bien effectivement, j'ai mis une majuscule à third il est passé en fuzzy et j'ai complètement changé le label two, il a été commenté :
#: ../../../index.php:11
msgid "this is the label number two : it has been deleted"
msgstr "voici le label deux : il a été supprimé"

#: ../../../index.php:12
#, fuzzy
msgid "Third label"
msgstr "troisième label"

#~ msgid "label two"
#~ msgstr "label deux"
En tout cas merci, j'ai compris les bases. T'es un chef :-P

EDIT : Ha tiens, un autre truc : je viens de tester mon exemple en français tel quel : le fuzzy 'Third label' n'est pas traduit en français lorsque je charge index.php. L'indicateur fuzzy n'est donc destiné qu'aux traducteur pour vérifier la traduction, mais gettext considère donc que le msgid n'est pas traduit, non ?
1
asevere Messages postés 13084 Date d'inscription lundi 28 janvier 2002 Statut Webmaster Dernière intervention 3 février 2022 426
23 nov. 2008 à 23:05
Question 1:
J'ai pas compris comment msginit a fait pour me remplir en faisant msgstr=msgid dans le PO anglais, comment a-t-il "su" que les msgid sont en anglais ?

C'est le point que je n'ai jamais réussi à élucider... ou enfin si..., c'est dans les sources de gettext, il n'a pas su, il considère que c'est de l'anglais, et à prioris, pas moyen de lui entendre autre chose :-)

Question 2:
POT: Portable Object Template
PO: Portable Object

A vrai dir c'est une question de norme, rien ne t'empeche à prioris d'utiliser d'autre extension...

Question 3:
C'est à peu prêt ça... Dans le pire des cas, il y a l'option -f de msginit pour utiliser les traductions notées comme fuzzy, mais à la base, les traductions qui sont notées en fuzzy sont à verifier, ensuite, soit elle sont OK et il faut enlever le marqueur, soit elles ne le sont pas et il faut les corriger et anlever le marqueur ;-)

C'est tout pour ce soir, bonne nuit, a plus
0
Yoan Messages postés 11795 Date d'inscription mardi 1 février 2005 Statut Modérateur Dernière intervention 10 décembre 2023 2 327
24 nov. 2008 à 07:24
Merci :-)
0