🟥 Not applicable to Blazor WebAssembly
One of the biggest challenges of building multilingual websites is managing translations efficiently. Blazor provides a powerful feature called deferred translation, which enables the seamless translation of text in your web application. With deferred translation, when a user changes the language preference, the website remembers it for future visits, but the language selection may not take effect until the user refreshes the website. In this tutorial, we will cover:
You can download the example code used in this topic on GitHub.
The browser language strategy is one of the methods that can be used to determine a user's preferred language in a multilingual website.
When a user visits a website, their browser sends a request header that contains information about the user's preferred language(s). This information is based on the language settings that the user has configured in their browser.
The browser language strategy works by checking the value of the Accept-Language
header in the incoming request, and then using that information to select the appropriate language for the website. If the website supports the user's preferred language, it will display content in that language. If the preferred language is not supported, the website may fall back to a default language or display an error message.
builder.Services.Configure<RequestLocalizationOptions>(options => { // You can set the default language using the following method: // options.SetDefaultCulture("fr"); options.AddSupportedCultures(new[] { "en", "fr" }); options.AddSupportedUICultures(new[] { "en", "fr" }); options.RequestCultureProviders = new List<IRequestCultureProvider>() { new AcceptLanguageHeaderRequestCultureProvider() }; });
Blazor can use the cookie language selection strategy to determine a user's preferred language on a website. If a cookie with the preferred language exists, the website can display content in that language by default. It's worth noting that while cookies can be used for language selection, MDN recommends using alternative browser storage methods like localStorage, sessionStorage, or IndexedDB due to their better performance and security.
builder.Services.AddControllers(); builder.Services.AddLocalization(...); builder.Services.Configure<RequestLocalizationOptions>(options => { // You can set the default language using the following method: // options.SetDefaultCulture("fr"); options.AddSupportedCultures(new[] { "en", "fr" }); options.AddSupportedUICultures(new[] { "en", "fr" }); options.RequestCultureProviders = new List<IRequestCultureProvider>() { new CookieRequestCultureProvider() }; });
Blazor is a Single Page Application (SPA) framework, and as such, there is typically only one request sent to the server. Cookies are attached to this request and changing them requires a new request. By introducing controllers, you can interpret the request and allow the Blazor Server to access and modify the cookies. In other words, controllers provide a mechanism for handling incoming requests and modifying the server state in response.
[Route("[controller]/[action]")] public class CultureController : Controller { public IActionResult Set(string culture, string redirectUri) { if (culture is not null) { HttpContext.Response.Cookies.Append(CookieRequestCultureProvider.DefaultCookieName, CookieRequestCultureProvider.MakeCookieValue(new(culture, culture))); } return LocalRedirect(redirectUri); } }
@inject NavigationManager NavigationManager <select @onchange="OnChangeLanguage"> <option value="">Select</option> <option value="en">English</option> <option value="fr">France</option> </select> @code { private void OnChangeLanguage(ChangeEventArgs e) { var uri = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped); var culture = CultureInfo.GetCultureInfo(e.Value as string); var cultureEscaped = Uri.EscapeDataString(culture.Name); var uriEscaped = Uri.EscapeDataString(uri); NavigationManager.NavigateTo($"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}", forceLoad: true); } }
The URL strategy allows users to easily switch to their preferred language or share a link with the preferred language.
builder.Services.Configure<RequestLocalizationOptions>(options => { // You can set the default language using the following method: // options.SetDefaultCulture("fr"); options.AddSupportedCultures(new[] { "fr", "en" }); options.AddSupportedUICultures(new[] { "fr", "en" }); options.RequestCultureProviders = new List<IRequestCultureProvider>() { new QueryStringRequestCultureProvider() }; });
@inject NavigationManager NavigationManager @inject IOptions<RequestLocalizationOptions> RequestLocalizationOptions ... @code { protected override void OnInitialized() { var uri = new Uri(NavigationManager.Uri); var urlParameters = HttpUtility.ParseQueryString(uri.Query); var defaultCulture = RequestLocalizationOptions.Value.DefaultRequestCulture.Culture; var cultureProvider = RequestLocalizationOptions.Value.RequestCultureProviders.First(p => p is QueryStringRequestCultureProvider) as QueryStringRequestCultureProvider; CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo(urlParameters[cultureProvider.QueryStringKey] ?? defaultCulture.Name); CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(urlParameters[cultureProvider.UIQueryStringKey] ?? CultureInfo.CurrentCulture.Name); } }
Once you have created all the required classes and prepared the translated resources, you can start using deferred translation. Here's an example:
@inject IStringLocalizer<ChangeLanguageDemonstrate> Localizer <h3>ChangeLanguageDemonstrate</h3> @Localizer["Hello Blazor School {0} {1}", "optional param1", "optional param2"]