Search code examples
.net-corelocalizationglobalizationasp.net-core-3.0

ASP.NET Core 3 Localization is only displaying keys


I am having some issues with getting text localization working in ASP.NET Core 3. Or rather, it was previously working, and since a mishap (not stashing changes and accidentally removing some of them) it no longer does. I'm sure I'm missing something basic, but I can work it out for the life of me.

I've got the following code blocks in place:

Startup.cs:

        private static readonly List<CultureInfo> SupportedCultures = new List<CultureInfo>
        {
            new CultureInfo("en"),
            new CultureInfo("fr")
        };

// ...

            services.AddMvc()
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
                .AddDataAnnotationsLocalization(options =>
                {
                    options.DataAnnotationLocalizerProvider = (type, factory) =>
                        factory.Create(typeof(Language));
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
                .AddRazorPagesOptions(options =>
                {
                    options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
                    options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
                });

            services.AddLocalization(o =>
            {
                o.ResourcesPath = "Resources";
            });

            services.Configure<RequestLocalizationOptions>(options =>
            {
                options.DefaultRequestCulture = new RequestCulture("en", "en");
                options.SupportedCultures = SupportedCultures;
                options.SupportedUICultures = SupportedCultures;
            });
// ...


            app.UseRequestLocalization(new RequestLocalizationOptions
            {
                DefaultRequestCulture = new RequestCulture("en"),
                SupportedCultures = SupportedCultures,
                SupportedUICultures = SupportedCultures,
                RequestCultureProviders = new List<IRequestCultureProvider>
                {
                    new QueryStringRequestCultureProvider(),
                    new CookieRequestCultureProvider()
                }
            });

Resources\Language.cs:

    public sealed class Language
    {

        public sealed class Login
        {
            public const string PageTitle          = nameof(Login) + nameof(PageTitle);
            public const string SubmitButton       = nameof(Login) + nameof(SubmitButton);
            public const string Username           = nameof(Login) + nameof(Username);
            // ...
        }
    }

View:

@inject IHtmlLocalizer<Language> Localizer

...

@Localizer[Language.Login.SubmitButton]

I also have the following resx files containing the keys and text.
Resources\Language.resx (also tried with name Language.en.resx to no avail)
Resources\Language.fr.resx

All text is simply showing as the keys, regardless of whether it originates in an MVC View, Razor page, arbitrary class taking the localizer from DI, or attributes.

Any clue as to what I'm doing wrong? Thanks


Solution

  • So, ultimately it turns out that it's just the location of the Language.cs file that mattered here. Having it within the Resources folder was causing something to break (even without taking the namespace for that folder), whereas having it in the Project root works without issue.

    I'm not exactly sure why this matters though - I'll edit this answer if I can find that out.

    EDIT: Thanks to @Grimm for finding the answer. This does indeed appear to be a bug in .net core 3.1, as detailed on https://github.com/dotnet/aspnetcore/issues/17733