Next sample page features a language selector, a label to display current language and a button to reload the page.
The language selector is binded to a variable with a setter where I update all culture settings I can think of.
The label successfully reflects any change on the selector. But when we click on the button to reload the page, it does not remember the changes.
@page "/test"
@inject NavigationManager NavigationManager
@using System.Globalization
<div class="Wrapper">
<select @bind="@Culture">
@foreach (var culture in cultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
<div>
Current culture: @CultureInfo.CurrentCulture.Name
</div>
<button @onclick="Reload">Reload the page</button>
</div>
<style>
.Wrapper {
display:flex;
flex-direction:column;
gap:15px;
max-width:200px;
margin:50px auto;
}
</style>
@code {
CultureInfo[] cultures = new[] {
new CultureInfo("es-ES"),
new CultureInfo("ca"),
new CultureInfo("en-US"),
new CultureInfo("pt-PT")
};
CultureInfo Culture
{
get => CultureInfo.CurrentCulture;
set
{
if (CultureInfo.CurrentCulture != value)
{
Thread.CurrentThread.CurrentCulture = value;
Thread.CurrentThread.CurrentUICulture = value;
CultureInfo.DefaultThreadCurrentCulture = value;
CultureInfo.DefaultThreadCurrentUICulture = value;
}
}
}
void Reload() {
NavigationManager.NavigateTo(NavigationManager.Uri, true);
}
}
After some help from @Liyun Zhang and many trial and errors I succeeded replacing cookies storage by Preferences storage to persist selected culture:
Install-Package Microsoft.Extensions.Localization
builder.Services.AddLocalization();
string? cc = Preferences.Get("blazorCulture", null);
if (string.IsNullOrEmpty(cc)) {
cc = "es-ES";
Preferences.Default.Set("blazorCulture", cc);
}
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(cc);
@using System.Globalization
@using Microsoft.Extensions.Localization
@using Test.Resources.Languages
Under Resources folder, add a Languages folder.
Under Languages folder, add a resources file and call it "MyStrings.resx".
Open MyStrings.resx and enter "HelloWorld" as key and "Hello, World!" as its default value.
Add a new resources file called "MyStrings.es-ES.resx" for European Spanish values.
Open MyStrings.es-ES.resx and enter "HelloWorld" as key and "Hola, Mundo!" as its Spanish value.
Add a new resources file called "MyStrings.ca.resx"
Open MyStrings.es-ES.resx and enter "HelloWorld" as key and "Hola, Mon!" as its Catalan value.
Add a new resources file called "MyStrings.pt-PT.resx" for portuguese european language.
Open MyStrings.pt-PT.resx and enter "HelloWorld" as key and "Olá Mundo!" as its Portuguese value.
Under Shared folder, add next Lang.razor component, which lets you select among a list of available languages and sends a callback notification to the component host when selection changes.
<select @bind="@Culture">
@foreach (var culture in cultures)
{
<option value="@culture">@culture.DisplayName</option>
}
</select>
@code {
[Parameter] public EventCallback<CultureInfo> AfterUpdate { get; set; }
[Parameter]
public CultureInfo? Culture
{
get => _culture;
set
{
if (_culture != value)
{
_culture = value;
if (AfterUpdate.HasDelegate) AfterUpdate.InvokeAsync(value);
}
}
}
private CultureInfo? _culture;
CultureInfo[] cultures = new[] {
new CultureInfo("es-ES"),
new CultureInfo("ca"),
new CultureInfo("en-US"),
new CultureInfo("pt-PT")
};
}
@page "/"
@inject IStringLocalizer<MyStrings> Localizer
@inject NavigationManager NavigationManager
<h1>@Localizer["HelloWorld"]</h1>
<Lang Culture="CultureInfo.DefaultThreadCurrentUICulture" AfterUpdate="AfterLangUpdate"></Lang>
@code {
private void AfterLangUpdate(CultureInfo culture) {
Preferences.Set("blazorCulture", culture.Name);
CultureInfo.DefaultThreadCurrentUICulture = culture;
NavigationManager.NavigateTo(NavigationManager.Uri, true);
}
}