Subversion Repositories Applications.framework

Rev

Rev 331 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
183 jpm 1
<?php
2
// declare(encoding='UTF-8');
3
/**
4
 * I18n permet de traduire une application à partir de données stockées dans des fichiers ini.
5
 * Si vous souhaitez utiliser le fonctionnement par défaut vous devrez :
6
 * - déposer les fichiers ini dans le dossier définit par la variable de config "chemin_i18n".
7
 * - nommer les fichiers selon la forme "locale.ini" (Ex.: fr.ini ou fr_CH.ini ).
8
 *
226 jpm 9
 * Elle offre l'accès en lecture seule aux paramètres des fichiers ini.
183 jpm 10
 * C'est une Singleton. Une seule classe de traduction peut être instanciée par Application.
11
 *
226 jpm 12
 * @category	PHP 5.2
331 jpm 13
 * @package		Framework
226 jpm 14
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
241 jpm 15
 * @copyright	Copyright (c) 2010, Tela Botanica (accueil@tela-botanica.org)
331 jpm 16
 * @license		http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
17
 * @license		http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
232 jpm 18
 * @since 		0.3
331 jpm 19
 * @version		$Id: I18n.php 492 2016-11-21 16:14:56Z mathias $
226 jpm 20
 * @link		/doc/framework/
183 jpm 21
 */
22
class I18n {
23
	/** Format de traduction utilisant les fichier .ini */
24
	const FORMAT_INI = '.ini';
25
 
26
	/** Instance de la classe pointant sur elle même (pour le pattern singleton) */
27
	private static $instance = null;
28
 
29
	/** Fichiers de traduction disponibles. */
30
	private static $traductions = array();
31
 
32
	/** Langue courrante utilisée par l'application. */
33
	private static $langue = null;
34
 
241 jpm 35
	/** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
274 jpm 36
	private static $parametres_obligatoires = array('chemin_i18n', 'i18n_url_parametre', 'i18n_langue_defaut', 'debogage');
241 jpm 37
 
183 jpm 38
	private function __construct() {
241 jpm 39
		Config::verifierPresenceParametres(self::$parametres_obligatoires);
183 jpm 40
		self::trouverLangue();
41
	}
42
 
43
	/**
44
	 * Accesseur pour la valeur d'une traduction
45
	 * @param string $param le nom du paramètre
46
	 * @return string la valeur du paramètre
47
	 */
48
	public static function get($identifiant, $langue = null) {
49
		self::verifierCreationInstance();
50
		$texte = '';
51
 
52
		// Récupération de la langue actuellement demandée
53
		$langue_a_charger = self::$langue;
54
		if (!is_null($langue)) {
55
			$langue_a_charger = $langue;
56
		}
57
 
58
		if (!isset(self::$traductions[$langue_a_charger])) {
59
			// Tentative de chargement du fichier de traduction
60
			$chargement = self::charger($langue_a_charger);
61
			if ($chargement === false) {
62
				$m = "Le fichier d'i18n pour la langue '$langue_a_charger' demandée n'a pas été trouvé.";
63
				self::ajouterErreur($m);
64
			}
65
		}
66
 
67
		// Recherche de la langue dans le tableau des traductions
68
		if (isset(self::$traductions[$langue_a_charger]) && self::$traductions[$langue_a_charger] !== false) {
69
			// Recherche de la traduction demandée
70
			$valeur = self::getValeur($identifiant, self::$traductions[$langue_a_charger]);
71
			if ($valeur !== false) {
72
				$texte = $valeur;
73
			} else {
74
				$m = "Le traduction n'existe pas pour l'identifiant '$identifiant' demandé.";
75
				self::ajouterErreur($m);
76
			}
77
		}
78
 
79
		return $texte;
80
	}
81
 
82
	/**
83
	 * Charge un fichier ini dans le tableau des paramètres de l'appli
84
	 * @param string $fichier_ini le nom du fichier à charger
85
	 * @return boolean true, si le fichier a été trouvé et correctement chargé, sinon false.
86
	 */
87
	public static function charger($langue, $fichier = null, $format = self::FORMAT_INI) {
88
		self::verifierCreationInstance();
89
		$ok = false;
90
 
91
		// Création du chemin vers le fichier de traduction par défaut
92
		if (is_null($fichier)) {
93
			$fichier = Config::get('chemin_i18n').$langue.$format;
94
		}
95
 
96
		// Chargement
97
		if ($format == self::FORMAT_INI) {
98
			$ok = self::chargerFichierIni($fichier, $langue);
99
		} else {
100
			$m = "Le format '$format' de fichier de traduction n'est pas pris en compte par le Framework.";
101
			self::ajouterErreur($m);
102
		}
103
 
104
		return $ok;
105
	}
106
 
107
	/**
108
	 * Définit la langue utiliser pour rechercher une traduction.
109
	 * @param string $fichier_ini le nom du fichier à charger
110
	 * @return array le fichier ini parsé
111
	 */
112
	public static function setLangue($langue) {
113
		self::verifierCreationInstance();
114
		self::$langue = $langue;
115
	}
116
 
117
	/**
118
	 * Renvoie la valeur demandé grâce une chaine de paramètres
119
	 * @param string $param la chaine identifiante
120
	 * @param array $i18n le tableau de traductions
121
	 * @return mixed la valeur correspondante à la chaine identifiante si elle est trouvée, sinon false.
122
	 */
123
	private static function getValeur($param, $i18n) {
124
		if ($param === null) {
125
			return false;
126
		} else {
127
			if (isset($i18n[$param])) {
128
				return $i18n[$param];
129
			} else if (strpos($param, '.') !== false) {
130
				$pieces = explode('.', $param, 2);
131
				if (strlen($pieces[0]) && strlen($pieces[1])) {
132
					if (isset($i18n[$pieces[0]])) {
133
					   if (is_array($i18n[$pieces[0]])) {
134
					   		return self::getValeur($pieces[1], $i18n[$pieces[0]]);
135
					   }
136
					}
137
				}
138
			} else {
139
				return false;
140
			}
141
		}
142
	}
143
 
144
	/**
145
	 * Parse le fichier ini donné en paramètre
146
	 * @param string $fichier_ini nom du fichier ini à parser
147
	 * @param string $langue la langue correspondant au fichier
148
	 * @return boolean true si le chargement c'est bien passé, sinon false.
149
	 */
150
	private static function chargerFichierIni($fichier_ini, $langue) {
151
		self::$traductions[$langue] = false;
152
		if (file_exists($fichier_ini)) {
186 jpm 153
			$ini = parse_ini_file($fichier_ini, true);
154
			$ini = self::analyserTableauIni($ini);
155
			self::$traductions[$langue] = $ini;
183 jpm 156
		}
157
		return (self::$traductions[$langue] === false) ?  false : true;
158
	}
159
 
160
	/**
186 jpm 161
	 * Analyse un tableau de traductions pour évaluer les clés.
162
	 * @param array $i18n le tableau de traductions
163
	 * @return array le tableau analysé et modifié si nécessaire.
164
	 */
165
	private static function analyserTableauIni($i18n = array()) {
166
		//ATTENTION : il est important de passer la valeur par référence car nous la modifions dynamiquement dans la boucle
167
		foreach ($i18n as $cle => &$valeur) {
168
			if (is_array($valeur)) {
169
				$i18n[$cle] = self::analyserTableauIni($valeur);
170
			} else {
492 mathias 171
				// @WARNING déconne avec eFlore dans Wordpress, pour on ne sait quelle raison
172
				//$i18n = self::evaluerCle($i18n, $cle, $valeur);
186 jpm 173
			}
174
		}
175
		return $i18n;
176
	}
177
 
178
	/**
179
	 * Dans le cas des chaines de traduction à sous clé (ex.: cle.souscle), cette méthode
180
	 * évalue les valeurs correspondantes et créée les sous tableaux associés.
181
	 * @param array $i18n tableau de traductions (par référence)
182
	 * @param string $cle la cle dans le tableau
183
	 * @param string $valeur la valeur à affecter
184
	 */
185
	private static function evaluerCle($i18n, $cle, $valeur) {
186
		if (strpos($cle, '.') !== false) {
187
			unset($i18n[$cle]);
188
			$pieces = explode('.', $cle, 2);
189
			if (strlen($pieces[0]) && strlen($pieces[1])) {
190
				if (isset($i18n[$pieces[0]]) && !is_array($i18n[$pieces[0]])) {
191
					$m = "Ne peut pas créer de sous-clé pour '{$pieces[0]}' car la clé existe déjà";
192
					trigger_error($m, E_USER_WARNING);
193
				} else {
194
					$i18n[$pieces[0]][$pieces[1]] = $valeur;
195
					$i18n[$pieces[0]] = self::evaluerCle($i18n[$pieces[0]], $pieces[1], $valeur);
196
				}
197
			} else {
198
				$m = "Clé invalide '$cle'";
199
				trigger_error($m, E_USER_WARNING);
200
			}
201
		} else {
202
			$i18n[$cle] = $valeur;
203
		}
204
		return $i18n;
205
	}
206
 
207
	/**
183 jpm 208
	 * Cherche l'information sur la langue demandée par l'application
209
	 */
210
	private static function trouverLangue() {
211
		if (isset($_GET[Config::get('i18n_url_parametre')])) {
212
			self::$langue = $_GET[Config::get('i18n_url_parametre')];
213
		} else {
214
			self::$langue = Config::get('i18n_langue_defaut');
215
		}
216
	}
217
 
218
	/**
219
	 * Vérifie si l'instance de classe à été crée, si non la crée
220
	 */
221
	private static function verifierCreationInstance() {
222
		if (empty(self::$instance)) {
223
			self::$instance = new I18n();
224
		}
225
	}
226
 
227
	/**
228
	 * Ajouter une message d'erreur
229
	 */
230
	private static function ajouterErreur($m, $e = E_USER_WARNING) {
274 jpm 231
		if (Config::get('debogage') === true) {
183 jpm 232
			trigger_error($m, $e);
233
		}
234
	}
230 jpm 235
}
492 mathias 236
?>