41382cb798a9d6e610d39db806ff683a5854c3ba
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * Gestion des langues et choix de langue
16 * @package SPIP\Core\Langue
18 if (!defined('_ECRIRE_INC_VERSION')) {
24 * Changer la langue courante
26 * Définit la langue utilisée par la langue désignée
27 * si elle fait partie des langues utilisables dans le site.
29 * Cette fonction définit les globales :
30 * spip_lang, spip_lang_rtl, spip_lang_right, spip_lang_left
33 * La langue à utiliser
35 * string : La langue qui a été utilisée si trouvée
36 * false : aucune langue ne correspondait à la demande
38 function changer_langue($lang) {
40 $liste_langues = ',' . @$GLOBALS['meta']['langues_proposees']
41 . ',' . @$GLOBALS['meta']['langues_multilingue'] . ',';
43 // Si la langue demandee n'existe pas, on essaie d'autres variantes
44 // Exemple : 'pt-br' => 'pt_br' => 'pt'
45 $lang = str_replace('-', '_', trim($lang));
50 if (strpos($liste_langues, ",$lang,") !== false
51 or ($lang = preg_replace(',_.*,', '', $lang)
52 and strpos($liste_langues, ",$lang,") !== false)
55 $GLOBALS['spip_lang_rtl'] = lang_dir($lang, '', '_rtl');
56 $GLOBALS['spip_lang_right'] = $GLOBALS['spip_lang_rtl'] ?
'left' : 'right';
57 $GLOBALS['spip_lang_left'] = $GLOBALS['spip_lang_rtl'] ?
'right' : 'left';
59 return $GLOBALS['spip_lang'] = $lang;
66 // Gestion des blocs multilingues
67 // Selection dans un tableau dont les index sont des noms de langues
68 // de la valeur associee a la langue en cours
69 // si absente, retourne le premier
70 // remarque : on pourrait aussi appeler un service de traduction externe
71 // ou permettre de choisir une langue "plus proche",
72 // par exemple le francais pour l'espagnol, l'anglais pour l'allemand, etc.
74 function choisir_traduction($trads, $lang = '') {
75 $k = approcher_langue($trads, $lang);
77 return $k ?
$trads[$k] : array_shift($trads);
80 // retourne son 2e argument si c'est un index du premier
81 // ou un index approchant sinon et si possible,
82 // la langue X etant consideree comme une approche de X_Y
83 function approcher_langue($trads, $lang = '') {
86 $lang = $GLOBALS['spip_lang'];
89 if (isset($trads[$lang])) {
91 } // cas des langues xx_yy
93 $r = explode('_', $lang);
94 if (isset($trads[$r[0]])) {
103 * Traduit un code de langue (fr, en, etc...) vers le nom de la langue
104 * en toute lettres dans cette langue (français, English, etc....).
106 * Si le spip ne connait pas le nom de la langue, il retourne le code
108 * @param string $lang
111 * Nom de la langue, sinon son code.
113 function traduire_nom_langue($lang) {
114 include_spip('inc/lang_liste');
115 include_spip('inc/charsets');
117 return html2unicode(isset($GLOBALS['codes_langues'][$lang]) ?
$GLOBALS['codes_langues'][$lang] : $lang);
124 // Donne la direction d'ecriture a partir de la langue. Retourne 'gaucher' si
125 // la langue est arabe, persan, kurde, dari, pachto, ourdou (langues ecrites en
126 // alphabet arabe a priori), hebreu, yiddish (langues ecrites en alphabet
127 // hebreu a priori), 'droitier' sinon.
128 // C'est utilise par #LANG_DIR, #LANG_LEFT, #LANG_RIGHT.
129 // http://code.spip.net/@lang_dir
130 function lang_dir($lang = '', $droitier = 'ltr', $gaucher = 'rtl') {
131 static $lang_rtl = array('ar', 'fa', 'ku', 'prs', 'ps', 'ur', 'he', 'heb', 'hbo', 'yi');
133 return in_array(($lang ?
$lang : $GLOBALS['spip_lang']), $lang_rtl) ?
134 $gaucher : $droitier;
137 // typo francaise ou anglaise ?
138 // $lang_objet est fixee dans l'interface privee pour editer
139 // un texte anglais en interface francaise (ou l'inverse) ;
140 // sinon determiner la typo en fonction de la langue courante
142 // http://code.spip.net/@lang_typo
143 function lang_typo($lang = '') {
145 $lang = isset($GLOBALS['lang_objet'])
146 ?
$GLOBALS['lang_objet']
147 : $GLOBALS['spip_lang'];
151 or strncmp($lang, 'fr_', 3) == 0
160 // gestion de la globale $lang_objet pour que les textes soient affiches
161 // avec les memes typo et direction dans l'espace prive que dans le public
162 // http://code.spip.net/@changer_typo
163 function changer_typo($lang = '') {
165 $GLOBALS['lang_objet'] = $lang;
167 unset($GLOBALS['lang_objet']);
172 // Afficher un menu de selection de langue
173 // - 'var_lang_ecrire' = langue interface privee,
174 // pour var_lang' = langue de l'article, espace public, voir les squelettes
175 // pour 'changer_lang' (langue de l'article, espace prive), c'est en Ajax
177 // http://code.spip.net/@menu_langues
178 function menu_langues($nom_select, $default = '') {
179 include_spip('inc/actions');
181 $langues = liste_options_langues($nom_select);
183 if (!count($langues)) {
188 $default = $GLOBALS['spip_lang'];
190 foreach ($langues as $l) {
191 $selected = ($l == $default) ?
' selected=\'selected\'' : '';
192 $ret .= "<option value='$l'$selected>[" . $l . "] " . traduire_nom_langue($l) . "</option>\n";
195 if (!test_espace_prive()) {
200 $base = spip_connect() ?
'base' : '';
203 $change = ' onchange="this.parentNode.parentNode.submit()"';
205 return generer_action_auteur('converser', $base, $cible,
206 (select_langues($nom_select, $change, $ret)
207 . "<noscript><div style='display:inline'><input type='submit' class='fondo' value='" . _T('bouton_changer') . "' /></div></noscript>"),
211 // http://code.spip.net/@select_langues
212 function select_langues($nom_select, $change, $options, $label = "") {
214 $id = "menu_langues" . $cpt++
;
217 "<label for='$id'>" . ($label ?
$label : _T('info_langues')) . "</label> " .
218 "<select name='$nom_select' id='$id' "
219 . ((!test_espace_prive()) ?
220 ("class='forml menu_langues'") :
221 (($nom_select == 'var_lang_ecrire') ?
222 ("class='lang_ecrire'") :
231 * Lister les langues disponibles
233 * Retourne un tableau de langue utilisables, triées par code de langue,
234 * mais pas le même tableau en fonction du paramètre $nom_select.
236 * @param string $nom_select
237 * Attribut name du select
238 * Selon son nom, retourne une liste différente :
240 * - var_lang ou changer_lang :
241 * liste des langues sélectionnées dans la config multilinguisme
242 * - var_lang_ecrire :
243 * toutes les langues présentes en fichier de langue
247 function liste_options_langues($nom_select) {
249 switch ($nom_select) {
252 # menu de changement de la langue d'un article
253 # les langues selectionnees dans la configuration "multilinguisme"
255 $langues = explode(',', $GLOBALS['meta']['langues_multilingue']);
257 # menu de l'interface (privee, installation et panneau de login)
258 # les langues presentes sous forme de fichiers de langue
259 # on force la relecture du repertoire des langues pour etre synchrone.
260 case 'var_lang_ecrire':
262 $GLOBALS['meta']['langues_proposees'] = '';
264 $langues = explode(',', $GLOBALS['meta']['langues_proposees']);
267 # dernier choix possible : toutes les langues = langues_proposees
268 # + langues_multilingues ; mais, ne sert pas
269 # $langues = explode(',', $GLOBALS['all_langs']);
271 if (count($langues) <= 1) {
281 * Redirige sur la bonne langue lorsque l'option forcer_lang est active
283 * Cette fonction est appelee depuis ecrire/public.php si on a installé
284 * la variable de personnalisation $forcer_lang ; elle renvoie le brouteur
285 * si necessaire vers l'URL xxxx?lang=ll
289 function verifier_lang_url() {
291 // quelle langue est demandee ?
292 $lang_demandee = (test_espace_prive() ?
$GLOBALS['spip_lang'] : $GLOBALS['meta']['langue_site']);
293 if (isset($_COOKIE['spip_lang_ecrire'])) {
294 $lang_demandee = $_COOKIE['spip_lang_ecrire'];
296 if (!test_espace_prive() and isset($_COOKIE['spip_lang'])) {
297 $lang_demandee = $_COOKIE['spip_lang'];
299 if (isset($_GET['lang'])) {
300 $lang_demandee = $_GET['lang'];
303 // Renvoyer si besoin (et si la langue demandee existe)
304 if ($GLOBALS['spip_lang'] != $lang_demandee
305 and changer_langue($lang_demandee)
306 and $lang_demandee != @$_GET['lang']
308 $destination = parametre_url(self(), 'lang', $lang_demandee, '&');
309 // ici on a besoin des var_truc
310 foreach ($_GET as $var => $val) {
311 if (!strncmp('var_', $var, 4)) {
312 $destination = parametre_url($destination, $var, $val, '&');
315 include_spip('inc/headers');
316 redirige_par_entete($destination);
319 // Subtilite : si la langue demandee par cookie est la bonne
320 // alors on fait comme si $lang etait passee dans l'URL
321 // (pour criteres {lang}).
322 $GLOBALS['lang'] = $_GET['lang'] = $GLOBALS['spip_lang'];
327 * Utilise la langue du site
329 * Change la langue en cours d'utilisation par la langue du site
330 * si ce n'est pas déjà le cas.
332 * Note : Cette fonction initialise la globale spip_lang au chargement de inc/lang
335 * La langue sélectionnée
337 function utiliser_langue_site() {
338 // s'il existe une langue du site (en gros tout le temps en théorie)
339 if (isset($GLOBALS['meta']['langue_site'])
340 // et si spip_langue est pas encore définie (ce que va faire changer_langue())
341 // ou qu'elle n'est pas identique à la langue du site
342 and (!isset($GLOBALS['spip_lang'])
343 or $GLOBALS['spip_lang'] != $GLOBALS['meta']['langue_site'])
345 return changer_langue($GLOBALS['meta']['langue_site']);//@:install
347 // en theorie là, la globale est définie, sinon c'est un problème.
348 if (!isset($GLOBALS['spip_lang'])) {
349 spip_log("La globale spip_lang est indéfinie dans utiliser_langue_site() !", _LOG_ERREUR
);
352 return $GLOBALS['spip_lang'];
356 * Initialise la langue pour un visiteur du site
358 * La langue est choisie dans cet ordre :
359 * - Dans le cookie 'spip_lang' ou 'spip_lang_ecrire' s'il existe (selon l'espace public ou privé).
360 * - Sinon dans la session du visiteur.
361 * - Sinon dans une des langues définie en préférence du navigateur
362 * - Sinon la langue du site
367 function utiliser_langue_visiteur() {
369 $l = (!test_espace_prive() ?
'spip_lang' : 'spip_lang_ecrire');
370 if (isset($_COOKIE[$l])) {
371 if (changer_langue($l = $_COOKIE[$l])) {
376 if (isset($GLOBALS['visiteur_session']['lang'])) {
377 if (changer_langue($l = $GLOBALS['visiteur_session']['lang'])) {
382 if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
383 foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $s) {
384 if (preg_match('#^([a-z]{2,3})(-[a-z]{2,3})?(;q=[0-9.]+)?$#i', trim($s), $r)) {
385 if (changer_langue($l = strtolower($r[1]))) {
392 return utiliser_langue_site();
397 * Verifier qu'une chaine suceptible d'etre un nom de langue a le bon format
398 * @param string $chaine
401 function match_langue($chaine) {
402 return preg_match('/^[a-z]{2,3}(_[a-z]{2,3}){0,2}$/', $chaine);
406 * Initialisation des listes de langues
408 * Initialise les métas :
409 * - langues_proposees : liste des traductions disponibles
410 * - langue_site : langue par défaut du site
412 * Lorsque ces métas n'existent pas encore (c'est à dire à l'installation),
413 * elles sont calculées en obtenant la liste des langues
414 * dans les fichiers de lang
418 function init_langues() {
420 // liste des langues dans les meta, sauf a l'install
421 $all_langs = @$GLOBALS['meta']['langues_proposees'];
425 // trouver tous les modules lang/spip_xx.php
426 $modules = find_all_in_path("lang/", "/spip_([a-z_]+)\.php$");
427 foreach ($modules as $name => $path) {
428 if (preg_match(',^spip_([a-z_]+)\.php$,', $name, $regs)) {
429 if (match_langue($regs[1])) {
435 $tout = join(',', $tout);
436 // Si les langues n'ont pas change, ne rien faire
437 if ($tout != $all_langs) {
438 $GLOBALS['meta']['langues_proposees'] = $tout;
439 include_spip('inc/meta');
440 ecrire_meta('langues_proposees', $tout);
443 if (!isset($GLOBALS['meta']['langue_site'])) {
444 // Initialisation : le francais si dispo, sinon la premiere langue trouvee
445 $GLOBALS['meta']['langue_site'] = $tout =
446 (!$all_langs or (strpos(',' . _LANGUE_PAR_DEFAUT
. ',', ",$all_langs,") !== false))
447 ? _LANGUE_PAR_DEFAUT
: substr($all_langs, 0, strpos($all_langs, ','));
448 ecrire_meta('langue_site', $tout);
453 * Retourne une balise <html>
455 * Retourne une balise HTML contenant les attributs 'lang' et 'dir'
456 * définis sur la langue en cours d'utilisation,
457 * ainsi que des classes CSS de ces du nom de la langue et direction choisie.
460 * Code html de la balise <html>
462 function html_lang_attributes() {
463 $lang = $GLOBALS['spip_lang'];
464 $dir = ($GLOBALS['spip_lang_rtl'] ?
'rtl' : 'ltr');
466 return "<html class='$dir $lang no-js' xmlns='http://www.w3.org/1999/xhtml' lang='$lang' dir='$dir'>\n";
471 * Calcul de la direction du texte et la mise en page selon la langue
473 * En hébreu le ? ne doit pas être inversé.
475 * @param string $spip_lang
476 * @param string $spip_lang_rtl
479 function aide_lang_dir($spip_lang, $spip_lang_rtl) {
480 return ($spip_lang <> 'he') ?
$spip_lang_rtl : '';
484 // initialise les globales (liste des langue, langue du site, spip_lang...)
486 utiliser_langue_site();