Laravel 5

Laravel 5.7 par la pratique – Les langues

Dans ce chapitre on va s’intéresser à l’aspect multi-langage. Pour le moment notre galerie est en français mais on a fait en sorte que les textes soient faciles à traduire en utilisant dans le code les helpers de Laravel. On va donc ajouter maintenant l’anglais à notre galerie. Ça ne concernera évidemment que l’interface et pas les données, ce qui serait une autre histoire…

La configuration

Dans le fichier config/app.php on a des réglages pour les langues :

'locale' => 'fr',

'fallback_locale' => 'en',

On a fixé la locale au français (fr) et la langue par défaut en cas d’absence de traduction à l’anglais (en).

On va ajouter un réglage avec les langues qu’on va mettre en œuvre et qui devront avoir les traductions présentes :

'locales' => ['fr', 'en',],

On va ajouter un fichier de configuration pour les locales :

Ce fichier est issu de ce dépôt Github. Il permet d’avoir par pays le code pour Carbon et celui pour setLocale().

Route, contrôleur et middleware

Route

On ajoute la route pour le changement de la langue :

Route::name('language')->get('language/{lang}', 'HomeController@language');

Contrôleur

Et on ajoute la fonction dans HomeController :

public function language(String $locale)
{
    $locale = in_array($locale, config('app.locales')) ? $locale : config('app.fallback_locale');

    session(['locale' => $locale]);

    return back();
}

On reçoit une locale en paramètre. Si elle est présente dans le tableau de la configuration on fixe cette locale en session, sinon on se rabat sur la locale par défaut.

Middleware

Il nous faut maintenant un middleware qui va vérifier si on a une locale en session pour réellement l’affecter. Si ce n’est pas le cas essayer de définir la langue de l’utilisateur. On va aussi fixer la locale pour les dates.

php artisan make:middleware Locale

Et on code ainsi :

public function handle($request, Closure $next)
{
    if (!session ()->has ('locale')) {
        session (['locale' => $request->getPreferredLanguage (config ('app.locales'))]);
    }
    $locale = session ('locale');
    app ()->setLocale ($locale);
    setlocale (LC_TIME, app()->environment('local') ? $locale : config('locale.languages')[$locale][1]);
    return $next ($request);
}

Et on le référence dans app/Http/Kernel :

protected $middlewareGroups = [
    'web' => [
        ... 

        \App\Http\Middleware\Locale::class,
        \App\Http\Middleware\Settings::class,
    ],

    ...
];

Le menu

On va ajouter un menu déroulant pour le choix de la locale dans views/layouts/app :

<ul class="navbar-nav mr-auto">
    <li class="nav-item dropdown">
        <a class="nav-link" href="#" id="navbarDropdownFlag" role="button" data-toggle="dropdown"
            aria-haspopup="true" aria-expanded="false">
            <img width="32" height="32" alt="{{ session('locale') }}"
                    src="{!! asset('images/flags/' . session('locale') . '-flag.png') !!}"/>
        </a>
        <div id="flags" class="dropdown-menu" aria-labelledby="navbarDropdownFlag">
            @foreach(config('app.locales') as $locale)
                @if($locale != session('locale'))
                    <a class="dropdown-item" href="{{ route('language', $locale) }}">
                        <img width="32" height="32" alt="{{ session('locale') }}"
                                src="{!! asset('images/flags/' . $locale . '-flag.png') !!}"/>
                    </a>
                @endif
            @endforeach
        </div>
    </li>

Et on va voir le résultat :

Je ne trouve pas trop élégant la largueur de la zone pour le drapeau.On va arranger ça dans resources/sass/_variables.scss. On va en profiter pour changer la typographie et un peu la pagination :

// Body
$body-bg: #343a40;

// Menu
$dropdown-min-width: 5rem;

// Typography
$font-family-sans-serif: "Raleway", sans-serif;
$font-size-base: 0.9rem;
$line-height-base: 1.6;
$text-color: #636b6f;

// Card
$card-border-width: 4px;
$card-border-radius: .3rem;
$card-border-color: rgba(255, 242, 242, .3);

// Pagination
$pagination-active-bg: grey;
$pagination-active-border-color: grey;

On lance npm…

Et c’est maintenant plus équilibré :

Pour le moment le changement de langue ne se voit que dans les validations :

Un package

Il nous faut créer un fichier JSON avec toutes les traductions pour l’anglais. On pourrait faire ça en explorant tout le code avec des copier/coller, ça serait vraiment laborieux !

On va plutôt utiliser un package pour nous aider. Comme je n’en ai pas vraiment trouvé un qui me plaise j’en ai créé un. On va commencer par l’installer :

composer require bestmomo/laravel5-artisan-language --dev

On a maintenant 4 commandes de plus dans artisan :

On va utiliser la deuxième :

php artisan language:make en

Le fichier JSON a été créé et on a tous les textes par ordre alphabétique qui attendent leur traduction :

