[php5.1] o-loc : classe et backoffice d'internationalisation

Soyez le premier à donner votre avis sur cette source.

Vue 15 365 fois - Téléchargée 995 fois

Description

Ce package comprend 2 outils distincts mais liés.
- la classe oLocale permettant de gérer l'affichage des traducstions sur un site multilingue. Elle se base sur un flux XML ayant une structure simple, mais bien précise. Elle a besoin d'une langue demandée, et d'une langue par défaut (dans les deux cas, la classe les fixe à l'anglais si ces 2 paramètres ne sont pas passés), et d'un chemin où aller chercher les fichiers de traduction. Par défaut, le chemin est 'locales/'. La structure de ce répertoire doit être respectée, par contre.
Si elle ne trouve pas une traduction dans la langue demandée, elle affichera automatiquement la traduction dans la langue par défaut. Elle permet aussi de changer de langue (langue par défaut et langue demandée) en cours de script, sur une même page.
Un exemple d'utilisation basique se situe dans le fichier oloc.example.php.
De toute manière, la classe est simple d'utilisation.
Elle ne possède que 2 méthodes appelables : oLocale::getMsg() permettant d'aller chercher une traduction, et oLocale::getLoc() renvoyant la langue courante.
Et 2 propriétés initialisable : oLocale::LOCALE est la langue courante, oLocale::DEFAULT est la langue par défaut.

