31.3. Utiliser les adaptateurs de traduction

La prochaine étape est d'utiliser l'adaptateur dans votre code.

Exemple 31.1. Exemple de code PHP monolingue

<?php
print "Exemple\n";
print "=======\n";
print "Ceci la ligne une\n";
print "Aujourd'hui nous sommes le " . date("d/m/Y") . "\n";
print "\n";
print "Correction de la langue ceci est la ligne deux\n";
?>

L'exemple ci-dessus montre l'affichage sans le support de traduction. Vous écrivez probablement votre code dans votre langue maternelle. Généralement vous devez traduire non seulement l'affichage, mais également les messages d'erreur et les messages de log.

La prochaine étape est d'inclure Zend_Translate dans votre code existant. Naturellement il est beaucoup plus facile si vous écrivez dès le début votre code en utilisant Zend_Translate au lieu de modifier votre code après.

Exemple 31.2. Exemple de code PHP multilingue

<?php
require_once("Zend/Translate.php");

$translate = new Zend_Translate('gettext', '/mon/chemin/source-de.mo', 'de');
$translate->addTranslation('//mon/chemin/fr-source.mo', 'fr');

print $translate->_("Exemple")."\n";
print "=======\n";
print $translate->_("Ceci la ligne une")."\n";
printf($translate->_("Aujourd'hui nous sommes le %1\$s") . "\n", date("d/m/Y"));
print "\n";

$translation->setLanguage('fr');
print $translate->_("Correction de la langue ceci est la ligne deux") . "\n";
?>

Maintenant regardons plus attentivement ce qui a été fait et la façon d'intégrer Zend_Translate dans votre code.

Créer un nouvel objet de traduction et définir l'adapteur de base :

<?php
require_once("Zend/Translate.php");

$translate = new Zend_Translate('gettext', '/chemin/vers/source-de.mo', 'de');
?>

Dans cet exemple nous avons décidé d'utiliser l'adaptateur Gettext. Nous plaçons notre fichier source-de.mo dans le dossier /chemin/vers. Le fichier gettext incluera la traduction allemande. Et nous avons également ajouté un autre fichier de langue pour le français.

L'étape suivante est d'envelopper toutes les chaînes qui doivent être traduites. L'approche la plus simple est d'avoir seulement des chaînes simples ou des phrases comme ceci :

<?php
print $translate->_("Exemple")."\n";
print "=======\n";
print $translate->_("Ceci la ligne une")."\n";
?>

Quelques chaînes ne sont pas nécessairement traduites. La ligne séparatrice est toujours la même ligne séparatrice, même dans d'autres langues.

Avoir des valeurs de données intégrées dans une chaîne de traduction est également supporté par l'utilisation des paramètres inclus.

<?php
printf($translate->_("Aujourd'hui nous sommes le %1\$s") . "\n", date("d/m/Y"));
?>

Au lieu de print(), utiliser la fonction printf() et remplacer tous les paramètres avec des éléments de type %1\$s. Le premier est %1\$s, le second %2\$s, et ainsi de suite. De cette façon une traduction peut être faite sans savoir la valeur exacte. Dans notre exemple, la date est toujours le jour actuel, mais la chaîne peut être traduite sans connaissance du jour actuel.

Chaque corde est identifiée dans le stockage de traduction par un identificateur de message. Vous pouvez employer l'identificateur de message au lieu des chaînes dans votre code, comme ceci :

<?php
print $translate->_(1)."\n";
print "=======\n";
print $translate->_(2)."\n";
?>

Mais faire ceci a plusieurs inconvénients :

Vous ne pouvez pas voir ce que votre code devrait afficher juste en regardant votre code.

En outre vous obtiendrez des problèmes si quelques chaînes ne sont pas traduites. Vous devez toujours imaginer comment la traduction fonctionne. Premièrement Zend_Translate vérifie si la langue choisie a une traduction pour l'identificateur de message ou la chaîne fournie. Si aucune chaîne de traduction n'a été trouvée, elle se reporte sur la langue suivante comme définie dans Zend_Locale. Ainsi le "de_AT" devient seulement "de". S'il n'y a aucune traduction trouvée pour le "de" non plus, alors le message original est retourné. De cette façon vous avez toujours un affichage, au cas où la traduction de message n'existerait pas dans votre stockage des messages. Zend_Translate ne lève jamais d'erreur ou d'exception en traduisant les chaînes.

31.3.1. Structures des source de traduction

