16 - Live Coding : Créer un site multilingue avec Symfony 4

Temps de lecture : 23 minutes environ.

Il arrive parfois d'avoir à mettre en place un site dans plusieurs langues, au niveau de son interface utilisateur.



Symfony nous propose des outils pour mettre en place cette "localisation", également appelée "Internationalization" ou "i18n" (en référence au nombre de caractères entre i et n).



ATTENTION : nous n'allons pas traiter de la traduction du contenu de la base de données, traîtée par l'extension Doctrine Translatable.



Symfony utilisera le service de traduction (Translation service) pour rechercher une traduction pour les chaînes identifiées. Si il trouve une traduction, il remplacera la chaîne par sa traduction.



Information : il sera toujours préférable d'écrire le site en langue anglaise et de le traduire vers les autres langues.



Installer le service



Le service de traduction s'installera au moyen de Composer. Il est déjà installé par défaut dans les configurations basées sur "website-skeleton".



La commande ci-dessous permettra de l'installer




composer require symfony/translation


Une fois installé, le service sera configuré par le fichier "config/packages/translation.yaml" qui contient le code ci-dessous par défaut




# config/packages/translation.yaml
framework:
default_locale: 'en'
translator:
default_path: '%kernel.project_dir%/translations'


L'option "default_locale" permet de définir la langue par défaut du site. Nous allons configurer le Français en indiquant "fr".



L'option "default_path" indique le chemin vers le dossier contenant les traductions.



Utiliser le service



Une fois le service de traduction installé, nous allons pouvoir l'utiliser. Il est possible de traduire des chaînes directement dans les contrôleurs, mais également dans les vues.



Dans les contrôleurs



Si vous devez envoyer une chaîne à traduire depuis un contrôleur, comme dans un message flash par exemple, il est possible de le faire en utilisant les instructions suivantes dans le contrôleur




use Symfony\Contracts\Translation\TranslatorInterface;

public function index(TranslatorInterface $translator)
{
$message = $translator->trans('Your comment is pending approval');

// ...
}


Dans les vues



Nous devrons parfois traduire des chaînes directement dans les vues (fichiers Twig) afin de personnaliser l'interface en fonction de la langue de l'utilisateur.



Par exemple, si nous souhaitons traduire la section suivante de nos vues




<h2>Commentaires ({{ article.commentaires|length }})</h2>
{% for commentaire in article.commentaires %}
<p>Publié par {{commentaire.pseudo }}</p>
<div>{{ commentaire.contenu }}</div>
{% else %}
<p>Il n'y a pas encore de commentaire</p>
{% endfor %}


Nous aurons à traduire les expressions "Commentaires", "Publié par" et "Il n'y a pas encore de commentaire"



Nous allons déclarer des chaînes traductibles dans les vues, comme ci-dessous




{% trans %}Chaîne à traduire{% endtrans %}

