Search code examples
c#localizationasp.net-core-2.0globalizationrazor-pages

Localization in ASP.Net Core 2.0 Web Application


I'm trying to globalize, and localize my ASP.NET Core 2.0 Web Application for Spanish. I'm trying to follow the docs, but it really seems like the docs were not meant for Core 2.0, as they don't seem to cover Razor Pages. Only Controllers & Views. Nevertheless, the localization isn't working whether I change the culture in the request headers, or use the query string as shown in the docs. Any insights into what I'm doing wrong?

 http://localhost:26417/?culture=es&ui-culture=es

Startup.cs

public void ConfigureServices( IServiceCollection services )
{
    services.AddDbContext<PartDbContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("PartDatabase"))
        );

    services.AddAuthentication(IISDefaults.AuthenticationScheme);

    services.AddLocalization(options => options.ResourcesPath = "Localization");
    services.AddMvc()
        .AddRazorPagesOptions(options => {
            //options.Conventions.AllowAnonymousToPage("/Index");
            // I can just use [AllowAnonymous] attribute
        })
        .AddViewLocalization()
        .AddDataAnnotationsLocalization();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure( IApplicationBuilder app, IHostingEnvironment env )
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    var supportedCultures = new []
    {
        new CultureInfo("en"),
        new CultureInfo("es"),
    };
    app.UseRequestLocalization(new RequestLocalizationOptions {
        DefaultRequestCulture = new Microsoft.AspNetCore.Localization.RequestCulture("en"),
        SupportedCultures = supportedCultures,
        SupportedUICultures = supportedCultures
    });
    app.UseStaticFiles();
    app.UseMvc(routes => {
        routes.MapRoute(name: "default", template: "{controller}/{action=Index}/{id?}");
    });
}

_ViewImports.cshtml

@using PartDatabase
@using Microsoft.Extensions.Configuration
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Mvc.Localization
@namespace PartDatabase.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@inject IConfiguration Configuration
@inject  IAuthorizationService AuthorizationService
@inject IViewLocalizer Localizer

_Layout.cshtml

<a class="navbar-brand" asp-page="/Index">@Localizer["Part Database"]</a>

File Structure

enter image description here

Resource File

enter image description here

Notes:

  • I tried moving _Layout.es.resx to the root of the Localization folder.
  • I tried tried using "Resources" as the name instead of the name "Localization" as they show in the docs, but I would like to the believe the line options.ResourcesPath = "Localization" takes care of me using a different folder name.

Solution

  • I never got ViewLocalizer to work in layout pages, it seems to be for actual views only. To use localized strings in _Layout.cshtml, this is what I had to do.

    1. Create a dummy class

    This is to be able to look up the resource file later. Path to resource file should reflect on where you put this file. For example, if you put the dummy file in Models/_Shared.cs, the resource file should be in Resources/Models/_Shared.es.resx.

    namespace WebApp.Models
    {
        // dummy class for shared resource strings
        public class _Shared
        {
        }
    }
    

    2. Inject an IHtmlLocalizer in _ViewImports.cshtml

    (or just put it at the top of _Layout.cshtml)

    @inject IHtmlLocalizer<Models._Shared> SharedLocalizer
    

    3. Use SharedLocalizer in _Layout.cshtml instead of Localizer

    SharedLocalizer can be used in other views as well, where you need to use the same shared resource instead of duplicating the translation in different resource files.

    <a class="navbar-brand" asp-page="/Index">@SharedLocalizer["Part Database"]</a>
    

    Update: Verified that this works in a Razor Pages project.