-
Notifications
You must be signed in to change notification settings - Fork 2
All about resource files
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:
- 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.
- The culture of the language, e.g. en-US, is the last part of the filename,
- 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.
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.
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.
There are two parts to linking localization services to the correct 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");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 outBut 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.
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.
.NET localization uses resource files, but you can use an alternative source, such as:
- @RickStrahl Westwind.Globalization
- @DarkLiKally I18Next.Net
- @nuages-io nuages-localization
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.