Aller au contenu principal

32-1 - Changement de langue (MVC)

Les fichiers ressources sont utilisés, mais nous n'avons pas de mécanisme de changement de langue en place.

.NET Core MVC propose un mécanisme natif au cadriciel pour gérer les langues et le changement de langue.

Configuration

Afin de supporter différentes cultures, on doit configurer l'application pour:

  • Dire quelles sont les locales supportées (ex.: fr, en, fr-CA, en-US, ...)
  • Quelle est la locale par défaut

Dans Program.cs, à l'aide du builder de l'application, on peut configurer ces options:

Snowfall.Web.Mvc/Program.cs
//...

builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new List<CultureInfo> { new CultureInfo("fr"), new CultureInfo("en") };
options.DefaultRequestCulture = new RequestCulture("fr");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});

//...

Puis, juste après la ligne app.UseSession():

//...
app.UseSession();

// Permet de configurer la langue via la requête (query string, cookie ou header http)
app.UseRequestLocalization();
///..

Créer une vue partielle de changement de langue

On voudra afficher un menu déroulant permettant la sélection d'une langue. Cette option sera ajoutée à la barre de navigation et afin de bien séparer le HTML et le code lié à cet élément d'interface, nous créerons une vue partielle _ChangementLangue sous le dossier Mvc/Views/Shared.

  1. Sous Web.Mvc/Views/Shared -> Add -> Razor MVC Partial View
  2. Nommez la vue partielle _ChangementLangue
  3. Allons-y avec une coquille de menu déroulant Bootstrap
    Snowfall.Web.Mvc/Views/Shared/_ChangementLangue.cshtml
    <li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
    Nom de la langue
    </a>
    <ul class="dropdown-menu dropdown-menu-end">
    </ul>
    </li>
  4. Ajouter à la navbar le menu de changement de langue
    Snowfall.Web.Mvc/Views/Shared/_Layout.cshtml
    <!-- ... -->
    <li class="nav-item">
    <a
    class="nav-link @(controller == "Comptes" ? "active" : String.Empty)"
    asp-controller="Comptes"
    asp-action="New">
    Inscription
    </a>
    </li>
    }
    <partial name="_ChangementLangue" />
    </ul>
    <!-- ... -->

Si vous lancez l'application, vous devriez voir un menu déroulant vide de la barre de navigation.

Afficher les locales supportées

On peut utiliser un bloc de code tel que celui-ci dans la vue partielle pour récupérer:

  • requestCulture: la locale associée à la requête (bref, la locale courante)
  • supportedUiCultures: les locales supportées par l'application
Snowfall.Web.Mvc/Views/Shared/_ChangementLangue.cshtml
@using Microsoft.AspNetCore.Localization
@using Microsoft.Extensions.Options
@inject IOptions<RequestLocalizationOptions> requestLocalizationOptions

@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var supportedUiCultures = requestLocalizationOptions.Value.SupportedUICultures;
}

Ensuite, on peut utiliser ces variables pour afficher la langue courante, ainsi que les autres valeurs possibles:

Snowfall.Web.Mvc/Views/Shared/_ChangementLangue.cshtml
@{
var requestCulture = Context.Features.Get<IRequestCultureFeature>();
var supportedUiCultures = requestLocalizationOptions.Value.SupportedUICultures;
}

<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
@requestCulture?.RequestCulture.UICulture.Name.ToUpper()
</a>
<ul class="dropdown-menu dropdown-menu-end">
@foreach (var culture in supportedUiCultures)
{
<li>
@culture.Name.ToUpper()
</li>
}
</ul>
</li>

Vous aurez ainsi une boîte de sélection avec les différentes options possibles.

Imgur

Changer la langue

Pour changer la langue et se souvenir des préférences de l'utilisateur entre les requêtes (on ne veut pas que l'utilisateur ait à changer la langue à chaque page!), on utilisera les cookies.

.NET Core MVC supporte nativement l'assignation d'une préférence de langue via cookies.

Pour se faire, lorsque l'utilisateur veut changer de langue, la demande devra être traitée par le serveur afin de configurer le cookie avec le choix de l'utilisateur.

