Site public dans la langue préférée du navigateur

All contributions published for previous SPIP versions

Un squelette qui perment de présenter à ceux et celles qui visitent le site un sommaire dans leur langue de préférence, définie dans le navigateur.

Peux mieux faire...

A l’heure de modifier la présente contrib, il convient de mentionner avant tout que depuis, Laurent en a fait une bien mieux!

Non seulement elle englobe fonctionnellement les deux approches proposées sur ce site [1], mais en plus elle utilise très élégamment les fonctions déjà développées dans le code de SPIP.

Je vous suggère vivement d’essayer d’abord sa solution. Les lignes qui suivent n’ont plus qu’un intérêt pédagogique.

<font
color="red">S<font
color="orange">P<font
color="yellow">I<font
color="green">P <font
color="blue">1<font
color="black">.7<font
color="darkviolet">.2
Attention: Pour faire marcher la contrib de Laurent avec SPIP 1.7.2, il faut ajouter dans mes_fonctions.php3 :

function gerer_menu_langues() {
    global $var_lang;
    if ($var_lang) {
        if (changer_langue($var_lang)) {
            spip_setcookie('spip_lang', $var_lang, time() + 24 * 3600);
        }
    }
}

En effet, la fonction gerer_menu_langues, qui était présente dans ecire/inc_lang.php3 dans la version 1.7, a disparu dans la 1.7.2 (sans doute parce qu’elle ne servait à rien pour SPIP lui-même)

La langue préférée dans le navigateur

Dans un navigateur, une personne peut indiquer quelles sont ses langues de prédilection, et les classer par préférence. En fonction de cela; un serveur web pourra modifier son comportement, et en particulier sélectionner la langue dans laquelle il affiche ses pages.

Dans Mozilla, par exemple, on le fait en éditant les préférences. Dans l’image ci-dessous, je lui indique que je préfère voir un site en espagnol, version uruguayenne si elle est disponible, sinon en français, version hexagonale de préférence, et enfin en anglais.

En fait, un site web n’apparaîtra dans la langue choisie que s’il est conçu pour cela. L’information est disponible et sa mise à disposition fait partie des standards HTTP/HTML, mais encore faut-il que le serveur s’en serve.

Dans cette contrib, nous verrons comment construire un site SPIP multilingue qui utilise cette fonctionnalité: celui ou celle qui visite le site verra s’afficher automatiquement le «sommaire» dans la langue existante sur le site, qui correspond le mieux à ses préférences.

L’idée pour SPIP

Le principe que nous venons de décrire n’est intéressant et faisable que si le site que nous construisons a vocation à présenter la totalité de son information (ou presque) dans chacune des langues qu’il gère. Dans ce cas, la structure la plus courante pour organiser ce type de site multilingue est de réserver un secteur [2] à chacune des langues du site [3].

Bien qu’il existe un squelette pour le sommaire du site (sommaire.html), la manière la plus logique de construire celui-ci pour chacune des langues sera sans doute avec la page de rubrique du secteur correspondant.

L’idée est d’utiliser le squelette sommaire.html pour détecter les langues de prédilection dans le navigateur et d’y effectuer la redirection correspondante.

Les fonctions PHP utilisées

Dans cette boucle nous utiliserons quelques variables et fonctions PHP:
-  $_SERVER['HTTP_ACCEPT_LANGUAGE'] est une variable réservée de PHP, à travers laquelle on accède à la liste ordonnée des langues préférées dans le navigateur client;
-  split() est une de ces fonctions puissantes que propose PHP pour transformer une chaîne de caractères en tableau (array)... mais en l’occurrence, comme signalé sur le forum ci-dessous, il est plus efficace d’utiliser explode()
-  header() est la fonction PHP qui permet de renvoyer une entête HTTP au navigateur. L’entête envoyée est "Location: [URL]" [RFC2612 14.30, page 134], où [URL] est une adresse HTTP pour redirection.

Le code de la solution

Pour réaliser la redirection, il suffit de créer un squelette sommaire.html qui contienne le code suivant:

<?php
/* 
 * Construire un tableau $langues avec les langues preferees 
 * du navigateur
 */
