Windows 10 now carrying a version of ICU. It will be good to allow .NET Core take advantage of that.
Goals
There are 2 goals which if we do will get us in the much better position regarding the globalization support.
- Allow using the installed Windows version of ICU when running on Windows 10 19H1 and up.
- Allow using the app ICU version which the app carry with.
Doing these 2 goals will give the flexibility to the apps to decide if want to use whatever ICU version shipping with Windows or decide to carry its own version of ICU.
How we can support ICU on Windows
- We'll merge System.Globalization.Native code to coreclr and include this code for Windows build too. System.Globalization.Native has the ICU interop.
- Adding a shim to load the ICU libraries like what we are doing on Linux, but we’ll try to load it from different places (From System32 folder or app folder for Windows).
- Having the inteop cs code which is compiled for Linux to be included for Windows too. Of course, we must refactor the current code more and instead of having Windows and Linux cs files, we’ll have NLS and ICU code paths instead.
Loading Default installed ICU on Windows
Windows RS2 started carrying ICU. The ICU DLLs are installed on %WINDIR%\System32 folder.
On RS2, there are 2 DLLs installed there named icuuc.dll and icuin.dll. On 19H1, Windows combined these 2 DLLs into a single DLL named icu.dll.
We'll support the loading ICU on Windows starting from 19H1 version and up. The reason is the previous versions require COM initialization which can cause some issues.
NLS or ICU as a default?
We'll use ICU by default as this is the future direction and we want to get users switch to that. Of course this will be kind of breaking change especially for sorting behavior and locale data. We are going to provide a config switch to allow using NLS if any app wanted to switch back to the old behavior.
Loading non-ICU default libraries
As the second goal is to allow using a specific version of ICU which not necessary the same version shipped with Windows. We are working with Windows team to have them produce ICU NuGet package which apps can get and install with their app (under the app folder). The apps will install it under the app folder for the reasons:
- Not try to access any files outside the app folder. That will be more secure.
- The app can be self-contained and possibly can get the ICU package work seamlessly with the .NET Core csproj which will place the ICU DLLs under the app published folder.
The app can opt-in to the app version using the config switch. We’ll try to find the libraries under the app folder according to the layout decided by NuGet package.
The ICU NuGet package will support running on down level Windows versions (e.g. Windows 7). That can give advantage of using ICU there too.
Config Switch
We need the config switch for 2 reasons:
To opt-in/out to or from using ICU/NLS.
To opt-in use the local app ICU version instead of the global version.
Note, we can have this switch work on Linux/macOS too. so, we’ll allow apps to carry their own ICU version if they need to. The issue here is, so far no one producing NuGet packages for ICU on Linux and macOS. The apps on Linux/macOS will need manually to carry the ICU libs to allow local ICU support.
The suggesting is to have a config switch named System.Globalization.ICU and will have the possible values:
- None means use the ICU (default value).
- NLS means use NLS APIs and not ICU. this value will be supported on Windows only.
- Local use app local version (maybe we need to specify the version in the value but need some more investigation about that).
We’ll support the switch through environment variable too called DOTNET_SYSTEM_GLOBALIZATION_ICU.
Falling back
- If the app didn't opt-in to use NLS and we fail to load the ICU libraries, we’ll fallback to NLS APIs
- If the app opt-in to use local app version of ICU and failed to load it, we'll fail the app and fail fast.
Invariant Mode
If the globalization invariant mode is enabled, we honor it and will not try to load ICU at all.
Windows 10 now carrying a version of ICU. It will be good to allow .NET Core take advantage of that.
Goals
There are 2 goals which if we do will get us in the much better position regarding the globalization support.
Doing these 2 goals will give the flexibility to the apps to decide if want to use whatever ICU version shipping with Windows or decide to carry its own version of ICU.
How we can support ICU on Windows
Loading Default installed ICU on Windows
Windows RS2 started carrying ICU. The ICU DLLs are installed on %WINDIR%\System32 folder.
On RS2, there are 2 DLLs installed there named icuuc.dll and icuin.dll. On 19H1, Windows combined these 2 DLLs into a single DLL named icu.dll.
We'll support the loading ICU on Windows starting from 19H1 version and up. The reason is the previous versions require COM initialization which can cause some issues.
NLS or ICU as a default?
We'll use ICU by default as this is the future direction and we want to get users switch to that. Of course this will be kind of breaking change especially for sorting behavior and locale data. We are going to provide a config switch to allow using NLS if any app wanted to switch back to the old behavior.
Loading non-ICU default libraries
As the second goal is to allow using a specific version of ICU which not necessary the same version shipped with Windows. We are working with Windows team to have them produce ICU NuGet package which apps can get and install with their app (under the app folder). The apps will install it under the app folder for the reasons:
The app can opt-in to the app version using the config switch. We’ll try to find the libraries under the app folder according to the layout decided by NuGet package.
The ICU NuGet package will support running on down level Windows versions (e.g. Windows 7). That can give advantage of using ICU there too.
Config Switch
We need the config switch for 2 reasons:
To opt-in/out to or from using ICU/NLS.
To opt-in use the local app ICU version instead of the global version.
Note, we can have this switch work on Linux/macOS too. so, we’ll allow apps to carry their own ICU version if they need to. The issue here is, so far no one producing NuGet packages for ICU on Linux and macOS. The apps on Linux/macOS will need manually to carry the ICU libs to allow local ICU support.
The suggesting is to have a config switch named System.Globalization.ICU and will have the possible values:
We’ll support the switch through environment variable too called DOTNET_SYSTEM_GLOBALIZATION_ICU.
Falling back
Invariant Mode
If the globalization invariant mode is enabled, we honor it and will not try to load ICU at all.