Localization of Blazor Components

22 May 202424 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,

NOTE

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.

NOTE

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

Copy the default resx file (SfResources.resx) and the other required resx files based on the culture to be localized and add them to the Resources folder. If you are implementing in a .NET MAUI Blazor app, create a LocalizationResources folder and add them into it.

Adding Resource Files in Blazor

NOTE

Update the localization files whenever you upgrade the Syncfusion NuGet packages in the application to avoid the issues occur due to localization strings.

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 .

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;

            //For .Net Maui Blazor App
            // Replace the ApplicationNamespace with your application name.
            //return ApplicationNamespace.LocalizationResources.SfResources.ResourceManager;
        }
    }
}

Register the ISyncfusionStringLocalizer and Syncfusion Blazor Service in the ~/Program.cs file of your app.

  • If you create a Blazor Web App with an Interactive render mode such as WebAssembly or Auto, you need to ensure the registration of the SyncfusionLocalizer and Syncfusion Blazor services in both ~/Program.cs files.

  • For MAUI Blazor App, register the Syncfusion Blazor Service in the ~/MauiProgram.cs file.

using Syncfusion.Blazor;
...
builder.Services.AddSyncfusionBlazor();
// 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 Web App and Blazor WASM App

In Blazor Web App and 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,

  • For Blazor Web App, prevent Blazor autostart by adding autostart="false" attribute to the Blazor <script> tag in the ~/Components/App.razor file.

  • For Blazor WebAssembly App , prevent Blazor autostart by adding autostart="false" attribute to Blazor’s <script> tag in the wwwroot/index.html file.

<body>
    ...
    <script src="_framework/blazor.web.js" autostart="false"></script>
    ...
</body>
<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.web.js" autostart="false"></script>
    <script>
        Blazor.start({
            webAssembly: {
                applicationCulture: 'de'
            }
        });
    </script>
    ...
</body>
<body>
    ...
    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
        Blazor.start({
            applicationCulture: 'de'
        });
    </script>
    ...
</body>

Setting the culture in C# code

For Blazor Web App & Blazor WASM App, 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-DE");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("de-DE");

Blazor Server App

  • For .NET 6 & .NET 7 app, specify the static culture in ~/Program.cs file.
...
var app = builder.Build();
app.UseRequestLocalization("de-DE");
...

MAUI Blazor App

In a MAUI Blazor app, you can set the culture in C# code by configuring the CultureInfo.DefaultThreadCurrentCulture and CultureInfo.DefaultThreadCurrentUICulture in MauiProgram.cs to the same culture. Ensure that this configuration is done before the line that builds and runs the MauiApp.CreateBuilder() (i.e., return builder.Build();).

using System.Globalization;

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("de-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 Web App and Blazor WASM App

For Blazor Web App and Blazor WASM App, set the BlazorWebAssemblyLoadAllGlobalizationData property to true in the project file:

<PropertyGroup>
    <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>
  • For Blazor Web App, add JS function in ~/Components/App.razor 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.

  • For Blazor WASM App, 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.web.js"></script>
<script>
    window.cultureInfo = {
        get: () => window.localStorage['BlazorCulture'],
        set: (value) => window.localStorage['BlazorCulture'] = value
    };
</script>
<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).

If you create a Blazor Web App with an Interactive render mode such as WebAssembly or Auto, you need to ensure the registration of the SyncfusionLocalizer and Syncfusion Blazor services in both ~/Program.cs files.

using Microsoft.JSInterop;
using System.Globalization;

...

builder.Services.AddSyncfusionBlazor();
//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

<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-DE"),
        new CultureInfo("fr-FR"),
        new CultureInfo("ar-AE"),
        new CultureInfo("zh-HK")
    };

    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 ~/MainLayout.razor to enable the culture switcher in all pages. If you create a Blazor Web App with an interactivity location as Per page/component, you need to ensure the set a render mode at the CultureSwitcher component instance in the ~/MainLayout.razor file.

<div class="page">
    ....
    <main>
        <div class="top-row px-4">
            <CultureSwitcher @rendermode="@InteractiveAuto" />
            ....
        </div>
    </main>
</div>
<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>

Blazor Server App and Blazor Web App (Interactive Server)

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

If you create a Blazor Web App with an Interactive render mode as Server make sure to include the registration of SyncfusionLocalizer and Syncfusion Blazor services in the ~/Program.cs files.

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();
//Register the Syncfusion locale service to localize Syncfusion Blazor components.
builder.Services.AddSingleton(typeof(ISyncfusionStringLocalizer), typeof(SyncfusionLocalizer));

var supportedCultures = new[] { "en-US", "de-DE", "fr-FR", "ar-AE", "zh-HK" };
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();
builder.Services.AddControllers();

builder.Services.AddSyncfusionBlazor();
builder.Services.AddLocalization();

var supportedCultures = new[] { "en-US", "de-DE", "fr-FR", "ar-AE", "zh-HK" };
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();

For .NET 6 and 7 set the current culture in a cookie immediately after opening <body> tag of Pages/_Host.cshtml.

For .NET 8 set the current culture in a cookie in App component file

@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Localization
@using System.Globalization
@{

    HttpContext.Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(
                    new RequestCulture(
                        CultureInfo.CurrentCulture,
                        CultureInfo.CurrentUICulture)));
}
@using System.Globalization
@using Microsoft.AspNetCore.Localization
@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)));
    }
}

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-DE"),
        new CultureInfo("fr-FR"),
        new CultureInfo("ar-AE"),
        new CultureInfo("zh-HK")
    };

    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>
<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

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

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

MAUI Blazor App

In App.xaml.cs, use Preferences to retrieve the user’s stored culture selection. If the storage doesn’t contain a culture for the user, the code sets a default value of United States English (en-US).

using System.Globalization;

namespace LocalizationMauiBlazor
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            var language = Preferences.Get("language", "en-US");
            var culture = new CultureInfo(language);
            CultureInfo.DefaultThreadCurrentCulture = culture;
            CultureInfo.DefaultThreadCurrentUICulture = culture;
            MainPage = new MainPage();
        }
    }
}

Create CultureSwitcher component to store the user’s culture selection via Preferences and to force reload the page using the updated culture.

@using System.Globalization
@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-DE"),
        new CultureInfo("fr-FR"),
        new CultureInfo("ar-AE"),
        new CultureInfo("zh-HK")
    };

    private CultureInfo Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                CultureInfo.DefaultThreadCurrentCulture = value;
                CultureInfo.DefaultThreadCurrentUICulture = value;
                Preferences.Set("language", value.Name);
                NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
            }
        }
    }
}

Add the CultureSwitcher component to Layout/MainLayout.razor to enable the culture switcher on all pages.

@inherits LayoutComponentBase

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

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

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

Dynamically set the culture in Blazor

NOTE

View Sample in GitHub

Localization using database in Blazor

See also