$langues = split(",", $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach( $langues as $lg ) {
/* 
 * pour chaque langue préférée par le visiteur 
 */
<BOUCLE_secteurs_langue(RUBRIQUES){racine}>
        /* 
         * Une boucle de secteurs, c'està dire des langues 
         * du site
         */

	if (substr($lg,0,2) == "#LANG") {
	/* 
	 * si la langue préférée (sans variante) est identique à  
         * celle du secteur, rediriger ver le secteur
	 */
		header("Location: #URL_RUBRIQUE");
		exit;
	};	
</BOUCLE_secteurs_langue>
}
	/* 
	 * si aucune des langues préférées n'existe dans le site 
	 * rediriger vers la langue principale (la première)      
	 */
<BOUCLE_langue_defaut(RUBRIQUES){racine}{0,1}>
	header("Location: #URL_RUBRIQUE");
</BOUCLE_langue_defaut>
?>

Bien sûr, on peut supprimer les lignes entre /* et */ qui ne sont que des commentaire pour mieux comprendre le squelette.

Pour finir de comprendre le fonctionnement, rappelons que SPIP est une sorte de «pré-processeur PHP»: à partir des squelettes et des données de la base SPIP construit un fichier PHP qu’il stocke dans le cache et qui s’exécute chaque fois que l’on appelle la page.

Supposons que notre site ait trois secteurs: le numéro 1 en espagnol, le numéro 2 en français, et le numéro 15 en arabe. A partir du squelette ci-dessus, SPIP va créer dans le cache un fichier avec le code PHP qui suit (on suppose qu’on a supprimé les commentaires):

<?php

$langues = split(",", $_SERVER['HTTP_ACCEPT_LANGUAGE']);
foreach( $langues as $lg ) {

	if (substr($lg,0,2) == "es") {

		header("Location: rubrique.php3?id_rubrique=1");
		exit;
	};	

	if (substr($lg,0,2) == "en") {

		header("Location: rubrique.php3?id_rubrique=2");
		exit;
	};	


	if (substr($lg,0,2) == "ar") {

		header("Location: rubrique.php3?id_rubrique=15");
		exit;
	};	
}
	header("Location: rubrique.php3?id_rubrique=1");
?>

Et chaque fois que cette page est appelée, ce code s’exécute avec, dans $_SERVER['HTTP_ACCEPT_LANGUAGE'], les valeurs appropriées des préférences.

Le squelette du «sommaire»

En utilisant les fonctionnalités des fichiers de langue pour
internationaliser les squelettes, il peut être utile de créer un squelette unique multilingue pour le sommaire dans toutes les langues. Cependant, comme on a déjà utilisé le squelette sommaire.html (qui, de toutes manières, ne nous aurait pas permis de distinguer véritablement la langue préférée), il sera nécessaire, si l’on veut que le sommaire se distingue des autres sous-sections, de prévoir des fichiers squelettes spécifiques pour chaque secteur de langue. Une solution pourra être d’utiliser la «fonction» SPIP INCLURE:

-  créer un squelette spécifique sommaire_lang.html et sommaire_lang.php3,

-  créer, pour chacun des secteurs, un squelette rubrique=N.html (où N est le numéro de secteur: 1, 2 et 15, dans l’exemple précédent) qui ne contiendra que l’inclusion du squelette précédent: <INCLURE(sommaire_lang.php3){id_rubrique}.

Certes, pas très élégante cette dernière proposition, mais je ne vois pas comment faire simple autrement... ;-)

Footnotes

