Some libraries don't work when an application runs in Globalization-Invariant mode. This mode disables all globalization features and forces the use of the Invariant culture. It is useful for applications that don't need globalization features and want to reduce their size.
If your library doesn't support this mode, you may want to report a meaningful error message to the user, which requires detecting it correctly. Most of the time, the user sets the DOTNET_SYSTEM_GLOBALIZATION_INVARIANT environment variable to true or 1. However, the user can also set the System.Globalization.Invariant switch in the runtimeconfig.json file (this is what happens when you use the <InvariantGlobalization>true</InvariantGlobalization> property in the csproj file). The runtimeconfig.json file contains the runtime configuration of the application. Because of native AOT, some configuration may be stripped when publishing the application, and the only way to verify this is to try to create a culture. This means you need to check multiple sources to detect whether the application is running in Globalization-Invariant mode.
C#
static bool IsGlobalizationInvariant()
{
// Validate the AppContext switch first
if (AppContext.TryGetSwitch("System.Globalization.Invariant", out bool isEnabled) && isEnabled)
return true;
// Then, check the environment variable
var environmentValue = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT");
if (string.Equals(environmentValue, bool.TrueString, StringComparison.OrdinalIgnoreCase) || environmentValue == "1")
return true;
// .NET 6 and greater will throw if the culture is not found, unless PredefinedCulturesOnly is set to false.
// Previous versions will return the Invariant Culture. See the breaking change for more info:
// https://learn.microsoft.com/en-us/dotnet/core/compatibility/globalization/6.0/culture-creation-invariant-mode?WT.mc_id=DT-MVP-5003978
//
// You can detect if a culture is the Invariant culture by checking its name or one of its properties.
// Note: The Invariant Culture is hard-coded: https://github.com/dotnet/runtime/blob/b69fa275565ceeca8ba39f7f9bcb1e301dd68ded/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs#L547
try
{
return CultureInfo.GetCultureInfo("en-US").EnglishName.Contains("Invariant", StringComparison.Ordinal);
// Note: A user can change the settings of the culture at the OS level or ICU data, so the following comparison may be true even if the Invariant Mode is disabled.
// return CultureInfo.GetCultureInfo("en-US").NumberFormat.CurrencySymbol == "¤";
}
catch (CultureNotFoundException)
{
// PredefinedCulturesOnly is true and the Invariant Mode is enabled
return true;
}
}
#Additional resources
Do you have a question or a suggestion about this post? Contact me!