Pourquoi ne pas simplement utiliser
gettext(), qui constitue le standard en la matière ?
1.
Création de l'arborescence, par exemple
Code : Tout sélectionner
./locale
|-- de
| `-- LC_MESSAGES
|-- en
| `-- LC_MESSAGES
`-- fr
`-- LC_MESSAGES
2.
Création des fichier .po (source) dans chaque dossier LC_MESSAGES. Ils ont pour nom le nom du «domaine de l'application» (façon d'identifier les tables de traduction), par exemple «MonAppli.po». Ces fichiers sont des paires de lignes de cette forme :
Code : Tout sélectionner
msgid "Identifiant de la chaîne à traduire"
msgstr "Valeur de la chaîne traduite"
En identifiant on utilise systématiquement la chaîne non traduite tout simplement, exemple :
Code : Tout sélectionner
msgid "Hello %s !"
msgstr "Bonjour %s !"
msgid "Bye bye :)"
msgstr "Au revoir :)"
3.
Compilation des fichiers .po en .mo. C'est ce qui donne au système sa performance

Pour chaque fichier il suffit d'utiliser msgfmt :
Code : Tout sélectionner
$ msgfmt -o ./locale/fr/LC_MESSAGES/MonAppli.mo ./locale/fr/LC_MESSAGES/MonAppli.po
J'utilise personnellement cette commande qui va me compiler tous les fichiers .po d'un dossier (récursivement) avec le même nom en .mo :
Code : Tout sélectionner
$ find ./locale -name *.po | while read f; do msgfmt -o $(echo $f | sed 's/po$/mo/') $f && echo "OK $f" || echo "FAIL $f"; done
4.
Utilisation. On va simplement reprendre l'exemple de la doc
<?php
// Choix de la langue
setlocale(LC_ALL, 'fr');
// Spécifie la localisation des tables de traduction (le dossier contenant l'arborescence) pour le domaine indiqué
bindtextdomain("MonAppli", "./locale");
// Choix du domaine
textdomain("MonAppli");
// La traduction est cherché dans ./locale/fr/LC_MESSAGES/MonAppli.mo
// Affichage d'un message de test
printf(gettext("Hello %s !") . "\n", getenv('USER'));
// Or use the alias _() for gettext()
echo _("Bye bye :)") . "\n";
?>
Avantages
- La localisation d'une appli non localisée au départ est très simple (cf. mon Post-Scriptum).
- On utilise la méthode standard GNU, ce qui signifie qu'un éventuel portage ne posera jamais le moindre problème.
- On utilise la richesse de gettext, pour en avoir une idée jeter un oeil par exemple à la fonction ngettext(), comment gérer aussi simplement les pluriels avec une autre méthode ?