L'étape suivante est la création des sources de traduction pour les multiples langues vers lesquelles vous traduisez. Chaque adaptateur est créé de sa propre manière comme décrit ici. Mais il y a quelques dispositifs généraux qui sont appropriés pour tous les adaptateurs.

Vous devrez savoir où stocker vos fichiers sources de traduction. Avec Zend_Translate vous n'êtes lié par aucune restriction. Les structures suivantes sont préférables :

  • Structure de source unique

    /application
    /languages
      lang.en
      lang.de
    /library
    

    Positif : Tous les fichiers sources pour chacune des langues peuvent être trouvés dans un dossier. Aucun fractionnement des fichiers.

  • Source structurée par langue

    /application
    /languages
      /en
        lang.en
        other.en
      /de
        lang.de
        other.de
    /library
    

    Positif : chaque langue est située dans un dossier. La traduction est facilitée car un seul dossier doit être traduit par une équipe de langue. En outre l'utilisation des dossiers multiples est transparente.

  • Source structurée par application

    /application
      /languages
        lang.en
        lang.de
        other.en
        other.de
    

    Positif : tous les fichiers sources pour chacune des langues peuvent être trouvés dans un seul dossier. Aucun fractionnement des fichiers.

    Négatif : avoir les dossiers multiples pour la même langue est problématique.

  • Source structurée par Gettext

    /languages
      /de
        /LC_MESSAGES
          lang.mo
          other.mo
      /en
        /LC_MESSAGES
          lang.mo
          other.mo
    

    Positif : de vieilles sources de gettext peuvent être utiliser sans changer la structure.

    Negative: avoir des dossiers de dossiers peut être embrouillant pour les personnes qui n'ont pas utilisé le gettext avant.

  • Source structurée par fichier

    /application
      /models
        mymodel.php
        mymodel.de
        mymodel.en
      /views
      /controllers
        mycontroller.de
    /document_root
      /images
      /styles
      .htaccess
      index.php
      index.de
    /library
      /Zend
    

    Positif : chaque fichier est lié à sa propre source de traduction. source.

    Négatif : de multiples petits fichiers source de traduction rendent plus dur la traduction. En outre chaque fichier doit être ajouté comme source de traduction.

Les fichiers source uniques et structurés par langue sont les plus utilisés pour Zend_Translate.

Maintenant, que nous connaissons la structure que nous voulons avoir, nous devons créer nos fichiers source de traduction.

31.3.2. Créer des fichiers source de type tableau

Les fichiers source de type tableau sont simplement des tableaux. Mais vous devez les définir manuellement parce qu'il n'y a aucun outil pour cela. Mais parce qu'ils sont si simples, c'est la manière la plus rapide de rechercher des messages si votre code fonctionne comme prévu. C'est généralement le meilleur adaptateur pour démarrer avec des systèmes multilingues.

$english = array('message1' => 'message1',
                 'message2' => 'message2',
                 'message3' => 'message3');
$german = array('message1' => 'Nachricht1',
                'message2' => 'Nachricht2',
                'message3' => 'Nachricht3');

$translate = new Zend_Translate('array', $english, 'en');
$translate->addTranslation($deutsch, 'de');

31.3.3. Créer des fichiers source Gettext

Des fichiers source Gettext sont créés par la bibliothèque GNU gettext. Il y a plusieurs outils libres disponibles qui peuvent analyser vos fichiers de code et créent les fichiers source nécessaires de gettext. Ces fichiers se termine par *.mo et ce sont des fichiers binaires. Un outil freeware pour créer ces fichiers est poEdit. Cet outil vous aide également pour le processus de traduction lui-même.

// Les fichiers mo sont créés et déjà traduits
$translate = new Zend_Translate('gettext', 'chemin/vers/english.mo', 'en');
$translate->addTranslation('chemin/vers/german.mo', 'de');

Comme vous pouvez le voir, les adaptateurs sont utilisés exactement de la même manière, avec seulement juste une petite différence. Changer "array" en "gettext". Toutes autres utilisations sont exactement les mêmes qu'avec tous autres adaptateurs. Avec l'adaptateur de gettext vous devez plus faire attention à la structure des répertoires, au "bindtextdomain" et au "textdomain". Fournissez juste le chemin et le nom de fichier à l'adaptateur.

[Note] Note

Vous devriez toujours employer UTF-8 comme source d'encodage. Autrement vous aurez des problèmes si vous employez deux encodages différents. Par exemple, si un de vos fichiers source est encodé en ISO-8815-11 et un fichier différent est codé avec CP815. Vous pouvez utiliser seulement un encodage pour votre fichier source, ainsi une de vos langues ne s'affichera probablement pas correctement.