Créer le contrôleur LocaleController

  1. Sous Web.Mvc/Controllers -> Add -> Controller

  2. Nommer le contrôleur LocaleController

  3. Ajoutez une fonction Update répondant à une requête PATCH.

    Snowfall.Web.Mvc/Controllers/LocaleController.cs
    /// <summary>
    /// Permets de changer la locale de l'utilisateur et de configurer le cookie de préférence
    /// </summary>
    /// <param name="culture"></param>
    /// <param name="urlRetour"></param>
    /// <returns></returns>
    [HttpPatch]
    public async Task<IActionResult> Update(string culture, string urlRetour)
    {

    }
    info
    • culture: la nouvelle locale
    • urlRetour: vers où rediriger l'utilisateur après la configuration de langue
    info

    On aurait pu utiliser n'importe quel nom d'action ici, comme ChangerLangue, mais une action standard comme Update a plein de sens dans le contexte de LocaleController: on cherche à mettre à jour la locale.

[HttpPatch]
public async Task<IActionResult> Update(string culture, string urlRetour)
{
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
);

return LocalRedirect(urlRetour);
}
info
  • Response.Cookies.Append ajoute un cookie à la réponse
  • CookieRequestCultureProvider.DefaultCookieName utilise le nom de cookie par défaut pour le cookie de langue
  • CookieRequestCultureProvider.MakeCookieValue assigne la valeur de la locale au cookie
  • return LocalRedirect(urlRetour); redirige vers l'URL de retour

Appeler l'action du contrôleur

Pour appeler l'action du contrôleur qui est responsable de configurer la langue active et le cookie, on aura besoin d'un formulaire dans le menu déroulant.

  1. Remplacer le <span> dans la boite de sélection par un formulaire vers l'action Update de LocaleController

    Snowfall.Web.Mvc/Views/Shared/_ChangementLangue.cshtml
    <li class="nav-item dropdown">
    <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" aria-expanded="false">
    @requestCulture?.RequestCulture.UICulture.Name.ToUpper()
    </a>
    <ul class="dropdown-menu dropdown-menu-end">
    @foreach (var culture in supportedUiCultures)
    {
    <li>
    <form asp-controller="Locale" asp-action="Update" asp class="dropdown-item">
    <input type="hidden" name="_method" value="PATCH"/>

    <button class="dropdown-item">@culture.Name.ToUpper()</button>
    </form>
    </li>
    }
    </ul>
    </li>
  2. Pour envoyer la culture, il est possible de simplement utiliser asp-route-culture sur le formulaire. Cela aura pour effet de l'envoyer en query string, ce qui est bien correct dans le cas qui nous occupe.

    <form asp-controller="Locale" asp-action="Update" asp-route-culture="@culture.Name" class="dropdown-item">
  3. Puis, pour envoyer l'URL de retour, on peut utiliser le même principe avec asp-route-urlRetour:

    <form asp-controller="Locale" asp-action="Update" asp-route-culture="@culture.Name" asp-route-urlRetour="" class="dropdown-item">
  4. Mais quoi passer comme valeur à UrlRetour? Au fond, on veut passer l'URL courante, pour revenir où nous sommes actuellement. On peut utiliser Context.Request.Path pour obtenir la valeur de l'URL actuelle.

    Snowfall.Web.Mvc/Views/Shared/_ChangementLangue.cshtml
    @{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var supportedUiCultures = requestLocalizationOptions.Value.SupportedUICultures;
    var urlRetour = string.IsNullOrEmpty(Context.Request.Path) ? "~/" : $"~{Context.Request.Path.Value}";
    }
  5. Pour finalement utiliser urlRetour en appelant l'action du contrôleur

    <form asp-controller="Locale"
    asp-action="Update"
    asp-route-culture="@culture.Name"
    asp-route-urlRetour="@urlRetour"
    class="dropdown-item">

Test

Vous pouvez maintenant tenter de changer de langue et même si la page n'est pas traduite, vous devriez observer des changements au niveau du format des dates et des prix entre le français et l'anglais.

Imgur

Traduire un fichier ressource

Pour traduire un fichier ressource, vous créez simplement une version avec le même nom, mais possédant dans son extension la locale ciblée par le fichier.

Par exemple:

Imgur

attention

Pour la remise finale, vous devrez traduire au moins une page significative en entier et que le changement de langue soit fonctionnel pour votre site.