Image for post
Image for post

Localization of a Blazor component

Xavier Solau
Jan 6 · 5 min read

This Blazor article shows how to implement localization in your Blazor component.

You can find the Github source repository this article series is based on here.

The Blazor article series

In the previous articles

We have seen in the previous articles how to write and unit test a component with Blazor. Today, we will continue to enhance our shared component with localization support.

Install dependencies

First of all we need to install the Microsoft.Extensions.Localization dependency in the projects (application and libraries).

Install with the Nuget package manager:

Image for post
Image for post

Or with dotnet command line tool:

dotnet add package Microsoft.Extensions.Localization

Create your resources

Our localized string are going to be defined in resource files (*.resx). So the first thing we need to do is to create our resx files.

In this article we are going to base our localization string on resx files but this is actually up to you because we could also use json files. It will be the object of a next article….

First add a “Resources” folder and add the resource file:

Image for post
Image for post

In our example we named the resource file with the name of our component. The idea here is to have a set of resource file for each component.

In this article we are using Visual Studio but if you are using Visual Studio Code you can use the ResExpress or ResX Editor extension to edit your resource files.

It gives us two files: Component1.resx and Component1.Designer.cs.

Image for post
Image for post

Actually we don’t need the Designer file and it is using a Generator ResXFileCodeGenerator that will work only with Visual Studio.

In addition we won’t get the Designer file if we use Visual Studio Code for example.

We can safely remove the Component1.Designer.cs file and reset the Custom Tool in the properties view:

Image for post
Image for post
With ResXFileCodeGenerator custom tool.

In order to get this:

Image for post
Image for post
No Custom Tool specified.

As you can see the resx files are automatically detected as “Embedded resource” even if the csproj file doesn’t specify it.

Once everything is clean we can add our translated resource files like Component1.fr.resx for a French translation.

Image for post
Image for post

Now we can add our translations:

Image for post
Image for post
Base resource values in English.
Image for post
Image for post
The French translation.

In order to be able to easily access the resource keys we can also create constant values in our Component1:

public const string Body = nameof(Body);
public const string ClickMe = nameof(ClickMe);
public const string EnterSomeText = nameof(EnterSomeText);

It is also possible to use a code generator to create the constant properties but I will leave that for an other article.

Use localized string values

IStringLocalizer

In order to get the localized resources in our component we need to use a dedicated service: IStringLocalizer<Component>.

 [Inject]
private IStringLocalizer<Component1> L { get; set; }

Note that the localizer is using the name of the given type to find what resources must be loaded.

Once it is injected in the component, we can use it to get localized string values. It provides an indexed access using the resource key:

var localizedText = L["ResourceKey"];

Or the same using string format parameters:

var localizedText = L["ResourceKey", "Arg1", "Arg2"];

In this case, you need to define your resource using the “{n}” with n the index of the argument like this for example: “Here is my first {0} argument followed with my second {1} argument”.

Use in razor component

To use the localizer un the razor component view code, this is prefixed with “@” as usual when you use C# code:

<button>@L[ClickMe]</button>

Handle HTML in the resources

Sometime it may be useful to define your resources as HTML text and the naive approach would be to directly use the result from the localizer in you razor code like this:

<div>
@L[Body, “MySharedComponents”, ElementIds.ParentNameId, ParentName]
</div>

But unfortunately, it won’t give you exactly what we could expect:

Image for post
Image for post

Thanks to the MarkupString struct, we can display the HTML as we are expecting:

<div>
@((MarkupString)L[Body, “MySharedComponents”,
ElementIds.ParentNameId, ParentName].ToString())
</div>

Giving us:

Image for post
Image for post

As the code is a bit ugly, we can write an helper functions like this:

public static class StringLocalizerHelper
{
public static MarkupString Html<T>(
this IStringLocalizer<T> localizer,
string key,
params object[] arguments)
{
return new MarkupString(localizer[key, arguments]);
}
}

Resulting in something prettier in the razor code:

<div>
@L.Html(Body, “MySharedComponents”, ElementIds.ParentNameId,
ParentName)
</div>

Setting up the application project

Server-side hosting model

Now that our component is localized we can set up our application. Let’s start with the server side hosting model. Once the dependency to Microsoft.Extensions.Localization is added we need to set up the localization services in the Startup.cs file.

In the ConfigureServices method we need to add the localization services with AddLocalization. Optionally you can specify where to get the resources, in our case it is “Resources” (since we put the resx files in the “Resources” folder).

services.AddLocalization(options =>
{
options.ResourcesPath = “Resources”;
});

And we also need to add the RequestLocalizationOptions options:

var supportedCultures = new List<CultureInfo>
{
new CultureInfo(“en”),
new CultureInfo(“fr”)
};
services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture =
new Microsoft.AspNetCore.Localization.RequestCulture(“en”);
options.SupportedUICultures = supportedCultures;
});

One last step is required in the Configure method:

app.UseRequestLocalization();

And that’s it! The users will see our application localized in the language specified in their browser.

That said, we can also override the browser language by code with the options of the RequestLocalizationMiddleware options:

options.AddInitialRequestCultureProvider(
new CustomRequestCultureProvider(
async ctx => new ProviderCultureResult(“fr”)));

Web Assembly hosting model

For Web Assembly application, we just need to update the Main method in the Program.cs file in order to setup the service.

builder.Services.AddLocalization(options=>
{
options.ResourcesPath = “Resources”;
});

We also can override the browser language settings specifying the : DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture in CultureInfo:

var culture = new CultureInfo(“en”);
CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

Check the Microsoft documentation for more information.

Next we are going to talk about a localization based on Json file.

YounitedTech

Le blog Tech de Younited, où l’on parle de développement…

Thanks to Stifu, Thomas Goldstein, and Slim Ayache

Xavier Solau

Written by

YounitedTech

Le blog Tech de Younited, où l’on parle de développement, d’architecture, de microservices, de cloud, de data… Et de comment on s’organise pour faire tout ça. Ah, et on recrute aussi, on vous a dit ?

Xavier Solau

Written by

YounitedTech

Le blog Tech de Younited, où l’on parle de développement, d’architecture, de microservices, de cloud, de data… Et de comment on s’organise pour faire tout ça. Ah, et on recrute aussi, on vous a dit ?

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store