docs/design/features/globalization-invariant-mode.md
Author: Tarek Mahmoud Sayed
The globalization invariant mode - new in .NET Core 2.0 - enables you to remove application dependencies on globalization data and globalization behavior. This mode is an opt-in feature that provides more flexibility if you care more about reducing dependencies and the size of distribution than globalization functionality or globalization-correctness.
The drawback of running in the invariant mode is applications will get poor globalization support. This new option is only recommended for developers that understand globalization and the impact of its absence.
The following scenarios are affected when the invariant mode is enabled. Their invariant mode behavior is defined in this document.
Globalization rules and the data that represents those rules frequently change, often due to country-specific policy changes (for example, changes in currency symbol, sorting behavior or time zones). Developers expect globalization behavior to always be current and for their applications to adapt to new data over time. In order to keep up with those changes, .NET Core (and the .NET Framework, too) depends on the underlying OS to keep up with these changes.
Relying on the underlying OS for globalization data has the following benefits:
Globalization support has the following potential challenges for applications:
Note: On Linux, .NET Core relies on globalization data from ICU. For example, .NET Core Linux Docker images install this component. Globalization data is available on Windows and macOS as part of their base installs.
When enabling the invariant mode, the behavior depends on the PredefinedCulturesOnly setting. When true (the default), creation of any culture except the invariant culture is disallowed. When false, all cultures behave like the invariant culture. The invariant culture has the following characteristics:
String casing (ToUpper and ToLower) will be performed for the ASCII range only. Requests to case code points outside that range will not be performed, however no exception will be thrown. In other words, casing will only be performed for character range ['a'..'z'].
Turkish I casing will not be supported when using Turkish cultures.
String operations like Compare, IndexOf and LastIndexOf are always performed as ordinal and not linguistic operations regardless of the string comparing options passed to the APIs.
The ignore case string sorting option is supported but only for the ASCII range as mentioned previously.
For example, the following comparison will resolve to being unequal:
However, the following comparison will resolve to being equal:
It is worth noticing that all other sort comparison options (for example, ignore symbols, ignore space, Katakana, Hiragana) will have no effect in the invariant mode (they are ignored).
Sort keys are used mostly when indexing some data (for example, database indexing). When generating sort keys of 2 strings and comparing the sort keys the results should hold the exact same results as if comparing the original 2 strings. In the invariant mode, sort keys will be generated according to ordinal comparison while respecting ignore casing options.
String normalization normalizes a string into some form (for example, composed, decomposed forms). Normalization data is required to perform these operations, which isn't available in invariant mode. In this mode, all strings are considered as already normalized, per the following behavior:
true.Internationalized Domain Names require globalization data to perform conversion to ASCII or Unicode forms, which isn't available in the invariant mode. In this mode, IDN functionality has the following behavior:
When running on Linux, ICU is used to get the time zone display name. In invariant mode, the standard time zone names are returned instead.
Applications can enable the invariant mode by either of the following:
in project file:
<PropertyGroup>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>
in runtimeconfig.json file:
{
"runtimeOptions": {
"configProperties": {
"System.Globalization.Invariant": true
}
}
}
setting environment variable value DOTNET_SYSTEM_GLOBALIZATION_INVARIANT to true or 1.
Note: value set in project file or runtimeconfig.json has higher priority than the environment variable.