Skip to content

All about resource files

Jon P Smith edited this page Jan 12, 2023 · 5 revisions

Resource files hold your messages you use in your application in different languages. The resource files have entries containing two columns called Name (which I call the localize key) and Value which holds your message in the correct language. The Name / Value entries in the resource files works like a dictionary, with the Name being the key.

These resource files must be in the ASP.NET Core project, most often in a folder, and the name of each resource file and is defined by three sections:

  1. A class, known as a TResource class, defines the first part of a resource filename. These TResource classes must be in the ASP.NET Core project.
  2. The culture of the language, e.g. en-US, is the last part of the filename,
  3. The resource files have the .resx extension.

Here is an example resource file name: Controllers.HomeController.fr.resx, but read Microsoft's document on resource file naming for a more fuller naming definition.

How to create / add entries to a resource files

The Microsoft section on creating and adding resource files is really good, so I suggest you read that.

I should say that I didn't found editing a resource file wasn't great in Visual Studio. See my tip on how to create resource files in one of the articles about localization, especially if the resource file is big or likely to change.

How to organize your resource files

In simple applications you might have a localization resource file per ASP.NET Core controller, but once your application becomes bigger, say with different layers etc., you need to think how you should organize your resource files. The two extremes are listed below with their pros and cons:

  • One resource file per class:
    • Pros: The localize keys only needs to be unique within the class.
    • Cons: You need to create lots of localization resource files.
  • One resource file per application:
    • Pros: One (big) localization resource file
    • Cons: The localize keys must be unique across the whole application.

How to link the localization services to the correct resource file

There are two parts to linking localization services to the correct resource files

1. Define a folder where the resource files

When you set up localization in your application you define the folder where you place your resource files. Here is the ASP.NET Core setup to say that the resource files will be in a top-level folder called "Resources".

services.AddLocalization(options => 
    options.ResourcesPath = "Resources");

2. Use a class to to link to the resource files

The localization services uses a class in the ASP.NET Core project to link to the resource file group. The easiest way to do this is to create the localization service by providing the class to the generic version of the service `IDefaultLocalizer, as shown below:

public class DefaultLocalizerController : Controller
{
    private readonly IDefaultLocalizer<HomeController> _defaultLocalizer;

    public DefaultLocalizerController(
        IDefaultLocalizer<HomeController> defaultLocalizer)
    {
        _defaultLocalizer = defaultLocalizer;
    }
// rest of the class is left out

But if you want to use localization in other projects (I call these backend projects ), then you can't directly use a class in the ASP.NET Core project. At that point you need the localization's factory method. This allows you to create a localization service using a Type value from your ASP.NET Core project.

This requires to define the Type of the class linked to the resource file group your backend project wants to access, as shown below

public class MyBackendCode 
{
    private readonly IDefaultLocalizer _defaultLocalizer;

    /// <summary>
    /// ctor
    /// </summary>
    public MyBackendCode(MyOptions options,
        IDefaultLocalizerFactory factory)
    {
        _localizeDefault = factory.Create(
            options.BackendResourceType) 
    }
    //… rest of class left out
}

NOTE: The ISimpleLocalizer has its class added when registered, to keep things simple. But the ISimpleLocalizer does have a ISimpleLocalizerFactory service, so this service can access different resource file groups if you want to.

What happens when there is a missing resource files / entries

The .NET localization will return the localize key if no entry is found in the resource files. This typically doesn’t provide a good experience for the user. The DefaultLocalizer service can provide the default message which isn’t in the correct language, but easy for the user to translate.

The other issue of missing resource files / entries is reporting. The NET localization does provide a ResourceNotFound parameter, which will be true if the localized message isn’t found, but if you want a log / event then you need to add that to each localization call. On the other hand, the DefaultLocalizer service provides a very detailed log – a example is shown below.

The message with the localizeKey name of 'MissingResourceEntry_MissingEntry' and culture of 'fr' was not found in the LocalizedWebApp.Resources.Controllers.HomeController' resource. The message came from DefaultLocalizerController.MissingResourceEntry, line 38.

This provides everything you need to correct this problem, including the class, method, and line number of where the localization came from.

Other options than using resource files

.NET localization uses resource files, but you can use an alternative source, such as:

I'm not using or recommending these, but if you are looking to not use resource files this gives you an idea. NOTE: using a database is likely to be slower than accessing a file.

Clone this wiki locally