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:
//...
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
.
- Sous
Web.Mvc/Views/Shared
->Add
->Razor MVC Partial View
- Nommez la vue partielle
_ChangementLangue
- 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> - 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
@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:
@{
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.
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
-
Sous
Web.Mvc/Controllers
->Add
->Controller
-
Nommer le contrôleur
LocaleController
-
Ajoutez une fonction
Update
répondant à une requêtePATCH
.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)
{
}infoculture
: la nouvelle localeurlRetour
: vers où rediriger l'utilisateur après la configuration de langue
infoOn aurait pu utiliser n'importe quel nom d'action ici, comme
ChangerLangue
, mais une action standard commeUpdate
a plein de sens dans le contexte deLocaleController
: on cherche à mettre à jour la locale.
Configurer le cookie
[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);
}
Response.Cookies.Append
ajoute un cookie à la réponseCookieRequestCultureProvider.DefaultCookieName
utilise le nom de cookie par défaut pour le cookie de langueCookieRequestCultureProvider.MakeCookieValue
assigne la valeur de la locale au cookiereturn 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.
-
Remplacer le
<span>
dans la boite de sélection par un formulaire vers l'actionUpdate
deLocaleController
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> -
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">
-
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">
-
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}";
} -
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.
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:
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.