{# ou #}

{{ 'Chaîne à traduire'|trans }}


Nous allons utiliser les deux dans notre exemple. Ce qui donnera




<h2>{% trans %}Comments{% endtrans %} ({{ article.commentaires|length }})</h2>
{% for commentaire in article.commentaires %}
<p>{% trans %}Published by{% endtrans %} {{commentaire.pseudo }}</p>
<div>{{ commentaire.contenu }}</div>
{% else %}
<p>{% trans %}There's no comment yet{% endtrans %}</p>
{% endfor %}


Créer le fichiers de traduction



Nous allons enfin créer le fichier de traduction qui contiendra les chaînes en anglais et leur traduction dans la langue de notre choix.



Création manuelle



Le fichier sera à créer en utilisant le code de la langue sur 2 caractères (à l'emplacement de xx), comme fr pour le français.



On créera donc autant de fichiers que de langues, sous le format "translation/messages.xx.xlf"



Pour traduire notre message flash vu précédemment, nous inscrirons donc ceci dans le fichier




<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file source-language="en" target-language="fr" datatype="plaintext" original="file.ext">
<header>
<tool tool-id="symfony" tool-name="Symfony"/>
</header>
<body>
<trans-unit id="2lTOrMA" resname="Article published successfully">
<source>Article published successfully</source>
<target>Article publié avec succès</target>
</trans-unit>
</body>
</file>
</xliff>


Ce fichier n'est pas simple, la partie ci-dessous explique comment l'automatiser.



Création automatique



Il existe une commande permettant de créer automatiquement le fichier de traduction pour la langue de notre choix.



Cette commande va parcourir tous les fichiers et intégrer toutes les chaines dans le fichier correspondant à la langue choisie.



ATTENTION : cette commande ne traduit pas le contenu




php bin/console translation:update --force fr


Le fichier xlf sera créé automatiquement.



Mettre en place le choix de la langue



Pour permettre aux utilisateurs de choisir la langue dans laquelle le site doit s'afficher, nous allons devoir stocker la langue choisie dans la session.



Pour commencer, nous allons créer une variable d'environnement qui contiendra la liste des langues souhaitée.



Cette variable sera déclarée dans "config/services.yaml" de cette façon




parameters:
# ici vos autres variables
app.locales: [en, fr]


Nous allons également déclarer cette variable globalement dans les fichiers Twig afin d'y accéder depuis tous les fichiers. Nous l'appellerons "locales" et l'intégrons dans "config/packages/twig.yaml"




twig:
default_path: '%kernel.project_dir%/templates'
debug: '%kernel.debug%'
strict_variables: '%kernel.debug%'
# On déclare ci-dessous le nom de la variable globale
globals:
locales: '%app.locales%'


On crée maintenant une méthode dans un contrôleur qui permettra de changer la langue.



Cette méthode contiendra le code suivant




/**
* @Route("/change_locale/{locale}", name="change_locale")
*/
public function changeLocale($locale, Request $request)
{
// On stocke la langue dans la session
$request->getSession()->set('_locale', $locale);

// On revient sur la page précédente
return $this->redirect($request->headers->get('referer'));
}


Nous appellerons cette méthode depuis notre menu ou tout fichier Twig dans lequel nous donnerons le choix de la langue aux utilisateurs.




{% for locale in locales %}
{% if locale != app.request.locale %}
<a href="{{ path('change_locale', {'locale': locale}) }}">{{ locale }}</a>
{% endif %}
{% endfor %}


Et voilà, la traduction est en place.



Intercepter les requêtes



Afin de gérer les changements de langues dans le coeur de Symfony (Kernel), nous allons nous attacher à chacune des requêtes en créant un souscripteur d'évènements (EventSubscriber).



Pour ce faire, nous allons entrer la commande suivante




php bin/console make:subscriber LocaleSubscriber


A la question de l'évènement à utiliser, entrer




Symfony\Component\HttpKernel\Event\RequestEvent


Le fichier "LocaleSubscriber.php" est créé dans le dossier "src/EventSubscriber"



Nous allons remplacer son code par celui-ci




<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class LocaleSubscriber implements EventSubscriberInterface
{
// Langue par défaut
private $defaultLocale;

public function __construct($defaultLocale = 'en')
{
$this->defaultLocale = $defaultLocale;
}

public function onKernelRequest(RequestEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}

// On vérifie si la langue est passée en paramètre de l'URL
if ($locale = $request->query->get('_locale')) {
$request->setLocale($locale);
} else {
// Sinon on utilise celle de la session
$request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
}
}

public static function getSubscribedEvents()
{
return [
// On doit définir une priorité élevée
KernelEvents::REQUEST => [['onKernelRequest', 20]],
];
}
}


Voilà qui termine ce tutoriel.



Obtenir de l'aide



Pour obtenir de l'aide, vous pouvez accéder au serveur Discord pour une entraide par chat

16 - Live Coding : Créer un site multilingue avec Symfony 4
Article publié le - Modifié le

Catégories : Tutoriel Symfony Live-Coding

Mots-clés : Tutoriel Controllers MVC Views Symfony Live-Coding traduction

Partager : Partager sur Facebook Partager sur Twitter Partager sur LinkedIn