- une application back-office pour gérer ses traductions. Elle se lance via le fichier back.office.php. Une aide en ligne sommaire mais complète est disponible sur l'interface.
Ce back-office permet de créer des traductions pour autant de sites que vous le voulez, de gérer des modules de traduction, et des constantes de traduction (chaque message, en fait). Et ce, soit manuellement, soit via l'upload d'un fichier respectant le modèle présent dans le répertoire 'templates/'. Il s'agit d'un fichier Excel.
Le back-office ne supporte que ce template, et un process bien défini : il FAUT utiliser ce template, puis il FAUT utiliser OpenOffice (version 2.3 pour moi, à tester avec d'autres versions) pour sauvegarder ce fichier en HTML (et pas XHTML), et c'est ce fichier HTML obtenu que l'on uploadera dans le back-office. J'ai externalisé tout le process de parsing de fichier, ce qui rend "facile" la création d'un nouveau template si vous désirez changer de process, et donc le parsing à appliquer. Il y a 2 classes pour cela : 'class/class.genparser.php' qui ne devrait pas être touchée, elle gère l'upload et diverses petites choses. Et une classe spécialisée 'class/class.openoffice23htmlparser.php' qui étend genparser. Il vous faudra créer la votre si vous voulez changer de modèle.
Le back-office est livré avec un "site" test, contenant 2 modules, et leurs traductions dans un paquet de langues (Bulgare, Grec, Tchèque, anglais, allemand, français etc...). Vous pouvez donc afficher les traductions, les modifier, etc...afin de tester l'application.
Toute l'interface utilise Ajax (upload mis à part) pour une ergonomie plus agréable.

A noter que pour le moment, je n'ai pas réussi à faire tourner cette application (je parle uniquement du back-office là) sur IE. Il n'y a pas grand chose à modifier mais je n'ai pas encore trouvé l'astuce pour faire ça simplement (IE et le DOM, décidément...).
Testé sur Firefox 2, Opera 9, Flock 1.

Voilà, je pense que c'est tout... ;-)

Source / Exemple :


<?php
/**
Web application localization back-office class
Copyright (C) 2007  Johan Barbier <johan.barbier@gmail.com>

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

  • /
/**
  • @author Johan Barbier <johan.barbier@gmail.com>
  • @version 20071031
  • @desc Web application localization back-office class
  • F R E N C H :
  • PRINCIPE : Ce back-office permet de générer les "locales" nécessaires à une application web localisée. La localisation obtenur se base sur la classe oLocale présente dans le répertoire class/ du back-office. Cette classe, si elle ne trouve pas de traduction pour une langue donnée utilisera la langue fixée en tant que langue par défaut à la place.
  • Le répertoire de travail des "locales" pour la classe oLocale présente sur un site est "locales/"..
  • Le répertoire de travail des "locales" pour le back-office est "websites/". La hiérarchie de ce répertoire est la suivante : websites/nom_site_web/locales/code_pays/modulex.xml
  • Chaque racine de site (websites/nom_site_web/locales/) possède automatiquement un répertoire default (au même niveau que le répertoire code_pays) contenant la définition des modules et des constantes attribuées au module, sous forme de fichier xml. x modules = x fichiers.
  • C'est ce répertoire "locales/" sous le "site" qu'il faut copier sur le serveur web, sous le site web de production désiré.
  • Pour créer une localisation, il faut commencer par créer un site web (website). Puis le sélectionner dans la liste déroulante des sites web. Toute autre manipulation passe nécessairement par la sélection d'un site web dans la liste déroulante!
  • Ensuite, en travaillant MANUELLEMENT :
  • On y ajoute ensuite une langue. A ce moment là, la langue est présente dans les listes déroulantes des langues disponibles et des langues de référence disponibles.
  • On y ajoute un module. De même, le module créé est alors disponible dans la liste déroulante des modules disponibles.
  • On peut alors commencer à travailler :
  • Pour modifier ou afficher une traduction, il faut absolument sélectionner un module, une langue de référence, et une langue de travail.
  • Ceci fait, la liste des constantes avec les traductions dans les 2 langues sélectionnées s'affiche.
  • Un champ de saisie permet de saisir une nouvelle constante. Attention à bien respecter les règles énoncées dans le paragraphe MODULES ci-dessous.
  • Si la traduction d'une constante pour une des langues n'est pas disponible, s'affiche alors à la place "NO TRANSLATION FOUND".
  • Les champs de traduction des 2 langues sont modifiables. Toute modification est répercutée sur le "blur" du champ (à la sortie du champ).
  • NB : Toujours bien penser à vérifier que l'on est sur le bon site avant de faire quoi que ce soit!
  • En travaillant par UPLOAD DE FICHIER :
  • Il faut toujours créer un site, puis le sélectionner.
  • Ceci fait, il faut prendre le fichier de traduction qui doit etre conforme au modèle présent dans le répertoire template/, et l'ouvrir avec Open Office. Là, l'enregistrer en tant que fichier HTML (et pas XHTML).
  • Enfin, l'uploader dans le champ consacré du back-office. Le traitement peut-être long selon la taille du fichier.
  • Une fois que le back-office a fini d'intégtrer ce fichier, il affichera un message "Fichier intégré avec succès".
  • On peut alors aller afficher les modules, traductions créés.
  • LANGUES : les langues seront préférablement utilisées avec le code ISO 3166-1 alpha 3 du pays. Lors de l'ajout de traductions via le fichier modèle, si les pays ne sont pas renseignés ainsi, la classe va tenter de retrouver ce code via la fonction countries/get.alpha.cn.php. S'il ne le trouve pas, il utilisera le nom présent dans le fichier. Attention à l'encodage en cas de caractères spécieux, dans ce cas! Le mieux étant de vérifier la bonne écriture des pays dans le fichier fourni.
  • WEBSITES : un simple nom de répertoire valide suffira à la création d'un "website" dans le back-office
  • MODULE : une chaîne alpha normale, sans caractère spéciaux et surtout pas d'underscore.
  • CONSTANTES : les constantes doivent être préfixées par le nom du module auquel elles appartiennent, suivi d'un underscore, puis de n'importe quelle chaîne valide pour le nom d'un élément xml (éviter les caractères spéciaux, donc).
*
  • E N G L I S H :
  • PURPOSE : This back-office allows you to generate localizations needed for a web application. The localization will be used by the oLocale class, see the given example on how to use this latter.
  • Work folder for localization used by oLocale class is 'locales/'.
  • Work folder for "locales" used by the back-office is 'websites/'. Structure of this folder is as follows : 'websites/website_name/locales/country_code/module_X.xml'
  • Root of a given website (websites/website_name/locales/) is automatically given a 'default/' folder (same level as the 'country_code/' folders) in which you find the module's and constants' definition as an xml file. X modules = X xml files.
  • It is THIS 'locales/' folder you'll have to copy to your localized website ('default/' is of no use on your website, however).
  • To create a localization, you must first create a website. Then, you have to select it in the dedicated combo list. Every thing you do NEEDS a website to be selected first.
  • Then, if working MANUALLY :
  • You add a language. Thie language will then be available in the list of available base languages and reference languages.
  • You add a module. Just as above, the new module will then be available in the list of available modules for this website.
  • You can now start working :
  • In order to display, modify or create a given translation, you must select a module, a base language, and a reference language.
  • Once done, the list of constants and translations is displayed.
  • An input allows you to create a new constant. Please respect the rules given in the chapter MODULE of this help.
  • If a translation is not available, 'NO TRANSLATION FOUND' is displayed.
  • Translations for both selected languages can be modify. Just click on the cell. Every modification is saved on the 'blur' event of the cell (when you click out of the cell).
  • NOTE: Just be SURE you are on the correct website before doing anything!
  • If working by UPLOADING A FILE :
  • You still have to create your website, and then select it.
  • Once done, take your translation file which must be compliant to the one given as an example in the 'templates/' folder. It's an Excel file. With this version of the back-office, it is the only available template (you can build your own, though, you'll find everything needed to do so in the 'class/class.genparser.php' and 'class/class.openoffice23htmlparser.php' files). You must open it in OpenOffice 2.3 and save it as an HTML file (I insist : HTML, not XHTML).
  • Finally, upload this HTML file in the back-office. It can take a while, depending on the size of your file.
  • When the back-office is done with the file, it will display a message "File successfully processed", so you will know.
  • You can then display your uploaded translations.
  • LANGUAGES : for languages name, you should use the ISO 3166-1 Alpha3 code, it's a good one! When you add translations via an uploaded file, if languages name does not use this format, the back-office will try to find it. It uses for that what you will find in the 'countries/' folder : an xml file and a function. If it cannot find it, it will use the name found in the file. In that case, be careful about special characters in the name, such as accents...it can be a problem while creating a folder with this name.
  • WEBSITES : a simple valid folder name will be ok.
  • MODULE : a normal string, again, without any underscores in it!
  • CONSTANTES : constants must be prefixed by their module name followed by an underscore (as you will see in the example file in the 'templates/' folder). Then, any xml valid string for tagname.
  • /
class backoffice { /**
  • Local website path
*
  • @var string
  • /
private $sPathLocale; /**
  • Stored available languages
*
  • @var ArrayIterator
  • /
private $oStoredLanguages; /**
  • Stored available modules
*
  • @var ArrayIterator
  • /
private $oStoredModules; /**
  • Stored available websites
  • Not used at the time. Might be useful later.
*
  • @var ArrayIterator
  • /
private $oStoredWebsites; /**
  • @desc Constructor. Will initialize backoffice::$sPathLocale property
*
  • @param string (optional) $sPathLocale
  • /
public function __construct($sPathLocale = null) { $this->oStoredWebsites = new ArrayIterator(self::getWebsites()); if(!is_null($sPathLocale)) { $sPathLocale .= '/locales'; if(!is_dir(PATH_ROOT.'websites/'.$sPathLocale)) { throw new boException(str_replace('__PATH__', $sPathLocale, boException::_MISSING_LOCALE_PATH_)); } $this->sPathLocale = PATH_ROOT.'websites/'.$sPathLocale.'/'; if(!is_dir($this->sPathLocale.'default')) { mkdir($this->sPathLocale.'default', 0755); } } } /**
  • @desc Just creates the folder 'websites' if not present and returns its contents
*
  • @return array : websites available
  • /
public static function getWebsites() { if(!is_dir(PATH_ROOT.'websites')) { mkdir(PATH_ROOT.'websites', 0755); } return self::getDir(PATH_ROOT.'websites'); } /**
  • @desc Returns the contents of a directory
*
  • @param string $sDir : directory to list
  • @return array : contents of the directory
  • /
private static function getDir($sDir) { $aDir = scandir($sDir); $aDir = array_diff($aDir, array('.', '..')); return $aDir; } /**
  • @desc Initializes available modules and languages
  • @return void
*
  • /
public function init() { $this->getLanguages(); $this->getModules(); } /**
  • @desc Gets available languages
*
  • @return ArrayIterator
  • /
public function getLanguages() { if(is_null($this->sPathLocale)) { return new ArrayIterator(); } $aDir = self::getDir($this->sPathLocale); $aStoredLanguages = array(); foreach($aDir as $sDir) { if($sDir !== 'default' && is_dir($this->sPathLocale.$sDir)) { $aStoredLanguages[] = $sDir; } } return $this->oStoredLanguages = new ArrayIterator($aStoredLanguages); } /**
  • @desc Gets available modules
*
  • @return ArrayIterator
  • /
public function getModules() { if(is_null($this->sPathLocale)) { return new ArrayIterator(); } $aDir = self::getDir($this->sPathLocale.'default'); $aStoredModules = array(); foreach($aDir as $sDir) { $sDir = substr($sDir, 0, strrpos($sDir, '.')); $aStoredModules[] = $sDir; } return $this->oStoredModules = new ArrayIterator($aStoredModules); } /**
  • @desc Builder method for translations list
*
  • @param string $sMod : mdoule asked for
  • @param string $sLng : base language asked for
  • @param string $sRef : reference language asked for
  • @return array : the list of translations for this module, and these languages
  • /
public function getTranslationsList($sMod = null, $sLng = null, $sRef = null) { if((!$this->oStoredLanguages instanceof ArrayIterator) || (!$this->oStoredModules instanceof ArrayIterator)) { $this->init(); } $aMessages = array(); $aMessages['REF'] = $this->loopOnParameters($sMod, $sRef); $aMessages['LNG'] = $this->loopOnParameters($sMod, $sLng); return $aMessages; } /**
  • @desc Loops on constants in module asked for, and languages
  • I have made available the possibility to retrieve translations for several modules, even if I do not use it in the current backoffice. I have tried, but it is a bit confusing then. Easy to extend, so.
*
  • @param string $sMod : module asked for
  • @param string $sLng : current languages on which we loop
  • @return array : list of translations for modules and languages asked for
  • /
private function loopOnParameters($sMod, $sLng) { $aMessages = array(); if(!is_null($sMod)) { if(!is_null($sLng)) { $aMessages[$sLng] = $this->getTranslationList($sMod, $sLng); } else { foreach($this->oStoredLanguages as $sLng) { $aMessages[$sLng] = $this->getTranslationList($sMod, $sLng); } } } else { foreach($this->oStoredModules as $sMod) { if(!is_null($sLng)) { if(empty($aMessages[$sLng])) { $aMessages[$sLng] = array(); } $aMessages[$sLng] = array_merge($aMessages[$sLng], $this->getTranslationList($sMod, $sLng)); } else { foreach($this->oStoredLanguages as $sLng) { if(empty($aMessages[$sLng])) { $aMessages[$sLng] = array(); } $aMessages[$sLng] = array_merge($aMessages[$sLng], $this->getTranslationList($sMod, $sLng)); } } } } return $aMessages; } /**
  • @desc Actually fetches list of translation, called by backoffice::loopOnParamaters
*
  • @param string $sMod : current module
  • @param string $sLng : current language
  • @return array : list of translations for this module and this language
  • /
private function getTranslationList ($sMod, $sLng) { $aMessages = array(); $oDefaultXml = simplexml_load_file($this->sPathLocale.'default/'.$sMod.'.xml'); if(file_exists($this->sPathLocale.'/'.$sLng.'/'.$sMod.'.xml')) { $oXml = simplexml_load_file($this->sPathLocale.'/'.$sLng.'/'.$sMod.'.xml'); } else { $oXml = null; } foreach ($oDefaultXml as $clef => $val) { if(!empty($oXml->$clef)) { $aMessages[$sMod][$clef] = (string)$oXml->$clef; } else { $aMessages[$sMod][$clef] = ''; } } return $aMessages; } /**
  • @desc : Adds a new module
  • Please follow documentation
*
  • @param string $sModule : new module name
  • @param string $sEncoding : new module encoding
  • /
public function addModule($sModule, $sEncoding='UTF-8') { if(empty($sModule)) { throw new boException(boException::_EMPTY_PARAMETER_); } if(file_exists($this->sPathLocale.'default/'.$sModule)) { throw new boException(str_replace('__MOD__', $sModule, boException::_MODULE_ALREADY_EXISTS_)); } if(false !== strpos($sModule, '_')) { throw new boException(boException::_INVALID_UNDERSCORE_); } $sXml = '<?xml version="1.0" encoding="'.$sEncoding.'"?> <constants> </constants>'; file_put_contents($this->sPathLocale.'default/'.$sModule.'.xml', $sXml); } /**
  • @desc : Adds a new website
  • Please follow documentation
*
  • @param string $sWebsite : new website name
  • /
public function addWebsite($sWebsite) { if(empty($sWebsite)) { throw new boException(boException::_EMPTY_PARAMETER_); } if(file_exists(PATH_ROOT.'websites/'.$sWebsite)) { throw new boException(str_replace('__WEB__', $sWebsite, boException::_WEBSITE_ALREADY_EXISTS_)); } mkdir(PATH_ROOT.'websites/'.$sWebsite); mkdir(PATH_ROOT.'websites/'.$sWebsite.'/locales'); } /**
  • @desc : Adds a new language
  • Please follow documentation
*
  • @param string $sLanguage : new language name (best is alpha2 or alpha3)
  • /
public function addLanguage($sLanguage) { if(empty($sLanguage)) { throw new boException(boException::_EMPTY_PARAMETER_); } if(is_dir($this->sPathLocale.$sLanguage)) { throw new boException(str_replace('__LNG__', $sLanguage, boException::_LANGUAGE_ALREADY_EXISTS_)); } mkdir($this->sPathLocale.$sLanguage, 0755); if(!$this->oStoredModules instanceof ArrayIterator) { $this->getModules(); } $oXml = new DOMDocument; foreach($this->oStoredModules as $sMod) { $oXml->load($this->sPathLocale.'default/'.$sMod.'.xml'); $sEncoding = $oXml->encoding; $sXml = '<?xml version="1.0" encoding="'.$sEncoding.'"?> <translations> </translations>'; file_put_contents($this->sPathLocale.'/'.$sLanguage.'/'.$sMod.'.xml', $sXml); } } /**
  • @desc Small method to parse the html elements ID in the list of translations
*
  • @param string $sClef : html element id
  • @return array : an array with the parsed ID (constant name, language name, and module name)
  • /
private function parseInputId($sClef) { $aProps = explode('@', $sClef); $sConst = $aProps[0]; $sLng = $aProps[1]; $sMod = substr($sConst, 0, strpos($sConst, '_')); return array($sConst, $sLng, $sMod); } /**
  • @desc Adds a new constant
*
  • @param string $sConst : new conatnts name
  • @param string $sMod : module owning the new constant
  • /
public function addNewConstant($sConst, $sMod) { if(!file_exists($this->sPathLocale.'default/'.$sMod.'.xml')) { throw new boException(str_replace('__MOD__', $sMod, boException::_DEFAULT_MOD_NOT_FOUND_)); } if(substr($sConst, 0, strpos($sConst, '_')) !== $sMod) { throw new boException(str_replace('__CONST__', $sConst, boException::_INVALID_CONST_)); } $oXml = new DOMDocument(); $oXml->load($this->sPathLocale.'default/'.$sMod.'.xml'); $root = $oXml->firstChild; $elem = $oXml->createElement($sConst); $root->appendChild($elem); $oXml->save($this->sPathLocale.'default/'.$sMod.'.xml'); } /**
  • @desc Deletes a constant in all languages
*
  • @param string $sConst : constant name
  • @param string $sMod : module owning constant
  • /
public function delConstant($sConst, $sMod) { if(!file_exists($this->sPathLocale.'default/'.$sMod.'.xml')) { throw new boException(str_replace('__MOD__', $sMod, boException::_DEFAULT_MOD_NOT_FOUND_)); } if(substr($sConst, 0, strpos($sConst, '_')) !== $sMod) { throw new boException(str_replace('__CONST__', $sConst, boException::_INVALID_CONST_)); } if((!$this->oStoredLanguages instanceof ArrayIterator)) { $this->init(); } $oXml = new DOMDocument(); $oXml->load($this->sPathLocale.'default/'.$sMod.'.xml'); $this->delConstantIn($oXml, $sConst, $sMod, 'default'); foreach($this->oStoredLanguages as $sLanguage) { $oXml->load($this->sPathLocale.$sLanguage.'/'.$sMod.'.xml'); $this->delConstantIn($oXml, $sConst, $sMod, $sLanguage); } } /**
  • @desc Deletes a constant in a given language
*
  • @param DOMDocument $oXml : DOMDocument in which the node must be removed
  • @param string $sConst : Constant to me deleted
  • @param string $sMod : module owning constant
  • @param string $sLanguage : Language in which the constant must be deleted
  • /
private function delConstantIn($oXml, $sConst, $sMod, $sLanguage) { $root = $oXml->firstChild; $xpath = new DOMXPath($oXml); $nodes = $xpath->query('//'.$sConst); if($nodes->length !== 0) { foreach($nodes as $oNode) { if(!is_null($oNode)) { $root->removeChild($oNode); } } $oXml->save($this->sPathLocale.$sLanguage.'/'.$sMod.'.xml'); } } /**
  • @desc Updates a new translation value
*
  • @param string $sClef : element ID
  • @param string $sVal : new translation value
  • @param boolean $bComesFromInput : if sets to true, $sClef does come from HTML, else it comes from uploaded file
  • @param string $sLng : language of the new translation
  • @param string $sMod : module of the new translation
  • /
public function updateValue($sClef, $sVal, $bComesFromInput = true, $sLng = null, $sMod = null) { if(true === $bComesFromInput) { $aProps = $this->parseInputId($sClef); $sConst = $aProps[0]; $sLng = $aProps[1]; $sMod = $aProps[2]; } else { if(is_null($sLng) || is_null($sMod)) { throw new boException(boException::_EMPTY_PARAMETER_); } $sConst = $sClef; } if(true === $bComesFromInput) { $sVal = html_entity_decode(str_replace(genparser::$aCor, array_keys(genparser::$aCor), utf8_decode($sVal))); $sEntities = htmlentities($sVal); } else { $sEntities = $sVal; } $sVal = str_replace(array_keys(genparser::$aCor), genparser::$aCor, $sEntities); $oXml = new DOMDocument(); if(!file_exists($this->sPathLocale.'/'.$sLng.'/'.$sMod.'.xml')) { $oXml->load($this->sPathLocale.'default/'.$sMod.'.xml'); $sEncoding = $oXml->encoding; $sXml = '<?xml version="1.0" encoding="'.$sEncoding.'"?> <translations> </translations>'; $oXml->loadXML($sXml); } else { $oXml->load($this->sPathLocale.'/'.$sLng.'/'.$sMod.'.xml'); } $cdata = $oXml->createCDATASection($sVal); $xpath = new DOMXPath($oXml); $nodes = $xpath->query('//'.$sConst); if($nodes->length !== 0) { foreach($nodes as $oNode) { if(!is_null($oNode->firstChild)) { $oNode->removeChild($oNode->firstChild); } $oNode->appendChild($cdata); } } else { $elem = $oXml->createElement($sConst); $elem->appendChild($cdata); $root = $oXml->firstChild; $root->appendChild($elem); } $oXml->save($this->sPathLocale.'/'.$sLng.'/'.$sMod.'.xml'); } /**
  • @desc Magical getter
*
  • @param string $sProp : property asked for
  • @return mixe : value of the property asked for
  • /
public function __get($sProp) { switch($sProp) { case 'MODULES': return $this->oStoredModules; break; case 'LANGUAGES': return $this->oStoredLanguages; break; case 'WEBSITES': return $this->oStoredWebsites; break; case 'LOCALE_PATH': return $this->sPathLocale; break; default: throw new boException(str_replace('__PROP__', $sLanguage, boException::_PROP_NOT_GETTABLE_)); break; } } } ?>

Conclusion :


NB :
J'ai utilisé la librairie javascript Prototype afin de faciliter la programmation du js.
Dans le répertoire 'countries/' se trouve un fichier XML provenant de Wikipedia et contenant les noms de tous les pays dans 7 langues, ainsi que leurs codes ISO 3166-1 alpha2 et alpha3. Vous trouverez au même endroit une petite fonction à moi permettant d'aller chercher les codes en fonction d'un nom de pays dans ce fichier. Ca peut-être utile (c'est utilisé dans le back-office).

Ce code vient d'être nomminé pour les Innovation Awards de décembre 2007 sur phpclasses.org. Si vous voulez voter pour moi :-) http://www.phpclasses.org/vote.html

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

stu76
Messages postés
186
Date d'inscription
samedi 5 mars 2005
Statut
Membre
Dernière intervention
17 février 2008
-
Juste pour dire BRAVO, nickel comme code je comprends pas tout. Mais je trouve super sympa de ta part de partager un tel code.

++
malalam
Messages postés
10844
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
Salut FhX :-)
Ca fait plaisir de te recroiser!
C'est une très bonne idée ce que tu proposes là! Ce serait plus joli à utiliser en effet, et plus pratique. Je vais me pencher là-dessus, merci :-)
FhX
Messages postés
2350
Date d'inscription
mercredi 13 octobre 2004
Statut
Membre
Dernière intervention
18 avril 2015
3 -
Mala ? J'ai pensé à un truc.

Pourquoi ne pas créer une classe dynamique au moment du parsing XML ? Ou alors, remplir des données dans une classe :

<?xml>
<root>
<translate id="nom_de_la_constante">La traduction qui va avec</translate>
<translate id="nom_de_la_constante_no2">L'autre traduction </translate>
</root>

<?php
// Eventuellement y mettre un Singleton au fesses, c'est plus sympa :D
class Language {
private $tab = array();
private $init = false;

public function setInit($bool) {
$this->init = $bool;
}

public function __set($id, $traduc) {
if ( $this->init) $this->$tab[$id] = $traduc;
}

public function __get($id) {
if ( !$this->init ) return $this->tab[$id];
}

}

// Tu fais ton parsing XML, et tu introduis ton couple ID/traduc dans la classe
// Puis, l'appel ce fait comme ceci :
$lang = new Language(...);
echo $lang->ROOT;
echo $lang->WELCOME_HOME;
echo $lang->KIKOO;

// ET puis voila :) Eventuellement, la classe de langage peut se charger du parsing XML à l'init :
$lang = new Language('fr');
// Et on charge les paramètres français depuis le fichier XML francais.
Encore mieux, si on doit faire du multilangage sur un site :
$lang_fr = new Factory_Language('fr');
$lang_de = new Factory_Language('de');
// Et quand on est dans une classe, on rappèle la factory qui se charge de faire un singleton :
class x {
public function x() {
$lang_fr = new Factory_Language('fr');
// stuf...
}
}

Une solution rapide et assez efficace. Reste à savoir si ca tiens la route sur x00000 de visiteurs à la secondes :)
malalam
Messages postés
10844
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
Il y a un autre truc qui m'a fait penché pour le xml : ma classe gère l'absence de traduction.
Sur les sites internationaux où l'on a utilisé des constantes, si par malheur on oubli une constante dans une trad, on a une belle erreur undefined constant bla bla.
Là, avec ce principe, ce n'est plus le cas : plus d'erreur, et la traduction dans la langue par défaut est affichée (bon, il faut qu'elle soit définie dans la langue par défaut quand même lol, mais c'est une sécurité en plus). D'ailleurs je pense ajouter de ne rien afficher si ni la langue demandée ni la langue par défaut n'ont las traduction demandée (je ne sais plus si je l'ai fait ou non dans oLocale : le backoffice lui, gère ça très bien).

Merci en tous cas :-)
kankrelune
Messages postés
1305
Date d'inscription
mardi 9 novembre 2004
Statut
Membre
Dernière intervention
21 mai 2015
-
j'aime bien... le principe est bon... la réalisation aussi... .. .

J'ai longtemps hésité à utiliser les fichiers xml pour l'internationalisation de mes codes mais je travail avec des constantes et je ne peut me résoudre à les abandoner... lol... non c'est surtout que les constantes ont l'avantage de pouvoir être appelées de partout à tout niveau sans avoir à passer par la globalisation d'une variable, d'un objet ou d'avoir à passer par un singleton... mais le xml me séduit quand même comme format de stockage... plus souple... ou alors il faudrait que la class fasse les define() au moment du chargement du fichier mais je trouve ça moins propre et le problème après c'est que tu peux plus changer de langue en cours de route... .. .

@ tchaOo°

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.