Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Localization file not effective rendering a Razor page in MVC ASP.NET Core 2.2

My Razor page looks like this.

@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
<h1>@Localizer["Index"]</h1>
...

My Startup.cs contains the following.

public void ConfigureServices(IServiceCollection services)
{
  ...
  services.AddLocalization(a => a.ResourcesPath = "/");

  services.Configure<RequestLocalizationOptions>(a =>
  {
    CultureInfo[] supportedCultures = {
      new CultureInfo("sv-SE"),
      new CultureInfo("se")
    };
    a.DefaultRequestCulture = new RequestCulture("se");
    a.SupportedCultures = supportedCultures;
    a.SupportedUICultures = supportedCultures;
  });
  ...
}

I placed a file called Controllers.HomeController.se.resx directly in the project's root. The controller HomeController contains the injection.

public class HomeController : Controller
{
  private readonly Context _context;
  private readonly IStringLocalizer<HomeController> _localizer;

  public HomeController(Context context, IStringLocalizer<HomeController> localizer)
  {
    _context = context;
    _localizer = localizer;
  }
  ...
}

The application doesn't crash but the string renedered is Index and not the value from the RESX file. I've tried to follow the docs as closely as possible but apparently I've missed something. I need help finding what that would be.

I breakpointed and checked the value of _localizer["Index"] in the constructor. As expected, the flag for the file not being found is set to true. Checking the value of SearchedLocation gives me Web...Controllers.MemberController. I can't tell if those three dots is the correct one for the RESX file in the project's root. I was expecting se somewhere in the name too.

like image 262
DonkeyBanana Avatar asked Feb 13 '19 21:02

DonkeyBanana


1 Answers

If you want to place you resources files in root of the project you should set ResourcesPath as following

services.AddLocalization(a => a.ResourcesPath = ""); //empty string

With this settings SearchedLocation will give you Web.Controllers.MemberController which points to Controllers.MemberController.resx file in the root of the project.

To use localization in view you have to follow Views.{ControllerName}.{ViewName}.resx pattern. For example if you have HomeController and About view in it you need to have Views.Home.About.resx file to use localization.

Another convention resource reader follows when searching for localization files is searching the files in respective folders rather than by dot separated names. For example if ResourcesPath is set to "Resources" the following variants are equal

Resources.Views.Home.About.resx
Resources\Views.Home.About.resx
Resources\Views\Home.About.resx
Resources\Views\Home\About.resx

So it's possible to structure your localization files by folders.

And you didn't specify you added app.UseRequestLocalization() in your Startup.cs. If you don't do this your application won't be able to determine request culture and it will always point to default resource file. Read more in the docs.

Note

There are 2 ways of configuring RequestLocalizationOptions for request localization, via services.Configure<RequestLocalizationOptions> or passing constructed options object (or delegate) to app.UseRequestLocalization. Effectively there is no difference between these approaches, they are totally equal in terms of localization middleware. But if at any point of an application you need to get RequestLocalizationOptions you won't be able to get value passed to app.UseRequestLocalization. But it is easy to accompish with services.Configure<RequestLocalizationOptions> (it's general approach described in the docs)

public class HomeController : Controller
{
    private readonly RequestLocalizationOptions _requestLocalizationOptions;

    public HomeController(IOptions<RequestLocalizationOptions> options)
    {
        _requestLocalizationOptions = options.Value;
    }

    //..
}
like image 81
Alexander Avatar answered Nov 15 '22 06:11

Alexander