Search code examples
c#asp.net-coreasp.net-core-mvclocalizationasp.net-core-localization

IViewLocalizer only show key instead of value from .resx file


I have a problem with ASP.NET Core localization. I want to use the method with IViewLocalizer. I have this Program.cs:

using xxx.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Localization;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using static System.Runtime.InteropServices.JavaScript.JSType;
using Microsoft.Extensions.Options;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDbContext<XXX>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("XXX"));
});

builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddDefaultTokenProviders()
                .AddDefaultUI();

builder.Services.AddControllersWithViews();

builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

// Přidání podpory pro lokalizaci pohledů a datových anotací
builder.Services.AddControllersWithViews()
    .AddViewLocalization()
    .AddDataAnnotationsLocalization();

var app = builder.Build();

var supportedCultures = new[] { "en-US", "cs-CZ" };

app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture("cs-CZ"),
    SupportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") },
    SupportedUICultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") }
});

app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);

using (var scope = app.Services.CreateScope())
{
    var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
    var roles = new[] { "Admin", "Redaktor", "Member" };
 
    foreach (var role in roles)
    {
        if (!await roleManager.RoleExistsAsync(role))
        {
            await roleManager.CreateAsync(new IdentityRole(role));
        }
    }
}

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.Use(async (context, next) =>
{
    await next();

    if (context.Response.StatusCode == 404)
    {
        context.Request.Path = "/NotFound";
        await next();
    }
});

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

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

app.Run();

My resources folder structure (at this moment I'm trying only on _Layout.cshtml):

Resources folder

And header of _Layout.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@using System.Globalization

<!DOCTYPE html>
<html lang="cs">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - xxx</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/xxx.styles.css" asp-append-version="true" />
    <link rel="stylesheet" href="/css/bootsrap-custo-var.css" />
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css" rel="stylesheet">
    @RenderSection("Styles", required: false)
</head>`
<body>
   <span>@Localizer["CookieSpanHeader"]</span>
</body>
</html>

The output of this code is, that instead of text from .resx (value), it shows only the key.

I looked for solutions to my problem, but without any better result.


Solution

  • Your resource file names for the _Layout.cshtml are incorrect. According to Resource file name, the file name should be:

    _Layout.resx
    _Layout.cs-CZ.resx
    

    which the extension .cshtml should be excluded.

    Also, you are incorrectly configuring for the RequestLocalizationOptions

    Add the code below:

    builder.Services.Configure<RequestLocalizationOptions>(options =>
    {
       options.DefaultRequestCulture = new RequestCulture("cs-CZ");
       options.SupportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") };
       options.SupportedUICultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") };
       options.RequestCultureProviders = new List<IRequestCultureProvider>
       {
           new UrlRequestCultureProvider()
       };
    });
    

    before the line:

    builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
    

    Reference: Use a custom provider

    And work with:

    app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
    

    Your Program.cs should be as below:

    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
    builder.Services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(connectionString));
    
    builder.Services.AddDatabaseDeveloperPageExceptionFilter();
    builder.Services.AddDbContext<XXX>(options =>
    {
        options.UseSqlServer(builder.Configuration.GetConnectionString("XXX"));
    });
    
    builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)
                    .AddEntityFrameworkStores<ApplicationDbContext>()
                    .AddDefaultTokenProviders()
                    .AddDefaultUI();
    
    builder.Services.AddControllersWithViews();
    
    builder.Services.Configure<RequestLocalizationOptions>(options =>
    {
       options.DefaultRequestCulture = new RequestCulture("cs-CZ");
       options.SupportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") };
       options.SupportedUICultures = new[] { new CultureInfo("en-US"), new CultureInfo("cs-CZ") };
       options.RequestCultureProviders = new List<IRequestCultureProvider>
       {
           new UrlRequestCultureProvider()
       };
    });
    
    builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
    
    // Přidání podpory pro lokalizaci pohledů a datových anotací
    builder.Services.AddControllersWithViews()
        .AddViewLocalization()
        .AddDataAnnotationsLocalization();
    
    var app = builder.Build();
    
    app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
    
    using (var scope = app.Services.CreateScope())
    {
        var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var roles = new[] { "Admin", "Redaktor", "Member" };
     
        foreach (var role in roles)
        {
            if (!await roleManager.RoleExistsAsync(role))
            {
                await roleManager.CreateAsync(new IdentityRole(role));
            }
        }
    }