diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.Icu.cs index 0e04fb4dd1e9dd..3c5e215426e3a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.Icu.cs @@ -14,7 +14,20 @@ private static bool NeedsTurkishCasing(string localeName) { Debug.Assert(localeName != null); - return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("\u0131", "I", CompareOptions.IgnoreCase) == 0; + // ICU applies the Turkish dotted/dotless "i" casing rules to the "tr" and "az" + // languages. This is determined from the locale name rather than by probing the + // collation tailoring, because some platforms (notably Android, which uses the + // system ICU) do not ship the collation data that probe relies on, which would + // silently fall back to non-Turkish casing. + ReadOnlySpan language = localeName.AsSpan(); + int separatorIndex = language.IndexOfAny('-', '_'); + if (separatorIndex >= 0) + { + language = language.Slice(0, separatorIndex); + } + + return language.Equals("tr", StringComparison.OrdinalIgnoreCase) || + language.Equals("az", StringComparison.OrdinalIgnoreCase); } internal unsafe void IcuChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper)