In this article, we are going to implement Localization in the Blazor WebAssembly sample application.
From the above output, we can understand our localization working perfectly but only issue with a dropdown which is not retaining its selected value on page reload. Now to fix let's add the below code to set the value for dropdown.
That's all about the localization implementation in blazor webassembly.
The translation to a specific region or country or culture or local can be called as Localization. The websites with Localization can reach a wider range of audiences.
Create A Sample Blazor WebAssembly App:
Let's start coding by creating a sample blazor webassembly application(I'm using .Net5 Blazor). For development, IDE can be chosen based on own preferences but the most recommended IDE's are Visual Studio 2019(The latest version that supports .Net5) and Visual Studio Code.
Install Supporting Package:
Package Manager:
Install-Package Microsoft.Extensions.Localization
.Net CLI:
dotnet add package Microsoft.Extensions.Localization
Register AddLocalization Services:
To get the full support of Localization we need to register the 'AddLocalization' service.
Program.cs:
builder.Services.AddLocalization(options => { options.ResourcesPath = "Resources"; });
- The 'ResourcesPath' option to specify the folder path to store the resource files(.resx files that store cultures data). This configuration is optional, on this we discuss more in upcoming steps.
Javascript Code To Store Culture In-Browser LocalStorage:
Since Blazor WebAssembly purely runs on the browser, to store the selected culture value we have to use the browser LocalStorage. So to store in local storage we are going to implement javascript code which will be communicated by our .net code using a built-in feature called JavaScript Interoperability.
wwwroot/index.html:
<script> window.appCulture = { set:(value) => { window.localStorage["culture"] = value; }, get:() => { return window.localStorage["culture"]; } } </script>
- Here created 'appCulture' javascript object literal that has properties like 'set' and 'get' whose values are callback functions.
- In 'set' callback takes culture value as an input parameter and saves to the browser local storage.
- In 'get' callback fetches the culture value from the browser's local storage.
Create A Model To Store And Display Culture Codes:
Let's create a container to store and display the culture codes.
Models/LanguageCodes.cs:
namespace BW.Localization.Sample.Models { public class LanguageCodes { public string DisplayName{get;set;} public string Code{get;set;} } }Add the model namespace into the _Imports.razor file
_Import.razor:
@using BW.Localization.Sample.Models
Create A Culture Change Blazor Component:
Now we need to create a shared blazor component that contains the culture dropdown which is designed to change the application culture.
Shared/LanguageSelection.razor:(Code Block Part)
@code{ private List<LanguageCodes> langCodes = new List<LanguageCodes>() { new LanguageCodes { Code = "fr-FR", DisplayName = "French" }, new LanguageCodes { Code = "en-US", DisplayName= "English(USA)" } }; private string selectedLang = ""; private async Task ChangeLanguage() { await _jsRuntime.InvokeAsync<string>("appCulture.set", selectedLang); _navigation.NavigateTo(_navigation.Uri, forceLoad:true); } }
- (Line: 2-14) Collection of culture codes that will be used by dropdown to populate its options.
- (Line: 16) The 'selectedLang' variable stores the selected culture value of the dropdown.
- (Line: 18) The 'ChangeLanguage' method will invoke on button click to change the application culture.
- (Line: 20) The variable '_jsRuntime' of type 'IJSRuntime' that works as Javascript Interoperability means communication between Javascript code and CSharp code. By calling the javascript method 'appCultur.set' and passing the 'selectedLang' as an input parameter.
- (Line: 21) The variable '_navigation' of type 'NavigationManager'. After saving the culture to browser local storage we need to reload the page to reflects the changes in the new culture selected.
@inject IJSRuntime _jsRuntime; @inject NavigationManager _navigation; <div class="form-group"> <select class="form-control" @bind="selectedLang"> @foreach (var langCode in langCodes) { <option value="@langCode.Code">@langCode.DisplayName</option> } </select> </div> <button class="btn btn-primary" @onclick="ChangeLanguage">Change Language</button>
- Injected 'IJSRuntime' and 'NavigationManager'
- (Line: 5) Dropdown bound with 'selectedLang' variable
- Looping the culture codes display as dropdown values.
- The 'ChangeLanguage' call back method assigned to the button click.
Shared/MainLayout.razor:
<LanguageSelection></LanguageSelection>
Load The App Culture On App Loading:
By default, the culture will be 'en-us', but we need to load the selected culture of the application on application start which means load the culture stored in browser local storage.
Program.cs:
using System; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.Extensions.DependencyInjection; using System.Globalization; using Microsoft.JSInterop; namespace BW.Localization.Sample { public class Program { public static async Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.Services.AddLocalization(options => { options.ResourcesPath = "Resources"; }); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); var host = builder.Build(); var jsInterop = host.Services.GetRequiredService<IJSRuntime>(); var result = await jsInterop.InvokeAsync<string>("appCulture.get"); if (result != null) { var culture = new CultureInfo(result); CultureInfo.DefaultThreadCurrentCulture = culture; CultureInfo.DefaultThreadCurrentUICulture = culture; } await builder.Build().RunAsync(); } } }
- (Line: 24) Creating the instance of 'IJSRuntime'
- (Line: 25) Fetching the culture value from the browser.
- To apply our culture change to our application we need to assign our culture data to 'CultureInfo.DefaultThreadCurrentCulture' and 'CultureInfo.DefaultThreadCurrentUICulture'
Resource File:
A resource file contains a translated string for our localization. An example of the resource file is like 'Example.resx'.
The resource file name should be fully qualified for its namespace by excluding the library name. For example, we have 'TestLocalization.dll' and we can create a resource file based on Program.cs file as Program.en-US.resx, Program.fr-FR.resx(contains translated french string value).
So resource file creation can be done with 2 types of techniques like 'dot notation' and 'folder structure'.
For example, a resource file for the Index.razor page using 'dot notation' looks as follow 'Pages.Index.en-US.resx', 'Pages.Index.fr-FR.resx' and using 'folder structure' looks as follow 'Resources/Pages/Index.en-Us.resx', 'Resources/Pages/Index.fr-FR.resx'('Resource' is the root folder configured in Program.cs file).
Note: For the default culture we no need to specify the culture name in the .resx file. So 'Index.en-US.resx' file can be created as 'Index.resx'.
Now for this sample, I will use a folder structure approach which looks as follow
Use IStringLocalizer<T> To Access Resources:
Blazor uses 'IStringLocalizer<T> ' to load the translated string from the resources file based on the culture selected.
Pages/Index.razor:
@page "/" @inject Microsoft.Extensions.Localization.IStringLocalizer<Index> Loc <h1>@Loc["Greetings"]</h1>
From the above output, we can understand our localization working perfectly but only issue with a dropdown which is not retaining its selected value on page reload. Now to fix let's add the below code to set the value for dropdown.
Shared/LanguageSelection.razor:
protected override async Task OnInitializedAsync() { selectedLang = CultureInfo.CurrentCulture.Name; }Now test again our application below.
That's all about the localization implementation in blazor webassembly.
Support Me!
Buy Me A Coffee
PayPal Me
Wrapping Up:
Hopefully, I think this article delivered some useful information on Blazor WebAssembly Localization. I love to have your feedback, suggestions, and better techniques in the comment section below.
Many thanks, You saved the day man!
ReplyDelete