localizationblazor-webassemblyresx

Resx in Blazor WASM: What is "the issue" with the old static way of using the Resx Files?


[Disclaimer: I'm a long-time Desktop developer slowly learning Web and Blazor, so might be a noob question] but,

How come, when you try to find best-practice for doing Localization in Blazor you are told from official MS Docs (https://learn.microsoft.com/en-us/aspnet/core/blazor/globalization-localization?view=aspnetcore-5.0&pivots=webassembly) and various blogs to do the following:

  1. Add NuGet Package: Microsoft.Extensions.Localization
  2. Register localization "builder.Services.AddLocalization();"
  3. Add your resx Files
  4. Make IStringLocalizer (@inject IStringLocalizer Loc)
  5. And finally use the following in your razor pages: @Loc["Greeting"]

Sure above works, but to a Desktop developer, this feels like a massive step-back in quality and "refactor-safeness" and the new way to use "magic strings" to reference the translations.

I've tested, and the "old way" on a Blazor Page of just:

  1. Adding a MyResource.resx
  2. Let it use the custom tool "PublicResXFileCodeGenerator" to make the .designer file
  3. Simply reference the translation using MyResource.MyTranslationKey;

It works, it is refactor-safe, no need for an injection or NuGet packages... It just works, but despite that, it is not the recommended way... My question is why not? What is the drawback (all the blog and documentation fail to say why the new way is better)

enter image description here


Solution

  • I think there are a number of disadvantages using PublicResXFileCodeGenerator, which may have led to the current recommendations on how to support i18n-capabilities in [blazor-]apps.

    Note that this is just a list of reasons I personally came up with finding possible causes which may have led to the current recommendations:

    A: Visual Studio exclusivness

    The way how PublicResXFileCodeGenerator generates files seem to be VisualStudio exclusive. Today´s teams tend to use a variety of IDEs / editor to build software, (f.e. VS, VSCode, Rider, WebStorm, etc.).

    At least from my perception over the last couple of years

    using IStringLocalizer works for all editors, even notepad or vim.

    B: no default fallback

    With the recommended way of accessing a translation, there will always be a useful fallback which is provided in markup. That is not the case when using the generated types to access translation-units.

    C: no builtin-support for interpolation

    Using IStringLocalizer, there is a built-in, lightweight and formalized way for utilizing interpolated strings. It even encourages using such strings in favor of manually building together such values, which is considered bad-practice when translating software.

    DO:

    @inject IStringLocalizer<DemoPage> L
    
    <h1>@L["Greetings,  {0}", userName]</h1> <!--Greetings, Arthur-->
    
    @code {
      string userName = "Arthur";
    }
    

    DON´T:

    
    <h1>@DemoPageRessources.Greeting @userName</h1> <!--Greetings Arthur-->
    
    @code {
      string userName = "Arthur";
    }
    

    this dictates the order of strings, which might be OK for one language, but not for another. Achieving this with the generated type is a bit more verbose, and even may lead to runtime-exceptions, when there is no actual translation, i guess.