runtime: Blazor globalization inconsistency between WASM and Server

Describe the bug

Working on updates to the Blazor Glob/Loc topic on https://github.com/dotnet/AspNetCore.Docs/pull/22525. cc: @hishamco

Either I’ve hit a bug or a personal knowledge gap: Globalization of a number isn’t consistent across Blazor Server and Blazor WebAssembly.

  • If a knowledge gap that I have, then I’ll address this behavior in the topic’s updates.
  • If a bug, then here it is.

To Reproduce

Blazor WebAssembly (✔️ Working-as-expected Case)

  1. Create a new Blazor WebAssembly app from the project template.

  2. Add CultureExample1 component to the app’s Pages folder:

    @page "/culture-example-1"
    @using System.Globalization
    @using System.Threading
    
    <h1>Culture Example 1</h1>
    
    <!-- 
        Updated code here, but screenshot is this comment will be left as-is.
        I'll add a screenshot of this output at the end of this issue.
    -->
    <ul>
        <li><b>CultureInfo.CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
        <li><b>CultureInfo.CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
        <li><b>Thread.CurrentThread.CurrentCulture</b>: @Thread.CurrentThread.CurrentCulture</li>
        <li><b>Thread.CurrentThread.CurrentUICulture</b>: @Thread.CurrentThread.CurrentUICulture</li>
    </ul>
    
    <h2>Rendered values</h2>
    
    <ul>
        <li><b>Date</b>: @dt</li>
        <li><b>number</b>: @number.ToString("N2")</li>
    </ul>
    
    @code {
        private DateTime dt = DateTime.Now;
        private double number = 1999.69;
    }
    
  3. Run the app. Use a browser with Peruvian Spanish (es-PE) as the first language choice:

    Capture1

    The date AND number are globalized (i.e., in Spanish: date is day-month format + 24-hour clock & number has a comma decimal and period separator). ✔️ All good. ✔️

Blazor Server (❌ Inconsistent/Not-working-as-expected Case)

  1. Create a new Blazor Server app from the project template.

  2. Add loc services:

    services.AddLocalization();
    
  3. Add loc middleware to the pipeline immediately after Routing Middleware:

    app.UseRequestLocalization(new RequestLocalizationOptions()
        .AddSupportedCultures(new[] { "en-US", "es-PE" })
        .AddSupportedUICultures(new[] { "en-US", "es-PE" }));
    
  4. Add the same CultureExample1 component ☝️ to the app’s Pages folder.

  5. Run the app. Use a browser with Peruvian Spanish (es-PE) as the first language choice:

Capture

The date is globalized ✔️, BUT the number isn’t ❌ (i.e., the number doesn’t have a comma decimal and period separator).

Is this the expected outcome, or is this a 🐞? If expected behavior, why? … because I’ll need to address this delta in the doc.

Exceptions (if any)

None

Further technical details

  • ASP.NET Core version

    5.0.6

  • Include the output of dotnet --info

    .NET SDK (reflecting any global.json):
     Version:   5.0.300
     Commit:    2e0c8c940e
    
    Runtime Environment:
     OS Name:     Windows
     OS Version:  10.0.19043
     OS Platform: Windows
     RID:         win10-x64
     Base Path:   C:\Program Files\dotnet\sdk\5.0.300\
    
    Host (useful for support):
      Version: 5.0.6
      Commit:  478b2f8c0e
    
    .NET SDKs installed:
      3.1.302 [C:\Program Files\dotnet\sdk]
      5.0.202 [C:\Program Files\dotnet\sdk]
      5.0.300 [C:\Program Files\dotnet\sdk]
    
    .NET runtimes installed:
      Microsoft.AspNetCore.All 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
      Microsoft.AspNetCore.All 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
      Microsoft.AspNetCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
      Microsoft.AspNetCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
      Microsoft.AspNetCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
      Microsoft.AspNetCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
      Microsoft.AspNetCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
      Microsoft.NETCore.App 2.1.28 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      Microsoft.NETCore.App 2.2.8 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      Microsoft.NETCore.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      Microsoft.NETCore.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      Microsoft.NETCore.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
      Microsoft.WindowsDesktop.App 3.1.15 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
      Microsoft.WindowsDesktop.App 5.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
      Microsoft.WindowsDesktop.App 5.0.6 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
    
  • The IDE (VS / VS Code/ VS4Mac) you’re running on, and its version

    Visual Studio 16.10.0

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 36 (23 by maintainers)

Most upvoted comments

I’ll remark that adding locales isn’t currently supported and maintain a tracking entry to check back later on custom ICU loading so that if/when that becomes available I can work it into a future version of the article.

Good idea, thank you for taking care of that. And no worries, the issue was indeed confusing. I am closing at this stage because it seems clear what is going on.

This is what happens on one cup of ☕ in the morning! I think it takes three cups to get going these days! 🙈

I’ll remark that adding locales isn’t currently supported and maintain a tracking entry to check back later on custom ICU loading so that if/when that becomes available I can work it into a future version of the article. Thanks for bearing with me.

NOW!More ☕☕☕ PLZ! 🤣

My bad, @ilonatommy … I forgot what happened. I opened this back in 2021, and I should’ve reviewed the follow-up remarks.

Is it possible for a dev to add a locale to a Blazor WebAssembly app? I suppose it would be a good idea to let devs know in the Blazor glob+loc article if they can (and how) or if that’s unsupported.

However, my issue here is that it was Blazor Server that wasn’t behaving as expected. See my opening remarks ☝️.

I understand that you opened the issue with the intention to report Blazro Server’s incorrect behavior but after the discussion and @tarekgh’s research, it was figured out it is the other way around. See: https://github.com/dotnet/runtime/issues/54486#issuecomment-865206478

The issue was left opened to continue solving it on WASM side - if Server is in line with Unicode standard and is not the same as WASM then it means something is wrong with WASM. Did I missunderstand something?

Thanks @tarekgh … I wasn’t aware of that (obviously lol). Now that I’ve researched it further, I see that Spanish is split on the format and that Peru is one of the ones with an English-like format for numbers.

Indeed, the Blazor WebAssembly app then goes the other way and is perhaps a problem here (or back on the ASP.NET Core repo). Its number format is a comma decimal and period number separator AFAICT.

@guardrex thanks.

This seems like a runtime bug then.

@guardrex thanks for filing this issue.

This indeed feels like a bug, I’m not sure if its something in the localization middleware or something on the way the number is formatted.

Can you print a few things in your sample: CultureInfo.CurrentCulture CultureInfo.CurrentUICulture Thread.CurrentThread.CurrentCulture Thread.CurrentThread.CurrentUICulture

Can you also show the prerendered vs non-prerendered version on Blazor Server?

You seem to be doing the right things, so I’m not sure if we are missing something on the setup. We don’t play a role in how numbers are formatted, so if all these are the same, then its a runtime issue I believe.

Sorry we are suffer few days ago from ISP, it blocks NuGet feed for unexpected reason. I will respond one everything is working

@hishamco … I put it up here 👉 https://github.com/guardrex/BlazorServerLoc2.

That’s a Blazor Server app created from the project template with the updates that I outlined in my opening comment ☝️.

When I set Opera to issue an Accept-Language header with Peruvian Spanish first, the date appears correctly and as expected … the number doesn’t globalize ❌ (period decimal, comma separator). The same setup in WASM works ✔️: date and number (comma decimal, period separator) are globalized.

As I told you before there was unexpected behavior that I faced long time ago when I was working with localization I Oqtane Framework. Could you please share a minimal repo or a zip file contains the example that you test, I may have a look