Subversion Repositories Applications.framework

Rev

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