localizationblazorresourcemanager

IStringLocalizer<T> doesn't work in Asp.Net core Blazor Server


I have set it up for localization as follows:

Set the neutralLanguage for the project,

// .csproj
<NeutralLanguage>ko-KR</NeutralLanguage>

Registered localization services into the service container,

// program.cs
builder.Services.AddLocalization(options =>
        {
            options.ResourcesPath = "Resources";
        }) ;

...

app.UseRequestLocalization(new RequestLocalizationOptions()
     .AddSupportedCultures(new[] { "ko-KR", "en-US" })
     .AddSupportedUICultures(new[] { "ko-KR", "en-US"}));

...

Created a .resx file in ~\Resource directory with VS 2022, which created .Designer.cs in the directory as per to my configuration

//~\Resources
UIStrings.resx
UIStrings.Designer.cs

Added a string resource into UIStrings.resx, for example:

Name : "이름" 

FYI, "이름" is Korean for English "name".

and, I am seeing the below result:

// .razor
...
@inject IStringLocalizer<UIStrings> Localizer

...

@UIStrings.Name                              // prints "이름"
@UIStrings.ResourceManager.GetString("Name") // prints "이름"
@Localizer["Name"]                            // prints "Name" <= not good

I don't know why IStringLocalizer doesn't work.


Solution

  • I tried some code and found how IStringLocalizer<T> behaves and how it differs from the behavior of ResourceManager.

    The failure of my question was from different file-location behavior of IStringLocalizer.

    All relevant comments are added between code shown here:

    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using Microsoft.Extensions.Localization;
    using ResourceManagementExam.Controls;
    using ResourceManagementExam.Pages;
    using ResourceManagementExam.Resources; // <== to identify Resource1 class
    using System.Globalization;
    using System.Resources;
    
    namespace ResourceManagementExam;
    internal class Program
    {
        private static void Main(string[] args)
        {
            var builder = Host.CreateApplicationBuilder(args);
    
            builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
            var app = builder.Build();
    
            // ResourceManager
            // requires the root name of the argument to be identical to that of .resx by default.         
            var rm = new ResourceManager(typeof(Resource1)); 
    
            Console.WriteLine($"UI Culture: {Thread.CurrentThread.CurrentUICulture}");
            Console.WriteLine("Hello : " + rm.GetString("Hello"));
            Console.WriteLine();
    
    
            // IStringLocalizer<T>
            // options.ResourcesPath = "Resources", which is the relative root path.
            var programLocalizer = app.Services.GetRequiredService<IStringLocalizer<SharedResource>>();
            Prints(programLocalizer);
    
            var indexPageLocalizer = app.Services.GetRequiredService<IStringLocalizer<IndexPage>>();
    
            Prints(indexPageLocalizer);
    
            var searchBarLocalizer = app.Services.GetRequiredService<IStringLocalizer<SearchBar>>();
    
            Prints(searchBarLocalizer);
        }
    
        private static void Prints(IStringLocalizer localizer)
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("ko-KR");
            Console.WriteLine($"UI Culture: {Thread.CurrentThread.CurrentUICulture}");
            Console.WriteLine("Hello : " + localizer["Hello"]);
            Console.WriteLine();
    
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
            Console.WriteLine($"UI Culture: {Thread.CurrentThread.CurrentUICulture}");
            Console.WriteLine("Hello : " + localizer["Hello"]);
            Console.WriteLine();
        }
    }
    

    The project folder structure is:

    enter image description here