You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
6.7 KiB
225 lines
6.7 KiB
![]()
2 years ago
|
---
|
||
|
sidebar_position: 2
|
||
|
title: User language selection
|
||
|
---
|
||
|
|
||
|
## Install localization
|
||
|
|
||
|
Install the `Microsoft.Extensions.Localization` package.
|
||
|
|
||
|
## Configure location
|
||
|
|
||
|
Open the `Program.cs` file:
|
||
|
|
||
|
```csharp title="Program.cs"
|
||
|
...
|
||
|
|
||
|
builder.Services.AddBlazoredModal();
|
||
|
|
||
|
// highlight-start
|
||
|
// Add the controller of the app
|
||
|
builder.Services.AddControllers();
|
||
|
|
||
|
// Add the localization to the app and specify the resources path
|
||
|
builder.Services.AddLocalization(opts => { opts.ResourcesPath = "Resources"; });
|
||
|
|
||
|
// Configure the localtization
|
||
|
builder.Services.Configure<RequestLocalizationOptions>(options =>
|
||
|
{
|
||
|
// Set the default culture of the web site
|
||
|
options.DefaultRequestCulture = new RequestCulture(new CultureInfo("en-US"));
|
||
|
|
||
|
// Declare the supported culture
|
||
|
options.SupportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
|
||
|
options.SupportedUICultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("fr-FR") };
|
||
|
});
|
||
|
// highlight-end
|
||
|
|
||
|
var app = builder.Build();
|
||
|
|
||
|
...
|
||
|
|
||
|
app.UseRouting();
|
||
|
|
||
|
// highlight-start
|
||
|
// Get the current localization options
|
||
|
var options = ((IApplicationBuilder)app).ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
|
||
|
|
||
|
if (options?.Value != null)
|
||
|
{
|
||
|
// use the default localization
|
||
|
app.UseRequestLocalization(options.Value);
|
||
|
}
|
||
|
|
||
|
// Add the controller to the endpoint
|
||
|
app.UseEndpoints(endpoints =>
|
||
|
{
|
||
|
endpoints.MapControllers();
|
||
|
});
|
||
|
// highlight-end
|
||
|
|
||
|
app.MapBlazorHub();
|
||
|
|
||
|
...
|
||
|
```
|
||
|
|
||
|
In order to be able to change the culture, we will have to declare a controller.
|
||
|
|
||
|
Create a new folder at the root of the site named `Controllers`.
|
||
|
|
||
|
Create a new class called `CultureController`.
|
||
|
|
||
|
```csharp title="Controllers/CultureController.cs"
|
||
|
using Microsoft.AspNetCore.Localization;
|
||
|
using Microsoft.AspNetCore.Mvc;
|
||
|
|
||
|
/// <summary>
|
||
|
/// The culture controller.
|
||
|
/// </summary>
|
||
|
[Route("[controller]/[action]")]
|
||
|
public class CultureController : Controller
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Sets the culture.
|
||
|
/// </summary>
|
||
|
/// <param name="culture">The culture.</param>
|
||
|
/// <param name="redirectUri">The redirect URI.</param>
|
||
|
/// <returns>
|
||
|
/// The action result.
|
||
|
/// </returns>
|
||
|
public IActionResult SetCulture(string culture, string redirectUri)
|
||
|
{
|
||
|
if (culture != null)
|
||
|
{
|
||
|
// Define a cookie with the selected culture
|
||
|
this.HttpContext.Response.Cookies.Append(
|
||
|
CookieRequestCultureProvider.DefaultCookieName,
|
||
|
CookieRequestCultureProvider.MakeCookieValue(
|
||
|
new RequestCulture(culture)));
|
||
|
}
|
||
|
|
||
|
return this.LocalRedirect(redirectUri);
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Language selector component
|
||
|
|
||
|
The following `CultureSelector` component shows how to set the user's culture selection.
|
||
|
The component is placed in the `Shared` folder for use throughout the application.
|
||
|
|
||
|
Create the `Shared/CultureSelector.razor` component.
|
||
|
|
||
|
```cshtml title="Shared/CultureSelector.razor"
|
||
|
@using System.Globalization
|
||
|
@inject NavigationManager NavigationManager
|
||
|
|
||
|
<p>
|
||
|
<label>
|
||
|
Select your locale:
|
||
|
<select @bind="Culture">
|
||
|
@foreach (var culture in supportedCultures)
|
||
|
{
|
||
|
<option value="@culture">@culture.DisplayName</option>
|
||
|
}
|
||
|
</select>
|
||
|
</label>
|
||
|
</p>
|
||
|
|
||
|
@code
|
||
|
{
|
||
|
private CultureInfo[] supportedCultures = new[]
|
||
|
{
|
||
|
new CultureInfo("en-US"),
|
||
|
new CultureInfo("fr-FR")
|
||
|
};
|
||
|
|
||
|
private CultureInfo Culture
|
||
|
{
|
||
|
get => CultureInfo.CurrentCulture;
|
||
|
set
|
||
|
{
|
||
|
if (CultureInfo.CurrentUICulture == value)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var culture = value.Name.ToLower(CultureInfo.InvariantCulture);
|
||
|
|
||
|
var uri = new Uri(this.NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
|
||
|
var query = $"?culture={Uri.EscapeDataString(culture)}&" + $"redirectUri={Uri.EscapeDataString(uri)}";
|
||
|
|
||
|
// Redirect the user to the culture controller to set the cookie
|
||
|
this.NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Add in the `<div class="top-row px-4">` div in `Shared/MainLayout.razor`, add the `CultureSelector` component:
|
||
|
|
||
|
```cshtml title="Shared/MainLayout.razor"
|
||
|
...
|
||
|
<main>
|
||
|
<div class="top-row px-4">
|
||
|
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
|
||
|
|
||
|
// highlight-start
|
||
|
<div class="px-4">
|
||
|
<CultureSelector />
|
||
|
</div>
|
||
|
// highlight-end
|
||
|
</div>
|
||
|
...
|
||
|
```
|
||
|
|
||
|
|
||
|
Add the following code in the `Pages/Index.razor` file to visualize the language change.
|
||
|
|
||
|
```cshtml title="Pages/Index.razor"
|
||
|
@using System.Globalization
|
||
|
...
|
||
|
|
||
|
<p>
|
||
|
<b>CurrentCulture</b>: @CultureInfo.CurrentCulture
|
||
|
</p>
|
||
|
|
||
|
...
|
||
|
```
|
||
|
|
||
|
## Concept: Controllers
|
||
|
|
||
|
Some actions are not possible with the razor model, such as the declaration of cookies on the fly, to declare a cookie it is absolutely necessary that no HTML element be displayed before.
|
||
|
|
||
|
In order to overcome this problem, we therefore use an MVC type controller without the View and Model part.
|
||
|
|
||
|
Here is a small definition of the MVC architecture:
|
||
|
|
||
|
The Model-View-Controller (MVC) architectural pattern separates an app into three main components: **M**odel, **V**iew, and **C**ontroller.
|
||
|
The MVC pattern helps you create apps that are more testable and easier to update than traditional monolithic apps.
|
||
|
|
||
|
MVC-based apps contain:
|
||
|
|
||
|
* **M**odels: Classes that represent the data of the app. The model classes use validation logic to enforce business rules for that data. Typically, model objects retrieve and store model state in a database.
|
||
|
* **V**iews: Views are the components that display the app's user interface (UI). Generally, this UI displays the model data.
|
||
|
* **C**ontrollers: Classes that:
|
||
|
* Handle browser requests.
|
||
|
* Retrieve model data.
|
||
|
* Call view templates that return a response.
|
||
|
|
||
|
In an MVC app, the view only displays information.
|
||
|
The controller handles and responds to user input and interaction.
|
||
|
For example, the controller handles URL segments and query-string values, and passes these values to the model. The model might use these values to query the database.
|
||
|
|
||
|
For example:
|
||
|
|
||
|
* `https://localhost:5001/Home/Privacy`: specifies the `Home` controller and the `Privacy` action.
|
||
|
* `https://localhost:5001/Movies/Edit/5`: is a request to edit the movie with `ID=5` using the `Movies` controller and the `Edit` action.
|
||
|
|
||
|
|
||
|
The MVC architectural pattern separates an app into three main groups of components: Models, Views, and Controllers.
|
||
|
This pattern helps to achieve separation of concerns: The UI logic belongs in the view. Input logic belongs in the controller.
|
||
|
Business logic belongs in the model.
|
||
|
This separation helps manage complexity when building an app, because it enables work on one aspect of the implementation at a time without impacting the code of another.
|
||
|
For example, you can work on the view code without depending on the business logic code.
|