Skip to main content

Localizing an ASP.NET Core Blazor website using VS Code

Localizing an ASP.NET Core Blazor website using VS Code

The standard way of localizing .NET applications is using .resx files, which is very easy to do in Visual Studio. It’s also possible to do this using Visual Studio Code, however this tooling doesn’t come by default with the C# extension for Visual Studio Code, which means you need an extension and a bit more work.
In this tutorial I will assume that you have run the dotnet new blazorserver command, which will bootstrap a Blazor project for you.

IDE setup

All you need to do is to install the ResX Editor extension by Dominic Vonk, which will allow you to edit .resx files in VS Code.

Create resource files

Now, create a Resources folder on your project and create a file called SharedResources.resx. You could also create one resource file per page, e.g. Home.resx, Register.resx, etc. You can now add as many keys to this file as you wish.


For each .resx file you make, you must also create a .cs file with the same name (e.g. Home.resx -> Home.cs) in the same folder. Add the following code to the new file, replacing the namespace and the class name to match the file name:

namespace MyApp.Resources;

public class SharedResources
{
}

This empty class is needed because VS Code doesn’t generate it automatically for us like Visual Studio does. It can be left empty because all we care about is the name, which the localization extension will use to find the .resx file.

Builder configuration

Next, you must register the required services in your app’s builder:

var builder = WebApplication.CreateBuilder(args);

// ...

builder.Services.AddLocalization();

Localizing Blazor components

In order to use the string localizer in Blazor components all you must first add the following line to the _Imports.razor file:

@using Microsoft.Extensions.Localization
@using MyApp.Resources

This will expose the localization extension and your resource classes on all Razor files, which means that you won’t have to add these @usings every time you want to localize a string.
Next, you must add the following line to the top of your Blazor component file, replacing SharedResources with whatever name you chose earlier:

@inject IStringLocalizer<SharedResources> Loc

Finally, in order to get a localized string all you need to do is Loc["Foo"], for example:

<h1>The following text is translated: @Loc["Foo"]</h1>

Adding more languages

Whenever the localizer requests a string on a specific culture it will look for a resource file whose name ends with the culture name, e.g. SharedResources.en-US.resx. If this file can’t be found, it will fall back to the file that has no culture name in it. This means that all you have to do to translate a string is to create another .resx file next to it that includes the culture name just before the .resx extension, e.g. .en-US.resx (there’s no need to create a C# file for these .resx files).

Check the Microsoft documentation for Blazor globalization for more info, for example to change how the localizer determines what culture to use.

Comments

Popular posts from this blog

Hangfire: setup and usage

How to setup Hangfire, a job scheduler for .NET Installing Hangfire Setting up Hangfire Setting up storage MySQL Storage In-memory storage Running jobs Fire-and-forget jobs Delayed jobs Continuation jobs Recurring jobs ASP.NET Core job integration Conclusion Hangfire is a job scheduler for .NET and .NET Core that lets you run jobs in the background. It features various different job types: Fire-and-forget jobs are executed only once , shortly after creation. Delayed jobs are very similar to fire-and-forget jobs but they wait for a specified amount of time before running. Continuation jobs, which run after their parent job has finished . Recurring jobs, perhaps the most interesting of all, run repeatedly on an interval . If you like Unix’s cron you’ll feel right at home, as this kind of job lets you specify the job interval as a cron expression . If you have never used this I recommend crontab.guru , it has a live expression editor, as well as some examp...

ConditionalWeakTable, what does it do?

C#'s ConditionalWeakTable, what does it do? C# has many lesser known features, some more useful than others, and one of them is the ConditionalWeakTable<TKey, TValue> (keep in mind that TKey and TValue must be reference types). You can think of this type as a dictionary where the keys are weakly referenced, meaning that they won’t count when the GC checks if the object has to be collected. Additionally, when the keys do eventually get collected by the GC, that entry will get removed from the dictionary. This means that you can attach arbitrary objects to any object, allowing you to do something like this: public static class Extensions { private static ConditionalWeakTable < object , dynamic > Table = new ConditionalWeakTable < object , dynamic > ( ) ; public static dynamic Data ( this object obj ) { if ( ! Table . TryGetValue ( obj , out var dyn ) ) Table . Add ( obj , dyn = new ExpandoObject ( )...

How to observe and control Windows media sessions in C#

How to control Windows media sessions in C# If you use Windows 10 and play music, you’ll most likely come across this dialog at some point: This is the media overlay, and it appears whenever you’re playing music and press a media key or you change the volume. This dialog uses the GlobalSystemMediaTransportControls family of APIs available on the Windows 10 Runtime API since version 1809. This API is usually restricted to UWP applications, however, the introduction of .NET 5 and the ability to target specific platforms in the project’s TargetFramework has made it available for use in any kind of application, like WPF or regular console programs. Fetching information from the GSMTC API The API’s entrypoint is the GlobalSystemMediaTransportControlsSessionManager . This class allows you to fetch all the current active sessions, as well as whichever one Windows thinks is the current one. In order to be able to access this class at all you must first set your project’s TargetFramewor...