[1celle de la présente contrib, et celle de Nicolas.

[2rappelons qu’un secteur est une rubrique de premier niveau, située à la racine du site.

[3Pour une discussion plus complète sur la façon d’organiser un site multilingues avec SPIP, voir la documentation «Réaliser un site multilingue».

Il convient de mentionner que je n’ai pas inventé tout ça tout seul: je me suis, comme toujours, inspiré d’un exemple trouvé sur internet (que je ne retourve plus à l’heure de rédiger la présente contrib...). L’apport est d’adapter à SPIP un exemple PHP.

updated on 23 February 2019

Discussion

4 discussions

  • ça marche presque chez moi 2.0.9,
    en rajoutant : le paramètre lang=XX
    de cette manière:[(#URL_RUBRIQUE|parametre_url’lang’,#LANG)]
    mais mon autre problème est que mon url est sous cette forme :
    spip.php?rubrique1 & amp ; lang=fr

    sauriez vous pourquoi le signe: ’&’ pourtant généré par spip est mal interprété ?

    merci!!

    Reply to this message

  • 1
    Philippe G.

    J’ai un problème bête de chez bête (je suis en 1.8.2d)...
    Tout marche, évidement, mais quand j’affiche la page sommaire et que je change de langue, je souhaite que la rubrique change aussi. Je m’explique avec un exemple :
    La rubrique “fr” est la rubrique 1 et la rubrique “en”est la 2. Quand je suis sur le site français (rubrique 1) et que je clique sur le menu de langues (pour afficher en anglais), je change bien de langue mais reste sur la rubrique 1 alors que je voudrais basculer sur la rubrique 2 (les articles ne sont pas forcément les mêmes).
    Merci de votre aide, je sèche !

    Reply to this message

  • 4

    « split() est une de ces fonctions puissantes que propose PHP pour transformer une chaîne de caractères en tableau (array) ; »

    Dans le manuel dont vous donnez la page, il est écrit qu’il vaut mieux préférer explode.

    • En effet, merci pour la remarque!

      Dès que j’ai l’occasion de le tester, je modifie la contrib.

    • Laurent Laville

      Pour toutes celles et ceux qui revaient d’un mixe des deux solutions.

      Venez lire mon article sur la page d’accueil multi-langues

      J’espère que dani ne m’en voudra pas d’avoir repris une grande partie de son article ;-)
      Mais comme je le dis, il faudrait être fou pour réinventer ce que d’autres avant nous ont très bien fait !

    • Salut,

      J’utilise SPIP 1.7.
      Merci pour vos articles ! Suite à la version de Laurent, je suis presque arrivé à mes fins.

      Sauriez vous pourquoi gerer_menu_langues() ne fonctionne pas ?
      je met bien une valeur dans $var_lang avant de l’appeler.

      j’ai toujours #LANG positionné à l’ancienne valeur, et du coup, mes boucles de menu ne changent jamais.

      Noel

      PS : Y a-t’il un moyen d’acceder à la langue de la rubrique courante ?

    • Sauriez vous pourquoi gerer_menu_langues() ne fonctionne pas ? je met bien une valeur dans $var_lang avant de l’appeler.

      Je pense que cette fonction n’attribue que les langues qui sont effectivement configurées dans le site (espace privé: Admin-> gestion langues->multilingüisme). Ton pb ne vient-il pas de là?

      Y a-t’il un moyen d’acceder à la langue de la rubrique courante ?

      Oui, la balise #LANG dans une boucle RUBRIQUES. (mais est-ce la question? ;-)

    Reply to this message

  • Nicolas Hoizey a fait une contrib qui propose une autre solution à la même problématique, déjà valable pour des sites multilingues sous 1.6. Les fonctionnalités ne sont pas exactement les mêmes :
    -  elle utilise phpLang, un script qui ajoute un avantage fonctionnel indéniable : l’utilisateur peut choisir une autre langue et le navigateur en garde la «mémoire» avec des cookies,
    -  ceci dit, elle requiert d’avoir accès aux Rewrite rules d’Apache soit directement dans httpd.onf, soit autorisées dans le .htaccess)
    -  elle est un peu moins générale, car il faut ajouter des ’rewrite rules’ pour chaque langue ajoutée.

    Ce serait bien de réfléchir à un mix des deux.

    Reply to this message

Comment on this article

Who are you?
  • [Log in]

To show your avatar with your message, register it first on gravatar.com (free et painless) and don’t forget to indicate your Email addresse here.

Enter your comment here

This form accepts SPIP shortcuts {{bold}} {italic} -*list [text->url] <quote> <code> and HTML code <q> <del> <ins>. To create paragraphs, just leave empty lines.

Add a document

Follow the comments: RSS 2.0 | Atom