Bonsoir,
Je réalise mon site sur la base du tuto en plusieurs jours. J'ai implémenté un système de langage et je voudrais construire une balise meta :

<link rel="alternate" hreflang="fr" href="http://www.site.com/fr/page.html" />
<link rel="alternate" hreflang="en" href="http://www.site.com/en/page.html" />

en me basant sur mes fichiers de routes. Mon problème est que je sais récupérer l'url de la page en cours avec : $this->url

Mais je ne sais pas comment m'y prendre pour changer le fichier route en fonction de la langue.

Exemple pour la page fr j'uilise :

<?php $this->redirect(Router::url('users/unsubscription/email:'.$email)); ?>

qui est traduit dans mon fichier routes.fr.php par :

Router::connect('stop/abonnements/:email','users/unsubscription/email:([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))');

Tout cela fonctionne mais dans la langue en cours.
Auriez vous une idée de comment je dois m'y prendre pour charger le fichier route (temporairement) d'une autre langue ?

$languages = array('fr_FR' => array('id' => 'fr'),'en_US' => array('id' => 'en'));
$alternate_lang = array();
foreach($languages as $k => $v){
        $alternate_lang[$v['id']] = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        if($v['id'] != DEFAULT_LOCALE_ID){
            $alternate_lang[$v['id']] = str_replace('/'.DEFAULT_LOCALE_ID.'/','/'.$v['id'].'/',$alternate_lang[$v['id']]);
        }
}

donne :

Array
(
    [fr] => http://localhost/fr/stop/abonnements/email@fr.fr
    [en] => http://localhost/en/stop/abonnements/email@fr.fr
)

D'avance merci.

17 réponses


Euh, moi j'enregistrerai la langue que l'utilisateur veut dans un cookie.
Mon fichier route resterait indiférent, c'est juste mon controller qui s'assure de bien me donner la langue que je désire, ou de me donner par défaut si elle n'existe pas.

Msappdem
Auteur

J'ai fait effectivement le choix de stocker la langue dans une session en l'initialisant à la base avec une langue par défaut.
Dans mes fichiers routes pour l'exemple j'ai ceci en francais :

Router::connect('stop/abonnements/:email','users/unsubscription/email:([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))');

et ceci en anglais :

Router::connect('stop/subscription/:email','users/unsubscription/email:([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))');

En fait je voudrais pouvoir de n'importe ou povoir construire un tableau qui contiendrait toutes les routes (multilangues) pour l'exemple, je voudrais à partir de ceci :

<?php 
    $email = email@fr.fr;
    $url = Router::url('users/unsubscription/email:'.$email);
 ?>

obtenir ceci :

Array
(
    [fr] => http://localhost/fr/stop/abonnements/email@fr.fr
    [en] => http://localhost/en/stop/unsubscription/email@fr.fr
)

C'est mieux expliquer je crois.

Je suis pas sûr de toujours bien comprendre, pourquoi de n'importe où tu désires construire ces routes ?
Tu as deux choix, (peut-être pas les seuls)

Soit tu stockes tes routes complètes dans un fichier genre routeEN.php routeFR.php...

Soit tu as bien bossé ton système de lang et alors tu as des constantes du type stocké dans un fichier que tu inclus.
du style

require 'constant/lang/' . $_COOKIE['lang'] . '.php'; 

dedans genre :

define('ROUTE_SUBSCRIPTION', 'abonnements');

ton routing devient :

Router::connect('stop/'.ROUTE_SUBSCRIPTION.'/:email','users/unsubscription/email:([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))');
Msappdem
Auteur

La finalité c'est pouvoir indiquer au moteur de recherche que tel ou tel page est disponible dans une langue différente. Et également pouvoir faire des liens pour les visiteurs de la page en cours mais dans une autre langue.

Je suis dans le premier cas, j'ai bien un fichier de route par langue que je charge en fonction de la valeur stocké en session. Je n'ai pas pensé à ton système.

Du coup ce que je voudrais faire c'est une boucle de ce type :

<?php 
    $email = email@fr.fr;
    $url = Router::url('users/unsubscription/email:'.$email);
    $languages = array('fr_FR' => array('id' => 'fr'),'en_US' => array('id' => 'en'),'it_IT' => array('id' => 'it'));
    $alternate_lang = array();
    foreach($languages as $k => $v){
        // charge fichier routes_$k
        // traduit $url
        // $alternate_lang[$v['id']] = {url_traduite};
      }
 ?>

pour au final avoir un tableau propre qui ressemblerait à ça :

