diff --git a/docs/core/compatibility/6.0.md b/docs/core/compatibility/6.0.md index 6a3780518b907..ec6cae156ab80 100644 --- a/docs/core/compatibility/6.0.md +++ b/docs/core/compatibility/6.0.md @@ -52,6 +52,12 @@ If you're migrating an app to .NET 6, the breaking changes listed here might aff | [Standard numeric format parsing precision](core-libraries/6.0/numeric-format-parsing-handles-higher-precision.md) | Preview 2 | | [Unhandled exceptions from a BackgroundService](core-libraries/6.0/hosting-exception-handling.md) | Preview 4 | +## Globalization + +| Title | Preview introduced | +| - | - | +| [Culture creation and case mapping in globalization-invariant mode](globalization/6.0/culture-creation-invariant-mode.md) | Preview 7 | + ## JIT compiler | Title | Preview introduced | diff --git a/docs/core/compatibility/globalization/5.0/unicode-categories-for-latin1-chars.md b/docs/core/compatibility/globalization/5.0/unicode-categories-for-latin1-chars.md index 1f5279a05c7ec..d44b11fafa9dd 100644 --- a/docs/core/compatibility/globalization/5.0/unicode-categories-for-latin1-chars.md +++ b/docs/core/compatibility/globalization/5.0/unicode-categories-for-latin1-chars.md @@ -57,5 +57,5 @@ Additionally, any class that depends on to obtain the Unicode - Core .NET libraries - Globalization -- + --> diff --git a/docs/core/compatibility/globalization/6.0/culture-creation-invariant-mode.md b/docs/core/compatibility/globalization/6.0/culture-creation-invariant-mode.md new file mode 100644 index 0000000000000..dcf43b51e5a56 --- /dev/null +++ b/docs/core/compatibility/globalization/6.0/culture-creation-invariant-mode.md @@ -0,0 +1,62 @@ +--- +title: "Breaking change: Culture creation and case mapping in globalization-invariant mode" +description: Learn about the globalization breaking change in .NET 6 where the creation of new cultures is restricted and case mapping support extends to all characters in globalization-invariant mode. +ms.date: 07/23/2021 +--- +# Culture creation and case mapping in globalization-invariant mode + +This breaking change affects *globalization-invariant mode* in two ways: + +- Previously, .NET allowed any culture to be created in globalization-invariant mode, as long as the culture name conformed to [BCP-47](https://tools.ietf.org/search/bcp47). However, [the invariant culture](/dotnet/api/system.globalization.cultureinfo?view=net-5.0#invariant-neutral-and-specific-cultures) data was used instead of the real culture data. Starting in .NET 6, an exception is thrown if you create any culture other than the invariant culture in globalization-invariant mode. +- Previously, globalization-invariant mode only supported case mapping for ASCII characters. Starting in .NET 6, globalization-invariant mode provides full case-mapping support for all Unicode-defined characters. Case mapping is used in operations such as string comparisons, string searches, and upper or lower casing strings. + +[Globalization-invariant mode](https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md) is used for apps that don't required any globalization support. That is, the app runs without access to culture-specific data and behavior. Globalization-invariant mode is enabled by default on some Docker containers, for example, Alpine containers. + +## Old behavior + +In previous .NET versions when globalization-invariant mode is enabled: + +- If an app creates a culture that's not the invariant culture, the operation succeeds but the returned culture always use the invariant culture data instead of the real culture data. +- Case mapping was performed only for ASCII characters. For example: + + ```csharp + if ("Á".Equals("á", StringComparison.CurrentCultureIgnoreCase)) // Evaluates to false. + ``` + +## New behavior + +Starting in .NET 6 when globalization-invariant mode is enabled: + +- If an app attempts to create a culture that's not the invariant culture, a exception is thrown. +- Case mapping is performed for all Unicode-defined characters. For example: + + ```csharp + if ("Á".Equals("á", StringComparison.CurrentCultureIgnoreCase)) // Evaluates to true. + ``` + +## Version introduced + +.NET 6 Preview 7 + +## Reason for change + +The culture-creation change was introduced to more easily diagnose culture-related problems. Some users are unaware that their apps are running in an environment where globalization-invariant mode is enabled. They may experience unexpected behavior and don't make the association with globalization-invariant mode, so it's hard to diagnose the issue. + +The full case-mapping support was introduced for better usability and experience in globalization-invariant mode. + +## Recommended action + +In most cases, no action is needed. However, if you desire the previous culture-creation behavior, you can set a run-time configuration option to allow creation of any culture in globalization-invariant mode. For more information, see [Predefined cultures](../../../run-time-config/globalization.md#predefined-cultures). + +## Affected APIs + +- +- +- +- +- Any APIs that perform string casing, comparison, or searching + +## See also + +- [.NET globalization invariant mode](https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md) +- [Invariant, neutral, and specific cultures](/dotnet/api/system.globalization.cultureinfo?view=net-5.0#invariant-neutral-and-specific-cultures) diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 92634a7427546..6796528b5542c 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -85,6 +85,10 @@ items: href: core-libraries/6.0/numeric-format-parsing-handles-higher-precision.md - name: Unhandled exceptions from a BackgroundService href: core-libraries/6.0/hosting-exception-handling.md + - name: Globalization + items: + - name: Culture creation and case mapping in globalization-invariant mode + href: globalization/6.0/culture-creation-invariant-mode.md - name: JIT compiler items: - name: Call argument coercion @@ -639,6 +643,10 @@ items: href: /ef/core/what-is-new/ef-core-3.x/breaking-changes?toc=/dotnet/core/compatibility/toc.json&bc=/dotnet/breadcrumb/toc.json - name: Globalization items: + - name: .NET 6 + items: + - name: Culture creation and case mapping in globalization-invariant mode + href: globalization/6.0/culture-creation-invariant-mode.md - name: .NET 5 items: - name: Use ICU libraries on Windows diff --git a/docs/core/project-sdk/msbuild-props.md b/docs/core/project-sdk/msbuild-props.md index 2ac8e79fece77..fa0c15036b575 100644 --- a/docs/core/project-sdk/msbuild-props.md +++ b/docs/core/project-sdk/msbuild-props.md @@ -621,6 +621,7 @@ You can configure some run-time behaviors by specifying MSBuild properties in th - [ConcurrentGarbageCollection](#concurrentgarbagecollection) - [InvariantGlobalization](#invariantglobalization) +- [PredefinedCulturesOnly](#predefinedculturesonly) - [RetainVMGarbageCollection](#retainvmgarbagecollection) - [ServerGarbageCollection](#servergarbagecollection) - [ThreadPoolMaxThreads](#threadpoolmaxthreads) @@ -649,6 +650,18 @@ The `InvariantGlobalization` property configures whether the app runs in *global ``` +### PredefinedCulturesOnly + +In .NET 6 and later versions, the `PredefinedCulturesOnly` property configures whether apps can create cultures other than the invariant culture when [globalization-invariant mode](https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md) is enabled. The default is `true`. Set the value to `false` to allow creation of any new culture in globalization-invariant mode. + +```xml + + false + +``` + +For more information, see [Culture creation and case mapping in globalization-invariant mode](../compatibility/globalization/6.0/culture-creation-invariant-mode.md). + ### RetainVMGarbageCollection The `RetainVMGarbageCollection` property configures the garbage collector to put deleted memory segments on a standby list for future use or release them. Setting the value to `true` tells the garbage collector to put the segments on a standby list. For more information, see [Retain VM](../run-time-config/garbage-collector.md#retain-vm). diff --git a/docs/core/run-time-config/globalization.md b/docs/core/run-time-config/globalization.md index f04968fa8d01c..e92391bd8dbb7 100644 --- a/docs/core/run-time-config/globalization.md +++ b/docs/core/run-time-config/globalization.md @@ -87,3 +87,15 @@ Project file: | - | - | - | - | | **runtimeconfig.json** | `System.Globalization.UseNls` | `false` - Use ICU globalization APIs
`true` - Use NLS globalization APIs | .NET 5.0 | | **Environment variable** | `DOTNET_SYSTEM_GLOBALIZATION_USENLS` | `false` - Use ICU globalization APIs
`true` - Use NLS globalization APIs | .NET 5.0 | + +## Predefined cultures + +- Configures whether apps can create cultures other than the invariant culture when [globalization-invariant mode](https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md) is enabled. +- If you omit this setting, .NET restricts the creation of cultures in globalization-invariant mode. This is equivalent to setting the value to `true`. +- For more information, see [Culture creation and case mapping in globalization-invariant mode](../compatibility/globalization/6.0/culture-creation-invariant-mode.md). + +| | Setting name | Values | Introduced | +| - | - | - | - | +| **runtimeconfig.json** | `System.Globalization.PredefinedCulturesOnly` | `true` - In globalization-invariant mode, don't allow creation of any culture except the invariant culture.
`false` - Allow creation of any culture. | .NET 6 | +| **MSBuild property** | `PredefinedCulturesOnly` | `true` - In globalization-invariant mode, don't allow creation of any culture except the invariant culture.
`false` - Allow creation of any culture. | .NET 6 | +| **Environment variable** | `DOTNET_SYSTEM_GLOBALIZATION_PREDEFINED_CULTURES_ONLY` | `true` - In globalization-invariant mode, don't allow creation of any culture except the invariant culture.
`false` - Allow creation of any culture. | .NET 6 | diff --git a/docs/core/run-time-config/index.md b/docs/core/run-time-config/index.md index 8845486272d3f..d4f4745d8e22b 100644 --- a/docs/core/run-time-config/index.md +++ b/docs/core/run-time-config/index.md @@ -1,11 +1,11 @@ --- title: Run-time config options -description: Learn how to configure .NET Core applications by using run-time configuration settings. -ms.date: 01/21/2020 +description: Learn how to configure .NET applications by using run-time configuration settings. +ms.date: 07/23/2021 --- -# .NET Core run-time configuration settings +# .NET run-time configuration settings -.NET Core supports the use of configuration files and environment variables to configure the behavior of .NET Core applications at run time. Run-time configuration is an attractive option if: +.NET 5+ (including .NET Core versions) supports the use of configuration files and environment variables to configure the behavior of .NET applications at run time. Run-time configuration is an attractive option if: - You don't own or control the source code for an application and therefore are unable to configure it programmatically. @@ -14,7 +14,7 @@ ms.date: 01/21/2020 > [!NOTE] > This documentation is a work in progress. If you notice that the information presented here is either incomplete or inaccurate, either [open an issue](https://github.com/dotnet/docs/issues) to let us know about it, or [submit a pull request](https://github.com/dotnet/docs/pulls) to address the issue. For information about submitting pull requests for the dotnet/docs repository, see the [contributor's guide](/contribute/dotnet/dotnet-contribute). -.NET Core provides the following mechanisms for configuring application behavior at run time: +.NET provides the following mechanisms for configuring application behavior at run time: - The [runtimeconfig.json file](#runtimeconfigjson) @@ -23,7 +23,7 @@ ms.date: 01/21/2020 - [Environment variables](#environment-variables) > [!TIP] -> Configuring a run-time option by using an environment variable applies the setting to all .NET Core apps. Configuring a run-time option in the *runtimeconfig.json* or project file applies the setting to that application only. +> Configuring a run-time option by using an environment variable applies the setting to all .NET apps. Configuring a run-time option in the *runtimeconfig.json* or project file applies the setting to that application only. Some configuration values can also be set programmatically by calling the method.