- On a une performance accrue (utilisation de la RAM, et rapidité de la traduction amoindries).
- L'utilisation est vraiment simplissime avec la fonction _()
- La définition de la langue de travail repose sur setlocale(), ce qui localise toute l'application et certaines fonctions comme date() en profiteront du même coup.
- On peut gérer plusieurs encodages (des pages en UTF-8, d'autres en ISO-quelquechose, etc...) avec la génération de fichiers .po au bon encodage, et de la fonction bind_textdomain_codeset()
Inconvénients
- Nécessite de compiler les fichier *.po avant de les envoyer sur le serveur.
- Nécessite la présence du module gettext dans la version de PHP (pas vraiment une difficulté puisque c'est activé par défaut)
Localisation d'une appli non prévue au départ
- Ajouter au début du script les appels à setlocale() (pour changer la langue),
bindtextdomain() (pour préciser l'emplacement de l'arborescence pour le domaine) et
textdomain() (pour préciser le domaine).
- Encadrer les chaînes à localiser avec
_()
- Utiliser le programme xgettext qui va générer un modèle de fichier .po (il va détecter les chaînes localisées). Par exemple la commande appliquée à notre script
Va donner le fichier messages.po
Code : Tout sélectionner
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-03-24 11:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: appli.php:15
#, php-format
msgid "Hello %s !"
msgstr ""
#: appli.php:18
msgid "Bye bye :)"
msgstr ""
- Dupliquer ce fichier dans l'arborescence de ./locale
- Traduire
- Compiler (avec la commande que j'ai donnée qui va tout compiler récursivement).
- L'application est intégralement traduire
[edit=1]Ajout des liens[/edit]
Pourquoi ne pas simplement utiliser [url=http://fr3.php.net/manual/fr/function.gettext.php]gettext[/url](), qui constitue le standard en la matière ?
1. [b]Création de l'arborescence[/b], par exemple
[code]./locale
|-- de
| `-- LC_MESSAGES
|-- en
| `-- LC_MESSAGES
`-- fr
`-- LC_MESSAGES[/code]
2. [b]Création des fichier .po (source)[/b] dans chaque dossier LC_MESSAGES. Ils ont pour nom le nom du «domaine de l'application» (façon d'identifier les tables de traduction), par exemple «MonAppli.po». Ces fichiers sont des paires de lignes de cette forme :
[code]msgid "Identifiant de la chaîne à traduire"
msgstr "Valeur de la chaîne traduite"[/code]
En identifiant on utilise systématiquement la chaîne non traduite tout simplement, exemple :[code]msgid "Hello %s !"
msgstr "Bonjour %s !"
msgid "Bye bye :)"
msgstr "Au revoir :)"[/code]
3. [b]Compilation des fichiers .po en .mo[/b]. C'est ce qui donne au système sa performance ;)
Pour chaque fichier il suffit d'utiliser msgfmt :
[code]$ msgfmt -o ./locale/fr/LC_MESSAGES/MonAppli.mo ./locale/fr/LC_MESSAGES/MonAppli.po[/code]
J'utilise personnellement cette commande qui va me compiler tous les fichiers .po d'un dossier (récursivement) avec le même nom en .mo :[code]$ find ./locale -name *.po | while read f; do msgfmt -o $(echo $f | sed 's/po$/mo/') $f && echo "OK $f" || echo "FAIL $f"; done[/code]
4. [b]Utilisation[/b]. On va simplement reprendre l'exemple de la doc :)
[php]<?php
// Choix de la langue
setlocale(LC_ALL, 'fr');
// Spécifie la localisation des tables de traduction (le dossier contenant l'arborescence) pour le domaine indiqué
bindtextdomain("MonAppli", "./locale");
// Choix du domaine
textdomain("MonAppli");
// La traduction est cherché dans ./locale/fr/LC_MESSAGES/MonAppli.mo
// Affichage d'un message de test
printf(gettext("Hello %s !") . "\n", getenv('USER'));
// Or use the alias _() for gettext()
echo _("Bye bye :)") . "\n";
?>[/php]
[b][u]Avantages[/u][/b]
[list]
[*]La localisation d'une appli non localisée au départ est très simple (cf. mon Post-Scriptum).
[*]On utilise la méthode standard GNU, ce qui signifie qu'un éventuel portage ne posera jamais le moindre problème.
[*]On utilise la richesse de gettext, pour en avoir une idée jeter un oeil par exemple à la fonction [url=http://fr3.php.net/manual/fr/function.ngettext.php]ngettext[/url](), comment gérer aussi simplement les pluriels avec une autre méthode ? ;)
[*]On a une performance accrue (utilisation de la RAM, et rapidité de la traduction amoindries).
[*]L'utilisation est vraiment simplissime avec la fonction _()
[*]La définition de la langue de travail repose sur setlocale(), ce qui localise toute l'application et certaines fonctions comme date() en profiteront du même coup.
[*]On peut gérer plusieurs encodages (des pages en UTF-8, d'autres en ISO-quelquechose, etc...) avec la génération de fichiers .po au bon encodage, et de la fonction [url=http://fr3.php.net/manual/fr/function.bind-textdomain-codeset.php]bind_textdomain_codeset[/url]()[/list]
[b][u]Inconvénients[/u][/b]
[list]
[*]Nécessite de compiler les fichier *.po avant de les envoyer sur le serveur.
[*]Nécessite la présence du module gettext dans la version de PHP (pas vraiment une difficulté puisque c'est activé par défaut)[/list]
[b][u]Localisation d'une appli non prévue au départ[/u][/b]
- Ajouter au début du script les appels à setlocale() (pour changer la langue), [url=http://fr3.php.net/manual/fr/function.bindtextdomain.php]bindtextdomain[/url]() (pour préciser l'emplacement de l'arborescence pour le domaine) et [url=http://fr3.php.net/manual/fr/function.textdomain.php]textdomain[/url]() (pour préciser le domaine).
- Encadrer les chaînes à localiser avec [url=http://fr3.php.net/manual/fr/function.gettext.php]_[/url]()
- Utiliser le programme xgettext qui va générer un modèle de fichier .po (il va détecter les chaînes localisées). Par exemple la commande appliquée à notre script[code]xgettext MonAppli.php --from-code=UTF-8[/code]Va donner le fichier messages.po[code]# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-03-24 11:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <
[email protected]>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: appli.php:15
#, php-format
msgid "Hello %s !"
msgstr ""
#: appli.php:18
msgid "Bye bye :)"
msgstr ""[/code]
- Dupliquer ce fichier dans l'arborescence de ./locale
- Traduire
- Compiler (avec la commande que j'ai donnée qui va tout compiler récursivement).
- L'application est intégralement traduire :)
[edit=1]Ajout des liens[/edit]