Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<char> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,21 +280,17 @@ public static IEnumerable<object[]> ToLower_TestData()

foreach (string cultureName in GetTestLocales())
{
// Android has its own ICU, which doesn't work well with tr
if (!PlatformDetection.IsAndroid && !PlatformDetection.IsLinuxBionic)
{
yield return new object[] { cultureName, "I", "\u0131" };
yield return new object[] { cultureName, "HI!", "h\u0131!" };
yield return new object[] { cultureName, "HI\n\0H\u0130\t!", "h\u0131\n\0hi\u0009!" };
}
yield return new object[] { cultureName, "I", "\u0131" };
yield return new object[] { cultureName, "HI!", "h\u0131!" };
yield return new object[] { cultureName, "HI\n\0H\u0130\t!", "h\u0131\n\0hi\u0009!" };
yield return new object[] { cultureName, "\u0130", "i" };
yield return new object[] { cultureName, "i", "i" };

}

// ICU has special tailoring for the en-US-POSIX locale which treats "i" and "I" as different letters
// instead of two letters with a case difference during collation. Make sure this doesn't confuse our
// casing implementation, which uses collation to understand if we need to do Turkish casing or not.
// casing implementation, which must apply Turkish casing only for the tr and az languages.
if (!PlatformDetection.IsWindows && PlatformDetection.IsNotBrowser)
{
yield return new object[] { "en-US-POSIX", "I", "i" };
Expand Down Expand Up @@ -431,20 +427,16 @@ public static IEnumerable<object[]> ToUpper_TestData()
// Turkish i
foreach (string cultureName in GetTestLocales())
{
// Android has its own ICU, which doesn't work well with tr
if (!PlatformDetection.IsAndroid && !PlatformDetection.IsLinuxBionic)
{
yield return new object[] { cultureName, "i", "\u0130" };
yield return new object[] { cultureName, "H\u0131\n\0Hi\u0009!", "HI\n\0H\u0130\t!" };
}
yield return new object[] { cultureName, "i", "\u0130" };
yield return new object[] { cultureName, "H\u0131\n\0Hi\u0009!", "HI\n\0H\u0130\t!" };
yield return new object[] { cultureName, "\u0130", "\u0130" };
yield return new object[] { cultureName, "\u0131", "I" };
yield return new object[] { cultureName, "I", "I" };
}

// ICU has special tailoring for the en-US-POSIX locale which treats "i" and "I" as different letters
// instead of two letters with a case difference during collation. Make sure this doesn't confuse our
// casing implementation, which uses collation to understand if we need to do Turkish casing or not.
// casing implementation, which must apply Turkish casing only for the tr and az languages.
if (!PlatformDetection.IsWindows && PlatformDetection.IsNotBrowser)
{
yield return new object[] { "en-US-POSIX", "i", "I" };
Expand Down
Loading