Bonjour à tous
Faisant suite à ma question déjà posé sur le forum ou je vous demandais des conseils pour réaliser un site multilingue (Voir ici https://www.grafikart.fr/forum/topics/28532) j'ai finalement opté pour la solution GETTEXT.
Donc j'ai un site "unique" (sans copie pour les langues) et c'est la variable GET qui comprendra la langue. Evidemment, le fichier .htaccess fera le reste en "simulant" les dossiers langues. Donc par exemple monsite.ch/home?lang=fr deviendra monsite.ch/fr/home (La variable GET sera donc conservé)
J'ai donc réalisé un script PHP pour la gestion des langues, qui sera inclus au début de mes pages. J'ai encore le .htaccess à configuré correctement mais pour le moment je souhaiterai avoir votre avis et vos conseils sur mon script. Je ne suis pas un expert PHP, j'aimerais donc savoir si mon code est bien optimisé et si vous pensez que des améliorations sont possible.
Le script prend en compte la variable GET si dispo, sinon il verifie si il y un cookies lang ou alors il recupère la langue du navigateur client.
Le voici :
<?php
// SCRIPT TEST LANGUE
// Variables pour la redirection
// Debut de l'URL pour la redirection
$host = "https://".$_SERVER['HTTP_HOST'].'/';
// Chemin courant pour la redirection, avec suppression de l'extension .php
$chemin_courant = substr($_SERVER['REQUEST_URI'], 0, -4);
// Si le get existe et n'est pas vide
if(isset($_GET['lang']) && $_GET['lang'] != ''){
// On peu récupéré la langue
$lang = $_GET['lang'];
// Array des langues
$langues = array("en", "fr", "de");
// Si, la langue recus dans le GET est dans l'array,
if(in_array($lang, $langues)){
// elle est considéré comme valide et la variable $lang pourra être utiliser pour les URLs de la page.
// Variables langues pour les réglages
$lang_param = $lang.'_CH'; // Exemple -> fr deviens fr_CH, it deviens it_CH etc... (Le site est SUISSE)
// On peu maintenant configurer les locales
$filename = $lang_param;
putenv("LC_MESSAGES=$lang_param");
setlocale(LC_MESSAGES, $lang_param);
bindtextdomain($filename, './locale');
bind_textdomain_codeset($filename, "UTF-8");
textdomain($filename);
exit(); // Tout est ok, on a bien recupéré la langue, on peu donc stopper le script et afficher la page dans la langue recus par le GET
// Par contre si, la langue recus dans le GET n'est PAS dans l'array (Donc pas valide)
}else{
// On regarde si le cookies langue_prefere existe
if(isset($_COOKIE["langue_prefere"])){
// Variable cookies langue
$langue_prefere = $_COOKIE["langue_prefere"];
// Et on redirige sur le même page mais en prenons en compte la langue. Ainsi, il y aura le GET lang lors de la redirection.
switch ($langue_prefere) {
case "fr":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
case "de":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'de'.$chemin_courant);
exit();
break;
case "es":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'es'.$chemin_courant);
exit();
break;
case "en":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'en'.$chemin_courant);
exit();
break;
case "it":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'it'.$chemin_courant);
exit();
break;
// Si aucune de ces langues ne corresponds au cookies,
default :
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
}
// Par contre si le cookies n'existe pas (et que le GET n'est pas dans l'array)
}else{
// On recupère la langue du navigateur client
$LangueNavigateur = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
// Si la variable $LangueNavigateur n'est PAS vide
if(!empty($LangueNavigateur)){
// on redirige sur la bonne langue
switch ($LangueNavigateur) {
case "fr":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
case "de":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'de'.$chemin_courant);
exit();
break;
case "es":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'es'.$chemin_courant);
exit();
break;
case "en":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'en'.$chemin_courant);
exit();
break;
case "it":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'it'.$chemin_courant);
exit();
break;
// Si aucune de ces langues ne corresponds au cookies,
default :
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
}
// Par contre, si on ne recupere pas la langue du visiteur
}else{
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
}
}
}
// Sinon, si le GET lang est vide
}else{
// On regarde si le cookies langue_prefere existe
if(isset($_COOKIE["langue_prefere"])){
// Variable cookies langue
$langue_prefere = $_COOKIE["langue_prefere"];
// Et on redirige sur la bonne langue
switch ($langue_prefere) {
case "fr":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
case "de":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'de'.$chemin_courant);
exit();
break;
case "es":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'es'.$chemin_courant);
exit();
break;
case "en":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'en'.$chemin_courant);
exit();
break;
case "it":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'it'.$chemin_courant);
exit();
break;
// Si aucune de ces langues ne corresponds au cookies,
default :
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
}
// Par contre si le cookies ET le GET n'existent pas
}else{
// On recupère la langue du navigateur client
$LangueNavigateur = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
// Si la variable $LangueNavigateur n'est PAS vide
if(!empty($LangueNavigateur)){
// on redirige sur la bonne langue
switch ($LangueNavigateur) {
case "fr":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
case "de":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'de'.$chemin_courant);
exit();
break;
case "es":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'es'.$chemin_courant);
exit();
break;
case "en":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'en'.$chemin_courant);
exit();
break;
case "it":
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'it'.$chemin_courant);
exit();
break;
// Si aucune langue ne correspond
default :
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
break;
}
// Par contre, si on ne recupere pas la langue du navigateur client
}else{
// On redirige sur la page par defaut fr
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
}
}
}
?>
Merci d'avance pour vos conseils :)
heuuuu, ça, ça gère une ?lang=fr ou ?lang=de ou ?lang=autre chose ??????????
je n'ose imaginer si le problème était complexe :D :D
@pluche
Pierre
Hello @Pierrot01,
Merci pour ton retour. Je ne suis pas sur d'avoir compris ta remarque mais oui effectivement ça gère les différentes langues via le get.
J'ai prévu un array des langues (Voir début du script) qui permet de vérifier si la langue recus dans le GET est bien valide. Par exemple si le GET recus est ?lang=nimporte_quoi, le GET lang n'est pas valide, et on rentre dans le else -> et on regarde si il y à un cookies.
Tu vois ?
A +
Michael
Salut,
Je vois juste que tu "pisses" près de 300 lignes de code pour en finir à quelque chose de très proche de ça :
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.'fr'.$chemin_courant);
exit();
y a de l'optimisation à faire :D ;)
de plus, cette imbrication de if elseif case et else est quasiment illisible ;)
je dirais qu'il faut un peu plus de reflexion et un peu moins de dactylographie :D
@plus
Pierre
Déjà au lieu de switch tu peux créer un tabbleau contenant it, fr etc ... et fait seulement une fonction qui gère le header en envoyant en param:
genre :
public function setHeader($langue = 'fr'){ //cas du default
$langues = array("en", "fr", "de");
if(!in_array($langue,$langues){
$langue = 'fr'; // cas où la langue n'est pas dans le tab, tu met à fr
}
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host$langue$chemin_courant);
exit();
}
On appel ça du refactoring, il est important car il permet un meilleur lisibilité de ton code :)
Des outils sur phpstorm peuvent t'aider à refactor, si ton code se répète de trop, une fonction qui fait cette tâche peut te faire limiter en nombre tes lignes de code ! Et donc plus de facilité à lire ton propre code :)
Hello tous le monde !
Merci pour vos retour,
Si je n'ai pas utilisé de fonction il y à une raison : je ne maitrise pas ca ! ^^
Evidemment le refactoring est surement une bonne solution mais je n'ai pas assez de connaissances pour le faire. Le site que je réalise actuellement c'est du PHP brut "simple".
Une autre solution pour optimisé mon code sans passer par le refactoring ? (Promis, j'apprendrais ca bienôt ^^)
Il n'y en a pas, en fait le but du refactoring c'est l'optimisation, et il n'y a que ça...
Salut,
Le traitement pour ce problème est très simple.
y a normalement pas de refactoring à faire.
Ecrire près de 300 lignes pour régler ce tout petit problème est une hérésie :D :D
Même sans la moindre fonction, ça doit faire une petite dizaine de lignes.
ça vaut quand même le coup de faire ça bien directement ;)
@plus
Pierre
Re !
@pierrot01 aurais tu une petite piste pour m'aiguiller ?
J'avoue que je ne sais pas trop comment reduire toutes ces lignes...
C'est vrai que mon script se repète beaucoup mais je ne vois pas comment je peux faire sans passer (pour le moment) par le refactoring.
Comme tu as pu le remarquer mon script prend en compte le GET, sinon le cookies sinon la langue du navigateur client. Je ne vois pas trop comment faire pour traiter tout cela sans faire toutes ces conditions imbriqués..
C'est vraiment possible en une dizaine de ligne ? Je seche ^^
Re !
J'ai eu de l'aide pour l'optimisation de mon code. Il à été considerablement réduis à 70 lignes, c'est déjà mieux non ? ^^
Le voici : (Qu'en pensez vous ?)
<?php
// SCRIPT TEST LANGUE
// Variables pour la redirection
// Debut de l'URL pour la redirection
$host = "https://".$_SERVER['HTTP_HOST'].'/';
// Chemin courant pour la redirection, avec suppression de l'extension .php
$chemin_courant = substr($_SERVER['REQUEST_URI'], 0, -4);
// Si le get existe et n'est pas vide
if(isset($_GET['lang']) && $_GET['lang'] != ''){
// On peu récupéré la langue
$lang = $_GET['lang'];
// Array des langues
$langues = array("en", "fr", "de");
// Si, la langue recus dans le GET est dans l'array,
if(in_array($lang, $langues)){
// elle est considéré comme valide et la variable $lang pourra être utiliser pour les URLs de la page.
// Variables langues pour les réglages
$lang_param = $lang.'_CH'; // Exemple -> fr deviens fr_CH, it deviens it_CH etc... (Le site est SUISSE)
// On peu maintenant configurer les locales
$filename = $lang_param;
putenv("LC_MESSAGES=$lang_param");
setlocale(LC_MESSAGES, $lang_param);
bindtextdomain($filename, './locale');
bind_textdomain_codeset($filename, "UTF-8");
textdomain($filename);
exit(); // Tout est ok, on a bien recupéré la langue, on peu donc stopper le script et afficher la page dans la langue recus par le GET
// fin du script si OK
}
}
// On regarde si le cookies langue_prefere existe
if(isset($_COOKIE["langue_prefere"])){
// Variable cookies langue
$langue_prefere = $_COOKIE["langue_prefere"];
// Par contre si le cookies n'existe pas (et que le GET n'est pas dans l'array)
}else{
// On recupère la langue du navigateur client
$langue_prefere = substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2);
// Si la variable $LangueNavigateur est vide
if(empty($langue_prefere)){
$langue_prefere = 'fr';
}
}
// On redirige sur la page par defaut de $langue_prefere
header('Status: 301 Moved Permanently', true, 301);
header('Location: '.$host.$langue_prefere.$chemin_courant);
?>
J'avoue que gettext me laisse perplexe
j'amais réussi à faire marcher ce truc :(
le passage de la langue par la locale ou par variable d'environnement ne peut pas fonctionner sur un serveur multi-thread
car seul le processus gère la locale
les threads partagent donc la même langue ... c'est foireux
Edit: gettext c'était prévu à l'époque pour des applications desktop pour s'adapter à la langue du poste, d'où l'utilisation de la locale.
En web le client n'a vraiment rien à voir avec la locale du serveur.