UTF-8 est un format portable qui supporte toutes les langues. Si vous employez l'encodage UTF-8 pour toutes les langues, vous éliminez le problème des encodages incompatibles.

31.3.4. Créer des fichiers source TMX

Les fichiers source TMX sont les nouveaux standard industriels. Ils ont l'avantage d'être des fichiers XML et ainsi ils sont lisibles par chaque éditeur de fichier et naturellement ils sont lisibles pour l'homme. Vous pouvez ou créer des fichiers TMX manuellement avec un éditeur de texte, ou vous pouvez utiliser un outil. Mais les la plupart des programmes actuellement disponible pour développer des fichiers source TMX ne sont pas freeware.

Exemple 31.3. Exemple de fichier TMX

<?xml version="1.0" ?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
 <header creationtoolversion="1.0.0" datatype="winres" segtype="sentence" adminlang="en-us" srclang="de-at" o-tmf="abc" creationtool="XYZTool" >
 </header>
 <body>
  <tu tuid='message1'>
   <tuv xml:lang="de"><seg>Nachricht1</seg></tuv>
   <tuv xml:lang="en"><seg>message1</seg></tuv>
  </tu>
  <tu tuid='message2'>
   <tuv xml:lang="en"><seg>message2</seg></tuv>
   <tuv xml:lang="de"><seg>Nachricht2</seg></tuv>
  </tu>
$translate = new Zend_Translate('tmx', 'chemin/vers/mytranslation.tmx', 'en');
// TMX peut contenir différentes langues dans le même fichier

Les fichiers TMX peuvent avoir plusieurs langues dans le même fichier. Toutes autres langues incluses sont ajoutées automatiquement, ainsi vous n'avez pas à appeler addLanguage().

31.3.5. Créer des fichiers source CSV

Les fichiers source CSV sont petits et lisibles pour l'homme. Si vos clients veulent eux-mêmes traduire, vous utiliserez probablement l'adaptateur CSV.

Exemple 31.4. Exemple avec un fichier CSV

#Exemple de fichier csv
message1;Nachricht1
message2;Nachricht2
$translate = new Zend_Translate('csv', 'chemin/vers/mytranslation.csv', 'de');
$translate->addTranslation('chemin/vers/other.csv', 'fr');

Le séparateur standard des fichiers CSV est le signe ';'. Mais celui-ci n'est pas obligatoire. Avec l'option 'separator' vous pouvez décider d'utiliser un autre signe de séparation.

Si vous devez avoir le signe séparateur dans votre traduction vous devez juste le doubler pour être inclus dans la traduction. Un seul signe séparateur séparera l'origine et les chaînes de traduction et deux signes séparateurs écriront le signe séparateur dans la chaîne. Voir l'exemple suivant :

Exemple 31.5. Exemple avec un fichier CSV (2)

#Example csv file
# original 'message,1'
message,,1,Nachricht1
# translation 'Nachricht,2'
message2,Nachricht,,2
# original 'message3,'
message3,,,Nachricht3
$translate = new Zend_Translate('csv', 'chemin/vers/matraduction.csv', 'de', array('separator' => ','));
$translate->addTranslation('chemin/vers/autre.csv', 'fr');

31.3.6. Options pour les adaptateurs

Les options peuvent être utilisées avec tous les adaptateurs. Bien sûr les options sont différentes pour tous les adaptateurs. Vous pouvez mettre des options quand vous créez l'adaptateur. Pour l'instant il y a une option qui est valable pour tous les adaptateurs. 'clear' décide si des données de traduction peuvent être ajoutées à l'existant ou non. Le comportement standard est d'ajouter des nouvelles données de traduction à l'existant. Les données de traduction sont seulement effacées pour la langue choisie. Donc on ne touchera pas aux autres langues.

Vous pouvez régler des options temporaires en utilisant addTranslation($donnees, $locale, array $options = array()) comme troisième paramètre optionel. Ou vous pouvez utiliser la fonction setOptions() pour régler une option.

Exemple 31.6. Utiliser les options de traduction

$options = array('clear' => true);
$translate = new Zend_Translate('csv', 'chemin/vers/matraduction.csv', 'de');
$translate->addTranslation('chemin/vers/autre.csv', 'fr');
... // do something
$translate->addTranslation('chemin/vers/nouvelle.csv', 'fr', $options); // efface et remplace la langue fr