Array
(
    [fr] => stop/abonnements/email@fr.fr
    [en] =>stop/unsubscription/email@fr.fr
    [it] =>stop/abbonamenti/email@fr.fr
)

En fait ce que je voudrais faire c'est charger temporairement un fichier de route pour traduire mon url ($url) sans perturber le fichier de route utilisé par le visiteur afin de construire ce tableau.

Une remarque qui me vient, c'est que pour ton referencement, je te conseil de rajouter fr/en, en début de routing.
D'accord, mais le trucs c'est que tu veux charger tout pour toutes les langues et... ça à un coût en performances... Je le vois comme une complication pour rien ce foreach et des pertes de perfs. Limite, tu peux t'en servir pour builder tes lignes en prod, mais ne t'en sert pas en temps réel. Mais tu devras stocker tes liens dans des constantes ou des tableaux, pour que ton foreach fonctionne... Donc bon grosso modo ca rejoint ma proposition n°2.

Il va pas pondre de lui meme que :

array('fr_FR' => array('hello' => 'bonjour),'en_US' => array('hello' => 'Hello'),'it_IT' => array('hello' => 'bonjourno'); 

Après tu es même pas obligé de stocker la langue préférée dans un cookie ou session, ça c'est juste pour l'utilisateur. Mais si tu ne le fais pas, tu as besoin alors de ton fr/en/it dans l'url. le tout c'est de verifier l'entrée de l'utilisateur avec ce qu'il existe sur le serveur. isset($lang['url[0]')
Ca nécessite de changer un bon gros paquet de code dans ton mvc car tu dois parser ton préfix. (again du traitement en plus).

Personnellement, un système mvc à facilité la compréhension de l'implémentation d'une système de langue comme celui-là.
Tout ce qui est textuelle et transmis à l'utilisateur, se trouve dans un fichier langue sous forme de constante.
Tu transmets ses constantes à ta view.

Après j'ignore la façon dont tu as fait le restant du site, peut-être que tu n'envisages pas faire ça car tu te rends compte que plus rien de va fonctionner en amont...

Msappdem
Auteur

Pour reprendre ton exemple du cas N°2 cela donnerait ça :

constant_fr_FR.php :

<?php
    define('ROUTE_STOP', 'stop');
    define('ROUTE_SUBSCRIPTION', 'abonnements');
?>

routes_fr_FR.php :

<?php
    require 'constant/lang/constant_' . $_COOKIE['lang'] . '.php'; 
    Router::connect(ROUTE_STOP.'/'.ROUTE_SUBSCRIPTION.'/:email','users/unsubscription/email:([_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3}))');
?>

Mais même en faisant comme ça (c'est tout à fait possible dans mon application mais j'ai du boulot pour créer les fichiers de constantes...) je devrais charger tous les fichiers de constantes pour avoir les valeurs dans toutes les langues, je devrais faire quelques chose dans le genre :

<?php
    $email = email@fr.fr;
    $languages = array('fr_FR' => array('id' => 'fr'),'en_US' => array('id' => 'en'),'it_IT' => array('id' => 'it'));
    $alternate_lang = array();
    foreach($languages as $k => $v){
        require 'constant/lang/constant_' . k . '.php';
        $url = Router::url('users/unsubscription/email:'.$email);
        $alternate_lang[$v['id']] = $url;
      }
?>

C'est l'idée ?

Oui pour les 2 bout de code c'est ce qu'il faut faire tu devras faire autant de constant_****.php que tu veux de langue.
Pour le deuxième, je ferais :

$lang = isset($_COOKIE['lang']) ? $_COOKIE['lang'] : 'fr_FR';
$path = 'constant/lang/constant_' . $lang . '.php'; 
if(file_exist($path)) {
    require $path;
} else {
    require 'constant/lang/constant_fr_FR.php'; 
}

Oui c'est du boulot pour définir tous ses fichiers, mais une fois que tu as fait toutes les constantes de l'un, tu dois juste traduire pour les autres.

Ton troisième code, je comprends toujours pas pourquoi tu insistes tant à vouloir le mettre, tu as créé un tableau statique, pour lequel tu créés une boucle require de fichier alors que tu ne vas toujours en n'utiliser qu'un à la fois ???

L'utilisateur, il va soit avoir le site en français, soit en anglais soit en italien... Pas tout en même temps :) Cette boucle ne sert à rien.

Car au lieu d'avoir un fichier de route par langue, tu n'en auras plus qu'un seul... D'où l'intéret de t'avoir expliqué ceci :)
Tu n'auras pas inclure un seul fichier route dans ta page index ou écrire les routes dans ta pag eindex directement. Ca c'est comme tu préfères....

Msappdem
Auteur

Effectivement je vois ce que tu veux dire. Je n'ai plus le temps de tester ce soir mais je vais essayer comme tu dis, je reviendrais ici pour la conclusion.
Merci d'avoir pris le temps de me répondre.

Msappdem
Auteur

Bonjour,

Merci pour votre aide, après deux bon jours de modifications j'ai corrigé beaucoup de choses et du coup j'y suis arrivé.

Encore merci.

Msappdem
Auteur

Je viens de me rendre compte que j'avais encore un problème.
Cette balise à l'origine était pour les moteurs de recherches, effectivement un visiteurs ne "consulte" qu'une seule langue à la fois.

Mais également je comptais m'en servir pour faire un menu (style liste déroulante) afin qu'un visiteur puisse être redirigé vers la même page mais dans la langue séléctionnée.

Actuellement et suite à mes dernières modifications je redirige le visiteur sur la page d'accueil suite au changement de la langue.
Le fichiers routes étant chargé à l'arrivée sur le site comment est il possible de "décharger" temporairement les routes pour charger les routes dans une autre langues afin d' avoir un tableau contenant toutes les url d'une même page mais dans les différentes langues ?

Exemple pour le tableau de sortie :

array('fr' => 'http://www.site.fr/fr/connexion','en' => 'http://www.site.fr/en/login');

D'avance merci.

Dans mon routing, chaque nom comporte un titre unique.
Ainsi je peu faire un reverse pour tout mes liens du style

Routing::generate('Articles',['id' => $id, 'slug' => $slug]);

Donc si tu optes pour cette solution là peu importe que ta page article se nomme dans les différentes langues, il faudra que tu mettes le même pour les 3.

Sinon, tu fais 3 menus, un pour chaque langue...

Msappdem
Auteur

Je voudrais bien faire un menu pour chaque langue mais comment le generer en fonction de mes routes ?

Pour reprendre mon exemple précédent voici la route :

Router::connect($router_language.ROUTE_CLIENT_AREA,'users/login');
ou $router_language est égal à 'fr 'et ROUTE_CLIENT_AREA est égal à 'espace' dans le fichier route_fr.php
maintenant dans le fichier route_en.php, $router_language est égal à 'en 'et ROUTE_CLIENT_AREA est égal à 'space'

Quand suis en mode langue 'fr' (route_fr.php) il faudrait pouvoir à la volée charger le fichier de langue anglaise (route_en.php) pour que le Router via la fonction connect renvoie la bonne route. J'ai essayé ce matin plein de chose mais sans resultat.

Comment vous y prendriez vous pour generer ces 3 menus ?

D'avance merci.

Si je comprends bien tu veux que els 3 menus soit affichés sur ta page pour changer de page et de langue en meme temps si l'utilisateur le veut ?

Msappdem
Auteur

oui c'est bien ça. Je voudrais faire un menu par exemple une liste qui permet à l'utilisateur de changer de langue tout en restant sur la même page.

<ul>
    <li><a href="http://www.site.fr/fr/connexion">fr</a></li>
    <li><a href="http://www.site.fr/en/login">en</a></li>    
</ul>

en utilisant mes routes actuelles.

Msappdem
Auteur

J'y ai encore passé ma matinée mas je n'y arrive pas. Comment vous y prendriez vous ?

D'avance merci.

On sait pas quelle technique tu as utilisés... Comment ton outing esst inclus
Ce qui est sur c'est que comme est ton code, tu devras lui préciser à la main quelle page à sa correspondance.

Msappdem
Auteur

J'ai utilisé la technique du tutoriel de création de site en 7jours.
Pour résumé dans le fichiers include.php en fonction de la langue stockée en session je fais ceci :

requiere 'router.php';
requiere $_SESSION['lang'].php; // Contient les constant de language
requiere 'route.php';
require 'Request.php';
require 'Controller.php';
require 'Model.php';
require 'Dispatcher.php';

les routes sont donc chargées au départ et dans la langue définit dans la session.

Pour changer de langue j'utilise un controler 'langue' qui grace à un formulaire permet de changer la valeur de cette variable de session.

Si je voulais définir à la main mes adresses il ne faudrait pas que j'utilise des constantes pour mes routes pour pouvoir les modifier je pense ? J'ai déjà testé mais comme les routes sont chargés au départ par la fonction connect() qui se trouve dans le router.php je ne sais pas comment le forcer à changer ce fichier de langue.

Quels détails vous faudrait il pour cerner mon problème et pouvoir m'aider ?

D'avance merci.