diff --git a/aspnetcore/blazor/globalization-localization.md b/aspnetcore/blazor/globalization-localization.md index 9a47ee9280ea..806358187241 100644 --- a/aspnetcore/blazor/globalization-localization.md +++ b/aspnetcore/blazor/globalization-localization.md @@ -183,9 +183,9 @@ Optionally, add a menu item to the navigation in the `NavMenu` component (`NavMe Add the [`Microsoft.Extensions.Localization`](https://www.nuget.org/packages/Microsoft.Extensions.Localization) package to the app. -The [`Accept-Language` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Language) is set by the browser and controlled by the user's language preferences in browser settings. In browser settings, a user sets one or more preferred languages in order of preference. The order of preference is used by the browser to set quality values (`q`, 0-1) for each language in the header. The following example specifies United States English, English, and Chilean Spanish with a preference for United States English or English: +The [`Accept-Language` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept-Language) is set by the browser and controlled by the user's language preferences in browser settings. In browser settings, a user sets one or more preferred languages in order of preference. The order of preference is used by the browser to set quality values (`q`, 0-1) for each language in the header. The following example specifies United States English, English, and Costa Rican Spanish with a preference for United States English or English: -**Accept-Language**: en-US,en;q=0.9,es-CL;q=0.8 +**Accept-Language**: en-US,en;q=0.9,es-CR;q=0.8 The app's culture is set by matching the first requested language that matches a supported culture of the app. @@ -218,17 +218,17 @@ Add the following line to the `Program` file where services are registered: builder.Services.AddLocalization(); ``` -In ***server-side development***, you can specify the app's supported cultures immediately after Routing Middleware is added to the processing pipeline. The following example configures supported cultures for United States English and Chilean Spanish: +In ***server-side development***, you can specify the app's supported cultures immediately after Routing Middleware is added to the processing pipeline. The following example configures supported cultures for United States English and Costa Rican Spanish: ```csharp app.UseRequestLocalization(new RequestLocalizationOptions() - .AddSupportedCultures(new[] { "en-US", "es-CL" }) - .AddSupportedUICultures(new[] { "en-US", "es-CL" })); + .AddSupportedCultures(new[] { "en-US", "es-CR" }) + .AddSupportedUICultures(new[] { "en-US", "es-CR" })); ``` For information on ordering the Localization Middleware in the middleware pipeline of the `Program` file, see . -Use the `CultureExample1` component shown in the [Demonstration component](#demonstration-component) section to study how globalization works. Issue a request with United States English (`en-US`). Switch to Chilean Spanish (`es-CL`) in the browser's language settings. Request the webpage again. +Use the `CultureExample1` component shown in the [Demonstration component](#demonstration-component) section to study how globalization works. Issue a request with United States English (`en-US`). Switch to Costa Rican Spanish (`es-CR`) in the browser's language settings. Request the webpage again. > [!NOTE] > Some browsers force you to use the default language setting for both requests and the browser's own UI settings. This can make changing the language back to one that you understand difficult because all of the setting UI screens might end up in a language that you can't read. A browser such as [Opera](https://www.opera.com/download) is a good choice for testing because it permits you to set a default language for webpage requests but leave the browser's settings UI in your language. @@ -238,7 +238,7 @@ When the culture is United States English (`en-US`), the rendered component uses * **Date**: 6/7/2021 6:45:22 AM * **Number**: 1,999.69 -When the culture is Chilean Spanish (`es-CL`), the rendered component uses day/month date formatting (`7/6`), 24-hour time, and period separators in numbers with a comma for the decimal value (`1.999,69`): +When the culture is Costa Rican Spanish (`es-CR`), the rendered component uses day/month date formatting (`7/6`), 24-hour time, and period separators in numbers with a comma for the decimal value (`1.999,69`): * **Date**: 7/6/2021 6:49:38 * **Number**: 1.999,69 @@ -265,7 +265,7 @@ By default, the Intermediate Language (IL) Linker configuration for client-side The app's culture can be set in JavaScript when Blazor starts with the `applicationCulture` Blazor start option. The following example configures the app to launch using the United States English (`en-US`) culture. -Prevent Blazor autostart by adding `autostart="false"` to Blazor's script tag: +Prevent Blazor autostart by adding `autostart="false"` to [Blazor's ` @@ -273,7 +273,7 @@ Prevent Blazor autostart by adding `autostart="false"` to Blazor's script tag: In the preceding example, the `{BLAZOR SCRIPT}` placeholder is the Blazor script path and file name. For the location of the script, see . -Add the following ` +``` + +> [!NOTE] +> The preceding example pollutes the client with global functions. For a better approach in production apps, see [JavaScript isolation in JavaScript modules](xref:blazor/js-interop/call-javascript-from-dotnet#javascript-isolation-in-javascript-modules). + +Add the following `@code` block to the bottom of the `App` component file: + +```razor +@code { + [CascadingParameter] + public HttpContext? HttpContext { get; set; } + + protected override void OnInitialized() + { + HttpContext?.Response.Cookies.Append( + CookieRequestCultureProvider.DefaultCookieName, + CookieRequestCultureProvider.MakeCookieValue( + new RequestCulture( + CultureInfo.CurrentCulture, + CultureInfo.CurrentUICulture))); + } +} +``` + +If the server project isn't configured to process controller actions: + +* Add MVC services by calling on the service collection in the `Program` file: + + ```csharp + builder.Services.AddControllers(); + ``` + +* Add controller endpoint routing in the `Program` file by calling on the (`app`): + + ```csharp + app.MapControllers(); + ``` + +To allow a user to select a culture for SSR components, use a *redirect-based approach* with a localization cookie. The app persists the user's selected culture via a redirect to a controller. The controller sets the user's selected culture into a cookie and redirects the user back to the original URI. The process is similar to what happens in a web app when a user attempts to access a secure resource, where the user is redirected to a sign-in page and then redirected back to the original resource. + +`Controllers/CultureController.cs`: + +```csharp +using Microsoft.AspNetCore.Localization; +using Microsoft.AspNetCore.Mvc; + +[Route("[controller]/[action]")] +public class CultureController : Controller +{ + public IActionResult Set(string culture, string redirectUri) + { + if (culture != null) + { + HttpContext.Response.Cookies.Append( + CookieRequestCultureProvider.DefaultCookieName, + CookieRequestCultureProvider.MakeCookieValue( + new RequestCulture(culture, culture))); + } + + return LocalRedirect(redirectUri); + } +} +``` + +> [!WARNING] +> Use the action result, as shown in the preceding example, to prevent open redirect attacks. For more information, see . + +Add the `CultureSelector` component to the `MainLayout` component. Place the following markup inside the closing `` tag in the `Components/Layout/MainLayout.razor` file: + +```razor +
+ +
+``` + +Use the `CultureExample1` component shown in the [Demonstration component](#demonstration-component) section to study how the preceding example works. + +In the server project, place the following `CultureServer` component to study how globalization works for SSR components. + +`Components/Pages/CultureServer.razor`: + +```razor +@page "/culture-server" +@rendermode InteractiveServer +@using System.Globalization + +Culture Server + +

Culture Server

+ +

+ CurrentCulture: @CultureInfo.CurrentCulture +

+ +

Rendered values

+ +
    +
  • Date: @dt
  • +
  • Number: @number.ToString("N2")
  • +
+ +

<input> elements that don't set a type

+ +

+ The following <input> elements use + CultureInfo.CurrentCulture. +

+ +
    +
  • +
  • +
+ +

<input> elements that set a type

+ +

+ The following <input> elements use + CultureInfo.InvariantCulture. +

+ +
    +
  • +
  • +
+ +@code { + private DateTime dt = DateTime.Now; + private double number = 1999.69; +} +``` + +Add both the `CultureClient` and `CultureServer` components to the sidebar navigation in `Components/Layout/NavMenu.razor`: + +```razor + + +``` + +### Interactive Auto components + +The guidance in this section also works for components that adopt the Interactive Auto render mode: + +```razor +@rendermode InteractiveAuto +``` + +:::moniker-end + ## Localization If the app doesn't already support dynamic culture selection, add the [`Microsoft.Extensions.Localization`](https://www.nuget.org/packages/Microsoft.Extensions.Localization) package to the app. @@ -816,7 +1206,7 @@ If the app doesn't already support dynamic culture selection: :::moniker range=">= aspnetcore-6.0" * Add localization services to the app with . -* Specify the app's default and supported cultures in the `Program` file. The following example configures supported cultures for United States English and Chilean Spanish. +* Specify the app's default and supported cultures in the `Program` file. The following example configures supported cultures for United States English and Costa Rican Spanish. ```csharp builder.Services.AddLocalization(); @@ -825,7 +1215,7 @@ builder.Services.AddLocalization(); Immediately after Routing Middleware is added to the processing pipeline: ```csharp -var supportedCultures = new[] { "en-US", "es-CL" }; +var supportedCultures = new[] { "en-US", "es-CR" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) @@ -841,7 +1231,7 @@ For information on ordering the Localization Middleware in the middleware pipeli :::moniker range="< aspnetcore-6.0" * Add localization services to the app with . -* Specify the app's default and supported cultures in `Startup.Configure` (`Startup.cs`). The following example configures supported cultures for United States English and Chilean Spanish. +* Specify the app's default and supported cultures in `Startup.Configure` (`Startup.cs`). The following example configures supported cultures for United States English and Costa Rican Spanish. In `Startup.ConfigureServices` (`Startup.cs`): @@ -852,7 +1242,7 @@ services.AddLocalization(); In `Startup.Configure` immediately after Routing Middleware is added to the processing pipeline: ```csharp -var supportedCultures = new[] { "en-US", "es-CL" }; +var supportedCultures = new[] { "en-US", "es-CR" }; var localizationOptions = new RequestLocalizationOptions() .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures)