Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect CurrentCulture derived from OS in .NET 8 runtime #110095

Closed
pvlst opened this issue Nov 22, 2024 · 9 comments
Closed

Incorrect CurrentCulture derived from OS in .NET 8 runtime #110095

pvlst opened this issue Nov 22, 2024 · 9 comments

Comments

@pvlst
Copy link

pvlst commented Nov 22, 2024

I'm struggling with incorrect CurrentCulture setting coming from the operating system.

  • the application is built using the SDK image and runs in the aspnet image
  • used images are 8.0-bookworm-slim (Debian 12, amd64)
  • deployed on K8S cluster

When preparing the SDK and aspnet images, the required locales are installed and then set via env variables:

ENV LANG "cs_CZ.UTF-8"
ENV LC_MESSAGES "en_US.UTF-8"

This should work so that all the localized values are in the cs_CZ locale and only messages (exceptions, dotnet tools messages etc.) are in the en_US locale. But it doesn't work as expected. Everything is in en_US locale format (dates, numbers, messages, ...). It's as if the cs_CZ is not set at all.

When I type the locale command into the system, it shows:

LANG=cs_CZ.UTF-8
LANGUAGE=
LC_CTYPE="cs_CZ.UTF-8"
LC_NUMERIC="cs_CZ.UTF-8"
LC_TIME="cs_CZ.UTF-8"
LC_COLLATE="cs_CZ.UTF-8"
LC_MONETARY="cs_CZ.UTF-8"
LC_MESSAGES=en_US.UTF-8
LC_PAPER="cs_CZ.UTF-8"
LC_NAME="cs_CZ.UTF-8"
LC_ADDRESS="cs_CZ.UTF-8"
LC_TELEPHONE="cs_CZ.UTF-8"
LC_MEASUREMENT="cs_CZ.UTF-8"
LC_IDENTIFICATION="cs_CZ.UTF-8"
LC_ALL=

Which seems fine. However, .NET's CurrentCulture and CurrentUICulture both return en-US. The only way to change this is to set LC_ALL to cs_CZ, but that also changes the language of messages, and of course not only in the .NET application, but also in the tools etc., which I don't want.

Why does the .NET 8 not use the cs_CZ locale for dates, numbers or anything really?
Am I doing something wrong or is this a bug?
How is the CurrentCulture determined?
Can you point me to some technical documentation or even source code that explains how it's determined from the OS settings?

Thanks in advance.

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Nov 22, 2024
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Nov 22, 2024
@MichalPetryka
Copy link
Contributor

How is the CurrentCulture determined?
Can you point me to some technical documentation or even source code that explains how it's determined from the OS settings?

I assume it's the same as here:

/// <summary>Environment variables that should be checked, in order, for locale.</summary>
/// <remarks>
/// One of these environment variables should contain a string of a form consistent with
/// the X/Open Portability Guide syntax:
/// language[territory][.charset][@modifier]
/// We're interested in the charset, as it specifies the encoding used
/// for the console.
/// </remarks>
private static readonly string[] s_localeEnvVars = { "LC_ALL", "LC_MESSAGES", "LANG" }; // this ordering codifies the lookup rules prescribed by POSIX

But I can't find the exact place that does it.

Why does the .NET 8 not use the cs_CZ locale for dates, numbers or anything really?

AFAIR .NET only uses a single culture at once, it has no way to use different cultures for different things without you specifying it manually.
Additionally, it's often preferred to use InvariantCulture everywhere but on displaying data to user to avoid behavioural differences between systems.

@jkotas jkotas added area-System.Globalization and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Nov 23, 2024
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-globalization
See info in area-owners.md if you want to be subscribed.

@pvlst
Copy link
Author

pvlst commented Nov 23, 2024

I assume it's the same as here:

runtime/src/libraries/Common/src/System/Text/EncodingHelper.Unix.cs

Lines 21 to 29 in 35e23f7

Thanks, I'll have a look.

Why does the .NET 8 not use the cs_CZ locale for dates, numbers or anything really?

