Comment créer un routeur de langue avec Go ?
Si vous vous êtes posé comme moi la question “Comment pourrais-je servir mes fichiers statiques correctement pour plusieurs langues ?", alors cet article est exactement fait pour vous ! N’ayant trouvé aucun équivalent répondant à mes attentes, je me suis donc attelé à la tâche de le créer. Voyons comment j’ai procédé.
Quelle arborescence de fichiers choisir ?
Ce fut la première question que je me suis posée. Une multitude de solution s’offre à nous pour répondre à ce problème. De mon côté, j’ai choisi de partir sur cette arborescence: en, fr, stylesheets, js et img. Les dossiers “en” et “fr” abriteront les fichiers html traduit en fonction du code du dossier (on suppose que les fichiers équivalents pour les deux langues portent le même nom), pour le reste je pense que vous avez deviné par vous-même.
Quel type d’URL utiliser ?
Il est important de laisser l’utilisateur savoir où il est. Ayant une architecture basique et des fichiers portant le même nom dans les différents dossier, il est judicieux (dans mon cas) de laisser l’arborescence apparaître comme elle est sur le serveur. Par ailleurs, si vos fichiers ont un nom différent pour des versions équivalentes (préférable), vous n'êtes pas obligé de montrer le dossier de langue dans l’URL pour l’utilisateur, cependant le codage du routeur sera plus ardu. L’idée principale est d’empêcher deux fichiers d'être définis par la même URL.
Quelle technologie utiliser ?
Afin de limiter le temps d’exécution entre les requêtes, nous nous devons d’utiliser un langage permettant une parallélisation facile. J’ai choisi Go car
“Il est non seulement facile de paralléliser, mais en plus une requète unique est elle même traitée très vite; le tout avec un langage moderne et facile à utiliser.” - Natsirtt
Nous utiliserons cette technologie dans la suite du tutoriel (avec le paquetage gorilla mux). Cependant ce routeur est tout à fait réalisable avec une autre technologie (node.js par exemple).
Assez parlé, codons !
Euh… On va d’abord mettre en place notre environnement de production. Assurez vous que votre variable d’environnement GOPATH contient le dossier de votre projet. Petit rappel :
|
|
Créez les dossiers bin, pkg, src au sein de votre projet. Allez dans src et créez un dossier reprenant le nom de votre projet. Dans mon cas ce sera ‘language-router’.
Donc maintenant dans notre projet nous avons :
|
|
Rendez vous au sein du dossier src. Installons gorilla mux. (mux nous propose des outils pour la création de routeur).
|
|
Vous devrez alors avoir cette arborescence pour src :
|
|
MAINTENANT CODONS POUR DE VRAI COMME DES BONHOMMES OU FEMMES TRÈS MUSCLÉES !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Commençons par créer le fichier language-router.go au sein de src/language-router/
Pour s’assurer que notre installation est bonne, nous pouvons commencer par coder un petit hello world comme ceci :
|
|
Et si nous sommes aussi génial que nous pensons l'être, en exécutant :
|
|
Le plus chaleureux message apparaît alors sur votre terminal :
|
|
Maintenant passons aux choses sérieuses.
Nous allons ajouter mux à nos paquetages (ou packages), et commencer à créer notre propre routeur.
|
|
Lancez le programme (go run language-router). Lancez votre navigateur et allez sur localhost. Vous devrez trouver normalement une page 404. Ne vous inquiétez pas, tout va bien. Ce que nous avons fait pour le moment et de créer le routeur et l’attribuer à la racine du serveur. Cependant notre routeur ne fait strictement rien. Changeons cela.
|
|
Nous avons ajouté ici une fonction “rootHandler” qui va nous renvoyer le même fichier (/home/juanwolf/juanwolf.fr/fr/index.html) et cette fonction sera attribuée à l’url “/” (la racine). Nous avons cité un peu plus haut que nous voulions une détection automatique du langage préféré de l’utilisateur cependant pour le moment notre fichier sera toujours la version française de index.html. IMPLEMENTONS ÇA OHHHHHHHHHH YEAAAAAAAAAAAAAAH.
Moi je veux bien, mais comment qu’on fait ?
Demandons à papy W3C.
For a first contact, using the Accept-Language value to infer regional settings may be a good starting point, but be sure to allow them to change the language as needed and specify their cultural settings more exactly if necessary. Store the results in a database or a cookie for later visits.
(Le lien vers l’article : Accept-Language used for locale setting)
D’accord, faisons comme ça. Ravis de t’avoir revu l’ami !
Donc comme l’a dit papy, on va prendre en compte premièrement l’attribut Accept-Language de la requête HTTP du client et par la suite si l’utilisateur décide de changer de langue on stockera son choix dans un cookie. Mais nous verrons cette dernière partie, un peu plus tard. Gérons dès à présent les préférences de l’utilisateur :
|
|
Comme vous pouvez le voir sur le code précédent, nous avons modifier notre variable ROOT_PATH afin qu’elle ne contienne plus la langue dans son chemin. LANG_DEFAULT servira seulement si le langage préféré de l’utilisateur n’est pas disponible au sein de languageMap. La variable languageMap représente les langues que vous mettez à disposition de l’utilisateur. Avant de nous lancer dans la décortication de la fonction de détection du langage, regardons de quoi est constitué ‘Accept-Language’.
Si on s’amuse à juste retourner la valeur d’Accept-Language, nous retrouvons une chaîne de caractère de la forme : en-GB,en;q=0.8,fr-FR;q=0.6,fr;q=0.4,es;q=0.2. Cet utilisateur a donc pour langue préférée en-GB puis en puis fr-FR. Le q symbolise la “qualité” de la langue, ce n’est autre qu’un poids pour la langue. Si la première n’en a pas, c’est qu’elle est définie à 1 par défaut.
Cela explique pourquoi nous avons autant spliter nos chaînes de caractères. On réutilise donc la noble fonction précédemment créée dans notre rootHandler. Et voilà !
On devait faire apparaître la langue dans l’URL, non ?
En effet. Faisons ça !
|
|
Qu’est ce qui a changé ? Premièrement notre rootHandler ne sert plus de fichiers mais renvoie vers l’URL constituée de la langue. Le routeur dispose maintenant d’un nouveau Handler pour les URLs de langues définies par indexHandler.
Gérons maintenant le cookie.
Pour cette partie nous supposons que votre site comporte un système de choix de la langue tel qu’un select ou autre et que ce système met en place un cookie contenant la langue choisie par l’utilisateur. Si votre site met déjà à disposition un cookie contenant les préférences de langue de l’utilisateur, vous pouvez passez la partie suivante.
Atelier cuisine
Créons notre cookie du côtés des fichiers statiques. Nous allons avoir maintenant besoin des fichiers javascript. On va donc ajouter une route pour que notre routeur nous fournisse ces fichiers statiques.
|
|
Notre fonction main() se transforme ainsi. Faites attention à bien définir la route /js/ avant la route spécifique pour les langues sinon vos fichiers ne seront jamais servis ! Ajoutons maintenant nos fonctions à notre fichier javascript,on suppose que nous ferons la transition entre les langues avec le select :
|
|
Le JavaScript qui lui est joint.
|
|
Maintenant nous avons notre propre cookie avec la langue voulue. On pourrait ajouter à ce javascript une fonction de redirection lors du changement de la langue. Si vous voulez que ce cookie soit disponible sur tout votre site, le point est très important dans la définition du domaine du cookie (domain=.domain.org)
REPASSONS AU GO
Nous devons maintenant lire le cookie s’il est présent sur l’ordinateur de l’utilisateur.
|
|
Et voilà, nous avons donc notre routeur de langue flambant neuf ! Bien sûr, il peut être soumis à des améliorations telles que la détection automatique des langues disponibles sur le serveur, ou la définition d’une 404 ou de sous domaine. Vous pourrez retrouver le lien du dépôt de ce projet ici.
En attendant, codez bien !