Localization of Blazor Components

23 Mar 202224 minutes to read

Localization is the process of translating the application resources into different languages for specific cultures. You can localize the Syncfusion Blazor components by adding a resource file for each language.

Localization of Syncfusion Blazor Components

The following two steps can be used to localize Syncfusion Blazor components based on culture. You can find the example codes in the below repository,

View Sample in GitHub

Adding culture based resx files

Syncfusion components can be localized using the Resource .resx files. You can find the default and culture based localization files in the following GitHub repository.

You can get default and culture based resource files from GitHub.

Copy default resx file (SfResources.resx) and the other required resx files based on the culture to be localized and add it into Resources folder.

Adding Resource Files in Blazor

After adding the resource file in the application, double click default resx (SfResources.resx) file and open Resource Editor. In the Resource Editor, change Access Modifier option as Public to generate designer.cs file.

Changing Access Modifier

Create and register localization service

ISyncfusionStringLocalizer which acts as a middleware to connect the Syncfusion Blazor UI components and resource files, uses ResourceManager to provide culture specific resources at runtime. Create a class implementing ISyncfusionStringLocalizer. In the newly created class, return the ResourceManager created in the above step for ResourceManager property and change GetText method to return localized string using resource manager.

In the following code, SyncfusionLocalizer class implements ISyncfusionStringLocalizer interface and ResourceManager configured to return the cached ResourceManager instance of default resource file created in Adding culture based resx files step.

using Syncfusion.Blazor;

public class SyncfusionLocalizer : ISyncfusionStringLocalizer
{
    public string GetText(string key)
    {
        return this.ResourceManager.GetString(key);
    }

    public System.Resources.ResourceManager ResourceManager
    {
        get
        {
            // Replace the ApplicationNamespace with your application name.
            return ApplicationNamespace.Resources.SfResources.ResourceManager;
        }
    }
}

Register the ISyncfusionStringLocalizer implementation to localize the Syncfusion Blazor components based on resources files added in application.

  • For Blazor Server App, register the Syncfusion Blazor Service as follows,
    • For .NET 6 app, open the ~/Program.cs file and register the Syncfusion Blazor Service.
    • For .NET 5 and .NET 3.X app, open the ~/Startup.cs file and register the Syncfusion Blazor Service.
  • For Blazor WebAssembly App, register the Syncfusion Blazor Service in the client web app of ~/Program.cs file.
...
builder.Services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
// Register the locale service to localize the  SyncfusionBlazor components.
builder.Services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));
...

Statically set the culture

If you don’t want to change culture dynamically, you can set it statically by following the procedures below.

Blazor Server App

  • For .NET 6 app, specify the static culture in ~/Program.cs file.
  • For .NET 5 and .NET 3.X app, specify the static culture in ~/Startup.cs file.
...
var app = builder.Build();
app.UseRequestLocalization("de");
...
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...
    app.UseRequestLocalization("de");
    ...
}

Blazor WASM App

In Blazor WASM app, you can set culture statically in Blazor’s start option or in C# code.

Setting the culture Blazor’s start option

The app’s culture can be set in JavaScript by setting applicationCulture in Blazor’s start option by following the steps below,

  • In wwwroot/index.html, prevent Blazor autostart by adding autostart="false" attribute to Blazor’s <script> tag.
<body>
    ...
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    ...
</body>
  • Add the script block below Blazor’s <script> tag and before the closing </body> tag to start blazor with specific culture.
<body>
    ...
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
        Blazor.start({
            applicationCulture: 'de'
        });
    </script>
    ...
</body>

Setting the culture in C# code

You can set culture in C# code alternative for setting the culture Blazor’s start option. Set the CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture in Program.cs to the same culture before line that builds and runs the WebAssemblyHostBuilder (await builder.Build().RunAsync();).

using System.Globalization;

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("de");

Localization of Blazor Component

Dynamically set the culture

The culture can be set dynamically based on user’s preference. The following example demonstrates how to use a localization cookie to store user’s localization preference.

Blazor Server App

Set the app’s supported cultures. Also, ensure the app is configured to process controller actions by calling AddControllers and MapControllers.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddControllers();

builder.Services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
//Register the Syncfusion locale service to localize Syncfusion Blazor components.
builder.Services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));

var supportedCultures = new[] { "en-US", "de", "fr", "ar", "zh" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

var app = builder.Build();
app.UseRequestLocalization(localizationOptions);
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");   
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();
public class Startup
{
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddControllers();
        services.AddServerSideBlazor();
        services.AddSingleton<WeatherForecastService>();
        services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
        //Register the Syncfusion locale service to localize Syncfusion Blazor components.
        services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));
        services.Configure<RequestLocalizationOptions>(options =>
        {
            // Define the list of cultures your app will support
            var supportedCultures = new List<CultureInfo>()
            {
                new CultureInfo("en-US"),
                new CultureInfo("de"),
                new CultureInfo("fr"),
                new CultureInfo("ar"),
                new CultureInfo("zh"),
            };
            // Set the default culture
            options.DefaultRequestCulture = new RequestCulture("en-US");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRequestLocalization(app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value);
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapBlazorHub();
            endpoints.MapFallbackToPage("/_Host");
        });
    }
}

Set the current culture in a cookie immediately after opening <body> tag of Pages/_Host.cshtml.

