spip_nursit/ecrire/inc/lang.php
2023-06-01 17:30:12 +02:00

486 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Copyright (c) 2001-2019 *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
/**
* Gestion des langues et choix de langue
*
* @package SPIP\Core\Langue
**/
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Changer la langue courante
*
* Définit la langue utilisée par la langue désignée
* si elle fait partie des langues utilisables dans le site.
*
* Cette fonction définit les globales :
* spip_lang, spip_lang_rtl, spip_lang_right, spip_lang_left
*
* @param string $lang
* La langue à utiliser
* @return string|bool
* string : La langue qui a été utilisée si trouvée
* false : aucune langue ne correspondait à la demande
**/
function changer_langue($lang) {
$liste_langues = ',' . @$GLOBALS['meta']['langues_proposees']
. ',' . @$GLOBALS['meta']['langues_multilingue'] . ',';
// Si la langue demandee n'existe pas, on essaie d'autres variantes
// Exemple : 'pt-br' => 'pt_br' => 'pt'
$lang = str_replace('-', '_', trim($lang));
if (!$lang) {
return false;
}
if (strpos($liste_langues, ",$lang,") !== false
or ($lang = preg_replace(',_.*,', '', $lang)
and strpos($liste_langues, ",$lang,") !== false)
) {
$GLOBALS['spip_lang_rtl'] = lang_dir($lang, '', '_rtl');
$GLOBALS['spip_lang_right'] = $GLOBALS['spip_lang_rtl'] ? 'left' : 'right';
$GLOBALS['spip_lang_left'] = $GLOBALS['spip_lang_rtl'] ? 'right' : 'left';
return $GLOBALS['spip_lang'] = $lang;
} else {
return false;
}
}
//
// Gestion des blocs multilingues
// Selection dans un tableau dont les index sont des noms de langues
// de la valeur associee a la langue en cours
// si absente, retourne le premier
// remarque : on pourrait aussi appeler un service de traduction externe
// ou permettre de choisir une langue "plus proche",
// par exemple le francais pour l'espagnol, l'anglais pour l'allemand, etc.
function choisir_traduction($trads, $lang = '') {
$k = approcher_langue($trads, $lang);
return $k ? $trads[$k] : array_shift($trads);
}
// retourne son 2e argument si c'est un index du premier
// ou un index approchant sinon et si possible,
// la langue X etant consideree comme une approche de X_Y
function approcher_langue($trads, $lang = '') {
if (!$lang) {
$lang = $GLOBALS['spip_lang'];
}
if (isset($trads[$lang])) {
return $lang;
} // cas des langues xx_yy
else {
$r = explode('_', $lang);
if (isset($trads[$r[0]])) {
return $r[0];
}
}
return '';
}
/**
* Traduit un code de langue (fr, en, etc...) vers le nom de la langue
* en toute lettres dans cette langue (français, English, etc....).
*
* Si le spip ne connait pas le nom de la langue, il retourne le code
*
* @param string $lang
* Code de langue
* @return string
* Nom de la langue, sinon son code.
**/
function traduire_nom_langue($lang) {
include_spip('inc/lang_liste');
include_spip('inc/charsets');
return html2unicode(isset($GLOBALS['codes_langues'][$lang]) ? $GLOBALS['codes_langues'][$lang] : $lang);
}
//
// Filtres de langue
//
// Donne la direction d'ecriture a partir de la langue. Retourne 'gaucher' si
// la langue est arabe, persan, kurde, dari, pachto, ourdou (langues ecrites en
// alphabet arabe a priori), hebreu, yiddish (langues ecrites en alphabet
// hebreu a priori), 'droitier' sinon.
// C'est utilise par #LANG_DIR, #LANG_LEFT, #LANG_RIGHT.
// http://code.spip.net/@lang_dir
function lang_dir($lang = '', $droitier = 'ltr', $gaucher = 'rtl') {
static $lang_rtl = array('ar', 'fa', 'ku', 'prs', 'ps', 'ur', 'he', 'heb', 'hbo', 'yi');
return in_array(($lang ? $lang : $GLOBALS['spip_lang']), $lang_rtl) ?
$gaucher : $droitier;
}
// typo francaise ou anglaise ?
// $lang_objet est fixee dans l'interface privee pour editer
// un texte anglais en interface francaise (ou l'inverse) ;
// sinon determiner la typo en fonction de la langue courante
// http://code.spip.net/@lang_typo
function lang_typo($lang = '') {
if (!$lang) {
$lang = isset($GLOBALS['lang_objet'])
? $GLOBALS['lang_objet']
: $GLOBALS['spip_lang'];
}
if ($lang == 'eo'
or $lang == 'fr'
or strncmp($lang, 'fr_', 3) == 0
or $lang == 'cpf'
) {
return 'fr';
} else {
return 'en';
}
}
// gestion de la globale $lang_objet pour que les textes soient affiches
// avec les memes typo et direction dans l'espace prive que dans le public
// http://code.spip.net/@changer_typo
function changer_typo($lang = '') {
if ($lang) {
$GLOBALS['lang_objet'] = $lang;
} else {
unset($GLOBALS['lang_objet']);
}
}
//
// Afficher un menu de selection de langue
// - 'var_lang_ecrire' = langue interface privee,
// pour var_lang' = langue de l'article, espace public, voir les squelettes
// pour 'changer_lang' (langue de l'article, espace prive), c'est en Ajax
//
// http://code.spip.net/@menu_langues
function menu_langues($nom_select, $default = '') {
include_spip('inc/actions');
$langues = liste_options_langues($nom_select);
$ret = "";
if (!count($langues)) {
return '';
}
if (!$default) {
$default = $GLOBALS['spip_lang'];
}
foreach ($langues as $l) {
$selected = ($l == $default) ? ' selected=\'selected\'' : '';
$ret .= "<option value='$l'$selected>[" . $l . "] " . traduire_nom_langue($l) . "</option>\n";
}
if (!test_espace_prive()) {
$cible = self();
$base = '';
} else {
$cible = self();
$base = spip_connect() ? 'base' : '';
}
$change = ' onchange="this.parentNode.parentNode.submit()"';
return generer_action_auteur('converser', $base, $cible,
(select_langues($nom_select, $change, $ret)
. "<noscript><div style='display:inline'><input type='submit' class='fondo' value='" . _T('bouton_changer') . "' /></div></noscript>"),
" method='post'");
}
// http://code.spip.net/@select_langues
function select_langues($nom_select, $change, $options, $label = "") {
static $cpt = 0;
$id = "menu_langues" . $cpt++;
return
"<label for='$id'>" . ($label ? $label : _T('info_langues')) . "</label> " .
"<select name='$nom_select' id='$id' "
. ((!test_espace_prive()) ?
("class='forml menu_langues'") :
(($nom_select == 'var_lang_ecrire') ?
("class='lang_ecrire'") :
"class='fondl'"))
. $change
. ">\n"
. $options
. "</select>";
}
/**
* Lister les langues disponibles
*
* Retourne un tableau de langue utilisables, triées par code de langue,
* mais pas le même tableau en fonction du paramètre $nom_select.
*
* @param string $nom_select
* Attribut name du select
* Selon son nom, retourne une liste différente :
*
* - var_lang ou changer_lang :
* liste des langues sélectionnées dans la config multilinguisme
* - var_lang_ecrire :
* toutes les langues présentes en fichier de langue
* @return array
* Liste des langues
*/
function liste_options_langues($nom_select) {
switch ($nom_select) {
# #MENU_LANG
case 'var_lang':
# menu de changement de la langue d'un article
# les langues selectionnees dans la configuration "multilinguisme"
case 'changer_lang':
$langues = explode(',', $GLOBALS['meta']['langues_multilingue']);
break;
# menu de l'interface (privee, installation et panneau de login)
# les langues presentes sous forme de fichiers de langue
# on force la relecture du repertoire des langues pour etre synchrone.
case 'var_lang_ecrire':
default:
$GLOBALS['meta']['langues_proposees'] = '';
init_langues();
$langues = explode(',', $GLOBALS['meta']['langues_proposees']);
break;
# dernier choix possible : toutes les langues = langues_proposees
# + langues_multilingues ; mais, ne sert pas
# $langues = explode(',', $GLOBALS['all_langs']);
}
if (count($langues) <= 1) {
return array();
}
sort($langues);
return $langues;
}
/**
* Redirige sur la bonne langue lorsque l'option forcer_lang est active
*
* Cette fonction est appelee depuis ecrire/public.php si on a installé
* la variable de personnalisation $forcer_lang ; elle renvoie le brouteur
* si necessaire vers l'URL xxxx?lang=ll
*
* @return void
**/
function verifier_lang_url() {
// quelle langue est demandee ?
$lang_demandee = (test_espace_prive() ? $GLOBALS['spip_lang'] : $GLOBALS['meta']['langue_site']);
if (isset($_COOKIE['spip_lang_ecrire'])) {
$lang_demandee = $_COOKIE['spip_lang_ecrire'];
}
if (!test_espace_prive() and isset($_COOKIE['spip_lang'])) {
$lang_demandee = $_COOKIE['spip_lang'];
}
if (isset($_GET['lang'])) {
$lang_demandee = $_GET['lang'];
}
// Renvoyer si besoin (et si la langue demandee existe)
if ($GLOBALS['spip_lang'] != $lang_demandee
and changer_langue($lang_demandee)
and $lang_demandee != @$_GET['lang']
) {
$destination = parametre_url(self(), 'lang', $lang_demandee, '&');
// ici on a besoin des var_truc
foreach ($_GET as $var => $val) {
if (!strncmp('var_', $var, 4)) {
$destination = parametre_url($destination, $var, $val, '&');
}
}
include_spip('inc/headers');
redirige_par_entete($destination);
}
// Subtilite : si la langue demandee par cookie est la bonne
// alors on fait comme si $lang etait passee dans l'URL
// (pour criteres {lang}).
$GLOBALS['lang'] = $_GET['lang'] = $GLOBALS['spip_lang'];
}
/**
* Utilise la langue du site
*
* Change la langue en cours d'utilisation par la langue du site
* si ce n'est pas déjà le cas.
*
* Note : Cette fonction initialise la globale spip_lang au chargement de inc/lang
*
* @return string
* La langue sélectionnée
**/
function utiliser_langue_site() {
// s'il existe une langue du site (en gros tout le temps en théorie)
if (isset($GLOBALS['meta']['langue_site'])
// et si spip_langue est pas encore définie (ce que va faire changer_langue())
// ou qu'elle n'est pas identique à la langue du site
and (!isset($GLOBALS['spip_lang'])
or $GLOBALS['spip_lang'] != $GLOBALS['meta']['langue_site'])
) {
return changer_langue($GLOBALS['meta']['langue_site']);//@:install
}
// en theorie là, la globale est définie, sinon c'est un problème.
if (!isset($GLOBALS['spip_lang'])) {
spip_log("La globale spip_lang est indéfinie dans utiliser_langue_site() !", _LOG_ERREUR);
}
return $GLOBALS['spip_lang'];
}
/**
* Initialise la langue pour un visiteur du site
*
* La langue est choisie dans cet ordre :
* - Dans le cookie 'spip_lang' ou 'spip_lang_ecrire' s'il existe (selon l'espace public ou privé).
* - Sinon dans la session du visiteur.
* - Sinon dans une des langues définie en préférence du navigateur
* - Sinon la langue du site
*
* @return string
* La langue utilisée
**/
function utiliser_langue_visiteur() {
$l = (!test_espace_prive() ? 'spip_lang' : 'spip_lang_ecrire');
if (isset($_COOKIE[$l])) {
if (changer_langue($l = $_COOKIE[$l])) {
return $l;
}
}
if (isset($GLOBALS['visiteur_session']['lang'])) {
if (changer_langue($l = $GLOBALS['visiteur_session']['lang'])) {
return $l;
}
}
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $s) {
if (preg_match('#^([a-z]{2,3})(-[a-z]{2,3})?(;q=[0-9.]+)?$#i', trim($s), $r)) {
if (changer_langue($l = strtolower($r[1]))) {
return $l;
}
}
}
}
return utiliser_langue_site();
}
/**
* Verifier qu'une chaine suceptible d'etre un nom de langue a le bon format
* @param string $chaine
* @return int
*/
function match_langue($chaine) {
return preg_match('/^[a-z]{2,3}(_[a-z]{2,3}){0,2}$/', $chaine);
}
/**
* Initialisation des listes de langues
*
* Initialise les métas :
* - langues_proposees : liste des traductions disponibles
* - langue_site : langue par défaut du site
*
* Lorsque ces métas n'existent pas encore (c'est à dire à l'installation),
* elles sont calculées en obtenant la liste des langues
* dans les fichiers de lang
*
* @return void
**/
function init_langues() {
// liste des langues dans les meta, sauf a l'install
$all_langs = @$GLOBALS['meta']['langues_proposees'];
$tout = array();
if (!$all_langs) {
// trouver tous les modules lang/spip_xx.php
$modules = find_all_in_path("lang/", "/spip_([a-z_]+)\.php$");
foreach ($modules as $name => $path) {
if (preg_match(',^spip_([a-z_]+)\.php$,', $name, $regs)) {
if (match_langue($regs[1])) {
$tout[] = $regs[1];
}
}
}
sort($tout);
$tout = join(',', $tout);
// Si les langues n'ont pas change, ne rien faire
if ($tout != $all_langs) {
$GLOBALS['meta']['langues_proposees'] = $tout;
include_spip('inc/meta');
ecrire_meta('langues_proposees', $tout);
}
}
if (!isset($GLOBALS['meta']['langue_site'])) {
// Initialisation : le francais si dispo, sinon la premiere langue trouvee
$GLOBALS['meta']['langue_site'] = $tout =
(!$all_langs or (strpos(',' . _LANGUE_PAR_DEFAUT . ',', ",$all_langs,") !== false))
? _LANGUE_PAR_DEFAUT : substr($all_langs, 0, strpos($all_langs, ','));
ecrire_meta('langue_site', $tout);
}
}
/**
* Retourne une balise <html>
*
* Retourne une balise HTML contenant les attributs 'lang' et 'dir'
* définis sur la langue en cours d'utilisation,
* ainsi que des classes CSS de ces du nom de la langue et direction choisie.
*
* @return string
* Code html de la balise <html>
**/
function html_lang_attributes() {
$lang = $GLOBALS['spip_lang'];
$dir = ($GLOBALS['spip_lang_rtl'] ? 'rtl' : 'ltr');
return "<html class='$dir $lang no-js' xmlns='http://www.w3.org/1999/xhtml' lang='$lang' dir='$dir'>\n";
}
/**
* Calcul de la direction du texte et la mise en page selon la langue
*
* En hébreu le ? ne doit pas être inversé.
*
* @param string $spip_lang
* @param string $spip_lang_rtl
* @return string
*/
function aide_lang_dir($spip_lang, $spip_lang_rtl) {
return ($spip_lang <> 'he') ? $spip_lang_rtl : '';
}
// initialise les globales (liste des langue, langue du site, spip_lang...)
init_langues();
utiliser_langue_site();