Локализация для ASP.NET Ядро 3.0 не работает

#c# #asp.net-core #.net-core #localization

#c# #asp.net-ядро #.net-ядро #локализация

Вопрос:

Поскольку в названии говорится, что локализация не работает, я получаю только ключ, а не значение, вот весь необходимый код.

Услуги конфигурации

     public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
            .AddEntityFrameworkStores<ApplicationDbContext>();
        services.AddControllersWithViews();
        services.AddRazorPages();

        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddMvc().AddDataAnnotationsLocalization().AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix, options =>
        options.ResourcesPath = "Resources");

        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("sr")
            };

            options.DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;

        });
    }
  

Настройка

     public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseRequestLocalization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
  

Контроллер

 public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;
    public IStringLocalizer<Resource> _localizer;

    public HomeController(
        ILogger<HomeController> logger,
        IStringLocalizer<Resource> localizer)
    {
        _logger = logger;
        _localizer = localizer;
    }

    public IActionResult Index()
    {
        return View();
    }

    [HandleError]
    public IActionResult Privacy()
    {
        throw new Exception();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
        return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }
}
  

Ресурс

 namespace WebApplication.Resources
{
    public class Resource
    {
    }
}
  

Index.cshtml

 @{
    ViewData["Title"] = "Home Page";
}

@using Microsoft.Extensions.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using WebApplication.Resources

@inject IStringLocalizer<Resource> localizer
@inject IViewLocalizer _localizer

<div class="text-center">
    <h1 class="display-4">Welcome</h1>
    <p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
    <p>@localizer["Hello"]</p>
    <p>@_localizer["Hello"]</p>
</div>
  

Обозреватель решений

В папке ресурсов у меня есть класс Resource и два файла .resx (Resource.en.resx, Resource.sr.resx), оба они содержат один ключ Hello. В представлении я пытаюсь отобразить значение этого ключа с помощью IStringLocalizer и IViewLocalizer, но безуспешно. Может кто-нибудь сказать мне, в чем проблема, что я делаю не так!

Ответ №1:

Вы должны быть осторожны с пространством имен класса, для которого вы приобретаете IStringLocalizer . Из документации:

Ресурсы называются по имени полного типа их класса минус имя сборки.

Полное имя типа вашего Resource класса WebApplication.Resources.Resource и вычитание имени сборки, которое вы получаете Resources.Resource . Также вы указали «Ресурсы» в качестве корневого пути для ваших файлов ресурсов ( services.AddLocalization(options => options.ResourcesPath = "Resources") ). Это означает, что при приобретении IStringLocalizer<Resource> он попытается найти ваш файл ресурсов по адресу <project root>/Resources/Resources.Resource.en.resx (для английской локализации).

У вас есть несколько вариантов:

1. Измените пространство имен вашего класса ресурсов

В вашем Resource.cs использовании используется следующее пространство имен:

 namespace WebApplication
{ ... }
  

Теперь локализатор будет искать файл ресурсов по адресу <project root>/Resources/Resource.en.resx (или <project root>/Resources.Resource.en.resx — точки или разделители путей не имеют значения)

2. Переименуйте ваши файлы RESX

Поскольку локализатор в данный момент ищет файл, <project root>/Resources/Resources.Resource.en.resx вы можете просто переименовать Resource.en.resx его в Resources.Resource.en.resx

3. Не устанавливайте относительный путь к ресурсам

Startup.cs При настройке локализации вы можете пропустить настройку ResourcesPath , чтобы локализатор искал файл относительно корневой папки проектов:

 // Startup.cs -> ConfigureServices()
services.AddLocalization();
  

Теперь локализатор будет искать файл по пути <project root>/Resources/Resource.en.resx .

Комментарии:

1. Спасибо, добрый сэр. Ты герой!