@using Microsoft.AspNetCore.Localization
@using System.Globalization
@{
    Layout = "_Layout";
    this.HttpContext.Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(
            new RequestCulture(
                CultureInfo.CurrentCulture,
                CultureInfo.CurrentUICulture)));
}
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Localization
@using System.Globalization
@{
    Layout = null;
    HttpContext.Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(
                    new RequestCulture(
                        CultureInfo.CurrentCulture,
                        CultureInfo.CurrentUICulture)));
}

To provide UI to allow a user to select a culture, 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.

using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;

[Route("[controller]/[action]")]
public class CultureController : Controller
{
    public IActionResult SetCulture(string culture, string redirectUri)
    {
        if (culture != null)
        {
            HttpContext.Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(
                    new RequestCulture(culture)));
        }
        return LocalRedirect(redirectUri);
    }
}

Create CultureSwitcher component and place it inside shared folder to perform the initial redirection when the user selects a culture.

@using  System.Globalization
@inject NavigationManager NavigationManager
@inject HttpClient Http

<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("de"),
        new CultureInfo("fr"),
        new CultureInfo("ar"),
        new CultureInfo("zh")
    };

    protected override void OnInitialized()
    {
        Culture = CultureInfo.CurrentCulture;
    }

    private CultureInfo Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                var uri = new Uri(NavigationManager.Uri)
                    .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
                var cultureEscaped = Uri.EscapeDataString(value.Name);
                var uriEscaped = Uri.EscapeDataString(uri);

                NavigationManager.NavigateTo(
                    $"Culture/SetCulture?culture={cultureEscaped}&redirectUri={uriEscaped}",
                    forceLoad: true);
            }
        }
    }
}

Add the CultureSwitcher component to Shared/MainLayout.razor to enable the culture switcher in all pages.

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <CultureSwitcher />
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

5.You can select the culture dynamically from culture switcher at run time by setting the following ways,

Blazor WASM App

Set the BlazorWebAssemblyLoadAllGlobalizationData property to true in the project file:

<PropertyGroup>
    <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>

Add JS function in wwwroot/index.html file (after Blazor’s <script> tag and before the closing </body>), to get and set the user’s selected culture in the browser local storage.

<script src="_framework/blazor.webassembly.js"></script>
<script>
    window.cultureInfo = {
        get: () => window.localStorage['BlazorCulture'],
        set: (value) => window.localStorage['BlazorCulture'] = value
    };
</script>

In Program.cs use JS interop to call above function and retrieve the user’s culture selection from local storage. If local storage doesn’t contain a culture for the user, the code sets a default value of United States English (en-US).

using Microsoft.JSInterop;
using System.Globalization;

...

builder.Services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
//Register the Syncfusion locale service to localize Syncfusion Blazor components.
builder.Services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));

var host = builder.Build();

//Setting culture of the application
var jsInterop = host.Services.GetRequiredService<IJSRuntime>();
var result = await jsInterop.InvokeAsync<string>("cultureInfo.get");
CultureInfo culture;
if (result != null)
{
    culture = new CultureInfo(result);
}
else
{
    culture = new CultureInfo("en-US");
    await jsInterop.InvokeVoidAsync("cultureInfo.set", "en-US");
}
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

await builder.Build().RunAsync();
using Microsoft.JSInterop;
using System.Globalization;

namespace SyncfusionWasmLocalization
{
    public class Program
    {
        public static async Task Main(string[] args)
        {
            ...
            builder.Services.AddSyncfusionBlazor(options => { options.IgnoreScriptIsolation = true; });
            //Register the Syncfusion locale service to localize Syncfusion Blazor components.
            builder.Services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));

            var host = builder.Build();

            //Setting culture of the application
            var jsInterop = host.Services.GetRequiredService<IJSRuntime>();
            var result = await jsInterop.InvokeAsync<string>("cultureInfo.get");
            CultureInfo culture;
            if (result != null)
            {
                culture = new CultureInfo(result);
            }
            else
            {
                culture = new CultureInfo("en-US");
                await jsInterop.InvokeVoidAsync("cultureInfo.set", "en-US");
            }
            CultureInfo.DefaultThreadCurrentCulture = culture;
            CultureInfo.DefaultThreadCurrentUICulture = culture;

            await builder.Build().RunAsync();
        }
    }
}

Create CultureSwitcher component to set the user’s culture selection into browser local storage via JS interop and to force reload the page using the updated culture.

@using  System.Globalization
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@using  System.Globalization
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager

<select @bind="Culture">
    @foreach (var culture in supportedCultures)
    {
        <option value="@culture">@culture.DisplayName</option>
    }
</select>

@code {
    private CultureInfo[] supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("de"),
        new CultureInfo("fr"),
        new CultureInfo("ar"),
        new CultureInfo("zh")
    };

    private CultureInfo Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                var js = (IJSInProcessRuntime)JSRuntime;
                js.InvokeVoid("cultureInfo.set", value.Name);

                NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
            }
        }
    }
}

Add the CultureSwitcher component to Shared/MainLayout.razor to enable the culture switcher in all pages.

<div class="page">
    ....
    <main>
        <div class="top-row px-4">
            <CultureSwitcher />
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>
    </main>
</div>

Dynamically set the culture in Blazor

View Sample in GitHub

Localization using database in Blazor

See also