ASP.NET Core Pitfalls - Localization with Shared Resources
Update: updated for ASP.NET Core 8, should work on earlier versions.
When localizing a web application using resources, there are two common ways:
- Using a resource per Razor view or page
- Using shared resources, e.g., not bound to a specific view or page
By default, ASP.NET Core’s localization expects resource files(.resx) to be located inside a Resources folder on the root of the web application. When using shared resources, we often create a dummy class (say, SharedResources) to which we can associate resources that are not associated with a specific view or page, for example, resources used in the page layout, so, we may be tempted to place this class inside this Resources folder. It turns out, however, that that won’t work: even if you change the namespace of this class to be the root assembly namespace (usually the web application’s name), the satellite resource assembly will not be generated properly. The solution is to place the dummy class at the root of the application (for example) and leave the resource files inside the Resources folder:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services
.AddControllersWithViews() .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);
...
var app = builder.Build();
...
var supportedCultures = new[] { "en", "pt" };
var localizationOptions = new RequestLocalizationOptions() { ApplyCurrentCultureToResponseHeaders = true } .SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); app.UseRequestLocalization(localizationOptions);
...
Finally, to use in a Razor view or page:
@inject IHtmlLocalizer<SharedResources> Localizer
<h1>@Localizer["Hello"]</h1>
Hope you find it useful!