Blazor Json localization using BlazorJsonLocalizer

Xavier Solau
YounitedTech
Published in
6 min readMar 31, 2021

--

The purpose of this article is to show how to enable Json localization support on your Blazor project. Thanks to the BlazorJsonLocalizer project, it has never been so easy!

Note that if you want to have an overview of how it works you can have a look at this article: JSON-based Blazor localization.

Basically this project enables both your Blazor WebAssembly and your Blazor Server Side project with a Json localization support.

It provides two Json resources storage model:

  • Embedded in your Component Assembly (all is downloaded by the client with the assembly even if you are using one single culture)
  • Distributed as static assets and fetched only as needed (the assembly payload is smaller and the culture files are downloaded only when requested)

Setting the localizer using embedded Json

If you are going to embed your Json files in your Assemblies, you just need the SoloX.BlazorJsonLocalization package to enable the localization support.

Install editing your project file:

<PackageReference Include="SoloX.BlazorJsonLocalization"
Version="1.0.0" />

Setup the dependency injection

A few lines of code are actually needed to setup the BlazorJsonLocalizer. You just need to use the name space SoloX.BlazorJsonLocalization to get access to the right extension methods and to add the services in your ServiceCollection :

  • For Blazor WebAssembly:

Update your Main method in the Program.cs file:

// Here we are going to store the Json files in the project
// 'Resources' folder.

builder.Services.AddJsonLocalization(
builder => builder.UseEmbeddedJson(
options => options.ResourcesPath = "Resources"));

By default the current culture is going to be taken from the browser settings. But it can be easily modified by code with this simple code:

var cultureInfo = CultureInfo.GetCultureInfo(name);CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

You can find an example in the BlazorJsonLocalizer project repository in src/examples/SoloX.BlazorJsonLocalization.Example.Wasm.

  • For Blazor Server Side:

First add the using Microsoft.AspNetCore.Localization directive and update your ConfigureServices method in the Startup.cs file:

// Here we are going to store the Json files in the project
// 'Resources' folder.

services.AddJsonLocalization(
builder => builder.UseEmbeddedJson(
options => options.ResourcesPath = "Resources"),
ServiceLifetime.Singleton);
// AspNet core standard localization setup to get culture from the
// Browser

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

And update your Configure method in the Startup.cs file:

// AspNet core standard localization setup to get culture from the
// Browser
app.UseRequestLocalization();

With this configuration, you will be able to get the culture from the browser. If you want to define the culture by code you can go to the Microsoft documentation: “Provide UI to choose the culture”. You will find a nice solution for this purpose using cookie.

In addition you can find an example in the BlazorJsonLocalizer project repository in src/examples/SoloX.BlazorJsonLocalization.Example.ServerSide.

Enable localization support in your component

Let’s say that we are going to use the localization in the Index page. The first thing to do is to create your Json resource files that are actually going to contain the translated text. You will add the Json files in the project "Resources" folder (since we have defined it in the options ResourcesPath property). The folders hierarchy is also important to avoid name collision so if your component is in a sub-folder your Json files must also be in the same sub-folder.

For example if your Index page is in the Pages sub-folder, your Index Json files must be in the same sub-folder: Resources/Pages with Resources the resources path defined in the options.

Write your localization Json files

The file must be named with the component name (In our case Index) and suffixed with CultureInfo name like “en-US” or the ISO2 language code like “en”:

Note that if you want to get the localization resources for your component MyComponent and for the French CultureInfo (fr-FR) the factory will first try to load MyComponent-fr-FR.json. If the file is not found, it will try to load MyComponent-fr.json and finally if the file is still not found, it will fall back to the file MyComponent.json

The content of the file is using a conventional Json syntax for example the English Json file will look like this:

{
"Hello": "Hello world!",
"Welcome": "Welcome to your new app."
}

and the French file:

{
"Hello": "Bonjour tout le monde!",
"Welcome": "Bienvenue dans votre nouvelle application."
}

The Json file need to be declared as Embedded resources in order to be shipped in the Assembly. You can do it this way in your csproj file:

<ItemGroup>
<EmbeddedResource Include="Resources\Index-fr.json" />
<EmbeddedResource Include="Resources\Index.json" />
</ItemGroup>

Use the localization in your code

You will need to inject the IStringLocalizer<Index> in the Index class:

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

or using the razor syntax in the Index.razor file:

@inject IStringLocalizer<Index> L

with the using declared in your _Imorts.razor:

@using Microsoft.Extensions.Localization

Once the localizer is available you can just use it like this in the Index.razor file:

@page "/"<h1>@L["Hello"]</h1>@L["Welcome"]

Share localization resources

Let’s say that you need to share localization resources between different components.

In this case you can create an empty class (or an empty interface) like this:

// Dummy class to group shared resources
namespace Localization
{
public class SharedResource
{
}
}

You just need to create the corresponding Json files like we have done previously and this is done! You can inject the shared localizer in your component.

@page "/"@inject IStringLocalizer<Index> localizer
@inject IStringLocalizer<SharedResource> sharedLocalizer
<h1>@localizer["Hello"]</h1><h2>@sharedLocalizer["SharedResourceKey"]</h2>@localizer["Welcome"]

Note that you can share those resources through a simple Nuget package the same way you would do it for a shared Blazor component.

Setup the localizer using Json static assets on the HTTP host side

Basically you need to do almost the same as above except for the following points.

Json resource files as static assets

Your resource files are not embedded any more and they are located in the wwwroot folder of your project with the same naming rules.

Dependency injection in Blazor WebAssembly

In addition of the SoloX.BlazorJsonLocalization package you will need the SoloX.BlazorJsonLocalization.WebAssembly extension package.

Install editing your project file:

<PackageReference Include="SoloX.BlazorJsonLocalization.WebAssembly"
Version="1.0.0" />

The registration of your services will look like this in the Program.cs file:

// Here we are going to store the Json files in the project
// 'wwwroot/Resources' folder.

builder.Services.AddWebAssemblyJsonLocalization(
builder => builder.UseHttpHostedJson(
options =>
{
options.ApplicationAssembly = typeof(Program).Assembly;
options.ResourcesPath = "Resources";
}));

Dependency injection in Blazor Server Side

In addition of the SoloX.BlazorJsonLocalization package you will need the SoloX.BlazorJsonLocalization.ServerSide extension package.

Install editing your project file:

<PackageReference Include="SoloX.BlazorJsonLocalization.ServerSide"
Version="1.0.0" />

The registration of your services will look like this in your ConfigureServices method in the Startup.cs file:

// Here we are going to store the Json files in the project
// 'wwwroot/Resources' folder.

services.AddServerSideJsonLocalization(
builder => builder.UseHttpHostedJson(
options =>
{
options.ApplicationAssembly = typeof(Program).Assembly;
options.ResourcesPath = "Resources";
}));

Make sure your Json resources are actually loaded

Since the Json resources are static assets, they need to be loaded through HTTP to be used in your components. Thanks to a cache system, this will occur only once for each of your components but it may be useful to override the OnInitializedAsync method with a L.LoadAsync() like this to make sure your refresh your localized text once the localization data are available:

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

protected override async Task OnInitializedAsync()
{
await L.LoadAsync();
await base.OnInitializedAsync();
}

Full example for Blazor WebAssembly and Json static assets

Last words

As you can see it is really easy now to localize your Blazor application based on Json translation resources. In addition the project BlazorJsonLocalizer is designed to make extension easy! So for example if you want to plug your Blazor application on a specific translation API, it is absolutely possible!

--

--