AFAIR .NET only uses a single culture at once, it has no way to use different cultures for different things without you specifying it manually. Additionally, it's often preferred to use InvariantCulture everywhere but on displaying data to user to avoid behavioural differences between systems.

Yes, I use InvariantCulture everywhere except for the human readable output. For example, the application generates many different localized reports that need to have numbers, dates etc. in the cs_CZ format.

The en_US messages and cs_CZ values settings does work correctly in my Windows development environment, and I don't set this explicitly anywhere. So I would hope that it can work the same on Linux environment.

@Suchiman
Copy link
Contributor

AFAIR .NET only uses a single culture at once, it has no way to use different cultures for different things without you specifying it manually.

Not multiple cultures but a custom / modified / forked culture with user overrides like on windows could work. E.g. on Windows you can go to your regional settings and adjust things to your liking
Image
Image
which then reflect in the CurrentCulture. You can explicitly opt out of that by specifying new CultureInfo("de-DE", useUserOverride: false) for example. On non windows platforms, .NET could do the same thing, by starting with a base culture as specified by LANG=cs_CZ.UTF-8 and then load overrides to specific settings.

@tarekgh
Copy link
Member

tarekgh commented Nov 24, 2024

.NET depends on the ICU for getting the default locale which is used as CurrentCulture. ICU is using LC_MESSAGES & LC_ALL for picking the default locale. I am closing this issue but feel free to send any more questions we can help with. It only uses LANG as a fallback if LC_MESSAGES is not defined.

@tarekgh tarekgh closed this as completed Nov 24, 2024
@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Nov 24, 2024
@pvlst
Copy link
Author

pvlst commented Nov 24, 2024

.NET depends on the ICU for getting the default locale which is used as CurrentCulture. ICU is using LC_MESSAGES & LC_ALL for picking the default locale. I am closing this issue but feel free to send any more questions we can help with. It only uses LANG as a fallback if LC_MESSAGES is not defined.

Thanks for the source code links. But I'm not sure if you fully understand my problem.

I want the messages to be in English (en_US) language and all other culture dependent stuff (dates, numbers, ...) to be in Czech (cs_CZ) format. How can I achieve this? Both Linux and Windows systems offer settings where you can configure it that way. It even works in .NET application running in Windows environment.

Why doesn't it work on Linux? Why does .NET take only LC_MESSAGES and apply it to everything?

@tarekgh
Copy link
Member

tarekgh commented Nov 24, 2024

On Linux, both CurrentCulture and CurrentUICulture are determined by the code I referenced, which uses ICU to obtain the locale. This is because .NET relies on ICU on Linux. As a result, both values are the same on Linux.

On Windows, however, the UI culture is configured separately from the current culture settings. Windows uses a distinct mechanism for setting the UI culture. You can still customize this behavior in your code. During your app's initialization, you can read any environment variable of your choice to determine the culture name for both messages and formatting. Then, use CultureInfo.DefaultThreadCurrentUICulture, CultureInfo.CurrentUICulture, CultureInfo.DefaultThreadCurrentCulture, and CultureInfo.CurrentCulture to set these values. This will ensure your app behaves as desired.

@pvlst
Copy link
Author

pvlst commented Nov 24, 2024

On Linux, both CurrentCulture and CurrentUICulture are determined by the code I referenced, which uses ICU to obtain the locale. This is because .NET relies on ICU on Linux. As a result, both values are the same on Linux.

Oh, I see. So in other words, it's not supported/implemented in .NET running on Linux. That's very unfortunate. I also found this 3 years old issue discussing the same thing.

Is this at least planned for a future release? It seems pretty essential to me.

@tarekgh
Copy link
Member

tarekgh commented Nov 25, 2024

#61148 issue is specific to macOS and I this this has been addressed. @steveisok may give more information about this one.

We currently have no plans to change this behavior on Linux, but we welcome your feedback. If there’s significant demand, we may consider it in the future. Could you clarify exactly what changes you’re proposing for Linux platforms?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants