OrchardCore: CultureInfo should not depend on local computer settings

Describe the bug

When the library sets the culture using new CultureInfo(culture) you can get unexpected results if this is also the system’s culture and data formats were customized. This could be a problem if the server wants one data format for internal administrative use that’s different from the culture’s canonical format.

For example you have an en-US server with date format set to ISO 8601 (this is actually what we have on our CI - this problem is most painful while doing UI tests). Then if you want to display a date in OC with the site set to American locale, it will display it using ISO 8601 which is not what you’d expect. The site’s internationalization should not depend on the local format settings.

To Reproduce

This repro assumes you have Windows 10 with en-US region settings: image

Steps to reproduce the behavior on Windows:

  1. Go to /Admin/Settings/localization and make sure your site is en-US.
  2. Create a new view that contains @T["Date: {0:d}", new DateTime(2022, 02, 21, 12, 0)]
  3. Navigate to it, you will see Date: 2/21/2022.
  4. Go to Start Menu > Settings > Time & Language > Region > Change data format
  5. Change the Short date to “2017-04-05”.
  6. Restart the server.
  7. Visit the same page again, you will see Date: 2022-02-21.

Expected behavior

You should still see Date: 2/21/2022.

Speculation

I believe the problem can be solved simply by altering OrchardCore.Localization.CultureScope.SetCultures to generate fresh stock cultures. So from this:

        private static void SetCultures(CultureInfo culture, CultureInfo uiCulture)
        {
            CultureInfo.CurrentCulture = culture;
            CultureInfo.CurrentUICulture = uiCulture;
        }

Into this:

        private static void SetCultures(CultureInfo culture, CultureInfo uiCulture)
        {
            CultureInfo.CurrentCulture = new CultureInfo(culture.Name, useUserOverride: false);
            CultureInfo.CurrentUICulture = new CultureInfo(uiCulture.Name, useUserOverride: false);
        }

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 67 (67 by maintainers)

Most upvoted comments

@Piedone And this CultureScope uses the same mechanic as the Localization Middleware to be consistent.

I meant the Orchard Core web application, e.g. OrchardCore.Cms.Web.exe (as it acts as an ASP.Net Core server).

Yes, see https://github.com/OrchardCMS/OrchardCore/issues/11228#issuecomment-1092191258

Here for example how SupportedCultures are added to the options when we use AddSupportedCultures, we can see the usage of new CultureInfo(culture) without using useUserOverride: false.

And then the winning culture is set here https://github.com/dotnet/aspnetcore/blob/b2679bf0bfe96cd3f8e1663868f5c87a1b0dbadd/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs#L129-L133

Hmm, one solution would be to not use AddSupportedCultures(), AddSupportedUICultures() and SetDefaultCulture() but our own extensions that would then use new CultureInfo(name, useUserOverride: false).

updated: Maybe a configurable option for the useUserOverride value to use.

We don’t use LCID’s, because they differ from one OS to another; we use the culture code if I remember correctly. So, he says that we should be able to create a standardized CultureInfo from a culture code that will not be altered by the system settings “Normalized”. But optionally allow changing these settings for any culture through the configuration.

ASP.NET you can override date formats of a given culture using RequestLocalizationOptions via Configure/PostConfigure. Same can be achieved in Orchard Core as well with custom module

That we know. The point of this issue is being able to configure the date time format used by Orchard for a given culture to be reliably exactly the same everywhere, regardless of server settings. The culture settings of the server shouldn’t matter.

To make it clear, ASP.NET Localization middleware already sets the cultures the same way that we did without setting useUserOverride to false, so I suggest to file an issue in ASP.NET Core repo