{
    "A l'url :": "",
    "A propos": "",
    "Administration": "",
    "Adresse email": "",
    "Adresse web :": "",
    "Adulte": ""

    ...

On ajoute donc les traductions. Comme le fichier est assez gros vous pouvez le récupérer sur github.

Maintenant si on passe à l’anglais on a bien les textes dans cette langue :

Vous pourrez aussi remarquer que les dates sont maintenant correctes.

C’est le dernier chapitre de cette série. Il reste quelques éléments dont je n’ai pas parlé, comme les pages d’information, mais que vous pouvez retrouver dans le dépôt Github.

Conclusion

Dans ce chapitre on a :

  • prévu la configuration pour les locales
  • ajouté la route, la fonction du contrôleur et un middleware pour le changement de locale
  • ajouté un menu déroulant avec les drapeaux des langues disponibles
  • installé un package pour créer le fichier de la nouvelle langue et ajouté ainsi les traductions

 

Print Friendly, PDF & Email

17 commentaires

  • Phil34

    Bonjour
    Merci pour tes cours c’est super!
    J’ai cependant quelques petits pb : Comme msbiz je n’ai pas tester les pages précédentes.
    J’ai une erreur avec Settings::class dans le Kernel : Class App\Http\Middleware\Settings does not exist…..Si je le met pas ça marche plutôt bien.
    Sauf que le changement de langue ne fonctionne pas en mode non connecté.
    Je suis intéressé aussi pour modifier le css mais npm install ne fonctionne pas.
    Je débute sur Laravel. Je suis en 5.8

  • cyril

    Bonjour,

    Je rencontre un souci avec la génération du fichier de langue, les points à la fin des phrases et les simples quotes posent problème.

    Par exemple:
    {{ __(« A fresh verification link has been sent to your email address. ») }}
    va donner:
    « A fresh verification link has been sent to your email address.\ ») }}\n\t\t\t\t\t\t\n\t\t\t\t\t@endif\n\n\t\t\t\t\t{{ __(« : «  »,

    Et:
    __(‘Capture d\’écran’)
    va donner:
    « Capture d\\ »: «  »,

    Merci par avance

    • cyril

      Alors j’ai résolu mes problèmes en modifiant l’expression régulière avec la suivante:

      (@lang|__|\$t|\$tc)\s*\([\' »]([^ »\’\\\\]*(?:\\\\.[^ »\’\\\\]*)*)[\' »]\)*

      et en rajoutant à la collection :

      ->map(function ($item) {
      return str_replace(« \\' », « ‘ », $item);
      })

      Par contre je n’ai pas assez de recul pour voir si elle est fiable (j’ai environ 600 chaînes)

          • msbiz

            Effectivement, quand je fais un dd(config(‘app.locales’)); il me renvoi « null »

            J’ai installé ton album, cela fonctionne parfaitement bien, j’ai pas du tout ce genre de message d’erreur.

            Je n’ai pas suivi les étapes précédente de ton tuto, j’ai directement commencé par cette étape : Laravel 5.7 par la pratique – Les langues et je l’ai directement intégré à mon projet. Donc il doit y avoir quelques chose qui passe pas juste.

            Tu sais si je dois installer des packages? ou changer quelque chose dans le code ? Que peux être tu as fais dans les étapes précédente et qui sont nécessaire dans celle-ci pour le bon fonctionnement.

            Merci d’avance & bonne année !

          • msbiz

            J’ ai résolu le problème !

            Tout était juste dans mon code, mais laravel me retournait NULL dans la variable config(‘app.locales’) car il avait gardé en cache les anciennes valeurs du fichiers app.php.

            Pour résoudre ce problème, il suffit de faire un php artisan config:clear et Laravel va prendre les nouvelles valeurs entrée dans le fichiers app.php

            Cordialement

  • msbiz

    Bonjour,

    J’ ai le message d’erreur suivant quand j’essaye d’appliquer ce code à mon projet.

    ErrorException (E_ERROR)
    Invalid argument supplied for foreach() (View: /home/vagrant/code/starter/resources/views/frontend/includes/header.blade.php) (View: /home/vagrant/code/starter/resources/views/frontend/includes/header.blade.php) (View: /home/vagrant/code/starter/resources/views/frontend/includes/header.blade.php)

    Laravel m’indique en souligné cela :

    addLoop($__currentLoopData); foreach($__currentLoopData as $locale): $__env->incrementLoopIndices(); $loop = $__env->getLastLoop(); ?>

    Ce message d’erreur apparaît quand j’ajoute la dropdown dans la vue qui doit afficher les drapeaux.

    Et quand je vais directement à l’url monsite.test//language/fr ou /en j’ai ce message d’erreur :

    in_array() expects parameter 2 to be array, null given

    et Laravel me souligne cette ligne de code :

    $locale = in_array($locale, config(‘app.locales’)) ? $locale : config(‘app.fallback_locale’);

    Merci d’avance pour votre aide !

    Bien entendu j’ai vérifié plusieurs fois tout les étapes que vous indiqué et tout est pareil. Je n’arrive pas à trouver d’où viens mon erreur.

    PS : Je suis sous Laravel 5.7

      • mpeleboy

        Bonjour
        Je devellope une application (inspirée du TUTO GALERIE PHOTOS) dans laquelle les publications de utilisateurs peuvent recevoir des notes.
        Devant le nom de chaque utilisateur, Je souhaite Additionner et Afficher la somme des notes de toutes ses publications qui ont recu des notes.
        Voici les champs de La TABLE ( post_user )
        – id
        – created_at
        – updated_at
        – note
        – user_id
        – post_id

        Je n’ai aucune idée de comment m’y prendre pour la requete SQL , j’avoue aussi que je suis nouveau dans LARAVEL.

        Merci…

Laisser un commentaire