Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[iOS][globalization] Incorrect region information when using English (US) language and non-US region #113614

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
matouskozak opened this issue Mar 17, 2025 · 10 comments

Comments

@matouskozak
Copy link
Member

matouskozak commented Mar 17, 2025

There seems to be something off with how iOS determines the language-region combination in preferredLanguages. If you select Germany region, you can choose

  • English (US): this will result in behavior where the region is incorrectly set to US even though iPhone region is still Germany.
2025-03-17 14:16:09.229227+0000 net9_maui[13431:5122872] CultureInfo.CurrentCulture: en-US
2025-03-17 14:16:09.229416+0000 net9_maui[13431:5122872] CultureInfo.CurrentUICulture: en-US
2025-03-17 14:16:09.229760+0000 net9_maui[13431:5122872] CultureInfo.CurrentUICulture.DisplayName: English (United States)
2025-03-17 14:16:09.231533+0000 net9_maui[13431:5122872] RegionInfo.CurrentRegion.CurrencyEnglishName: US Dollar
2025-03-17 14:16:09.231593+0000 net9_maui[13431:5122872] RegionInfo.CurrentRegion.ISOCurrencySymbol: USD
2025-03-17 14:16:09.231654+0000 net9_maui[13431:5122872] RegionInfo.CurrentRegion.CurrencyNativeName: US Dollar
2025-03-17 14:16:09.231694+0000 net9_maui[13431:5122872] RegionInfo.CurrentRegion.CurrencySymbol: $
2025-03-17 14:16:09.231771+0000 net9_maui[13431:5122872] CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol: $
Image
  • English (UK): this will result in correct behavior, i.e., German regional info and English as a language.
2025-03-17 14:13:56.740872+0000 net9_maui[10392:5103515] CultureInfo.CurrentCulture: en-DE
2025-03-17 14:13:56.741067+0000 net9_maui[10392:5103515] CultureInfo.CurrentUICulture: en-DE
2025-03-17 14:13:56.741291+0000 net9_maui[10392:5103515] CultureInfo.CurrentUICulture.DisplayName: English (Germany)
2025-03-17 14:13:56.743050+0000 net9_maui[10392:5103515] RegionInfo.CurrentRegion.CurrencyEnglishName: Euro
2025-03-17 14:13:56.743108+0000 net9_maui[10392:5103515] RegionInfo.CurrentRegion.ISOCurrencySymbol: EUR
2025-03-17 14:13:56.743168+0000 net9_maui[10392:5103515] RegionInfo.CurrentRegion.CurrencyNativeName: Euro
2025-03-17 14:13:56.743215+0000 net9_maui[10392:5103515] RegionInfo.CurrentRegion.CurrencySymbol: €
2025-03-17 14:13:56.743277+0000 net9_maui[10392:5103515] CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol: €

We should always return regional information for Germany as the iPhone region is set that way.

Copy link
Contributor

Tagging subscribers to 'os-ios': @vitek-karas, @kotlarmilos, @ivanpovazan, @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-globalization
See info in area-owners.md if you want to be subscribed.

@makazeu
Copy link
Contributor

makazeu commented Mar 18, 2025

When the language is set to English (UK), why does CultureInfo.CurrentCulture show as en-DE? Shouldn't it be en-GB instead?

@matouskozak
Copy link
Member Author

When the language is set to English (UK), why does CultureInfo.CurrentCulture show as en-DE? Shouldn't it be en-GB instead?

It is still unclear to me why we're seeing this difference behavior between English (UK) and English (US). We're taking the current locale (culture) information directly from NSLocale.preferredLanguages Objective-C API. We might need to revisit if this API is the most appropriate and if something like NSLocale.currentLocale doesn't align better with our use-case.

@makazeu
Copy link
Contributor

makazeu commented Mar 18, 2025

Region should be different from preferred language, because they're simply different things.

For Windows, the current region is the UserGeo from Win32 API:

internal static unsafe CultureData GetCurrentRegionData()
{
Span<char> geoIso2Letters = stackalloc char[10];
int geoId = Interop.Kernel32.GetUserGeoID(Interop.Kernel32.GEOCLASS_NATION);
if (geoId != Interop.Kernel32.GEOID_NOT_AVAILABLE)
{
int geoIsoIdLength;
fixed (char* pGeoIsoId = geoIso2Letters)
{
geoIsoIdLength = Interop.Kernel32.GetGeoInfo(geoId, Interop.Kernel32.GEO_ISO2, pGeoIsoId, geoIso2Letters.Length, 0);
}
if (geoIsoIdLength != 0)
{
geoIsoIdLength -= geoIso2Letters[geoIsoIdLength - 1] == 0 ? 1 : 0; // handle null termination and exclude it.
CultureData? cd = GetCultureDataForRegion(geoIso2Letters.Slice(0, geoIsoIdLength).ToString(), true);
if (cd != null)
{
return cd;
}
}
}
// Fallback to current locale data.
return CultureInfo.CurrentCulture._cultureData;
}

However, for all Unix-like OS's, the current region is simply CurrentCulture:

internal static unsafe CultureData GetCurrentRegionData() => CultureInfo.CurrentCulture._cultureData;

On iOS, the CurrentCulture is the Locale from Native API:

private static string GetLocaleInfoNative(string localeName, LocaleStringData type, string? uiLocaleName = null)
{
Debug.Assert(localeName != null, "[CultureData.GetLocaleInfoNative] Expected localeName to be not be null");
return Interop.Globalization.GetLocaleInfoStringNative(localeName, (uint)type, uiLocaleName);
}

@matouskozak
Copy link
Member Author

On iOS, the CurrentCulture is the Locale from Native API:

I think the CurrentCulture on iOS is taken from

#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS
if (GlobalizationMode.Hybrid)
{
windowsName = Interop.Globalization.GetDefaultLocaleNameNative();
return windowsName != null && windowsName.Length > 0;
}
else
#endif

I agree that it does seem a bit off to use preferredLanguages API to get CurrentCulture region info. @mdh1418 @steveisok do you remember why we switched from using NSLocale.currentLocale to NSLocale.preferredLanguages in #95786? I suppose that NSLocale.preferredLanguages is what usually changes for users on iPhones but I don't now for sure as I would expect NSLocale.currentLocale to work as well (since we use it on macOS also).

@mdh1418
Copy link
Member

mdh1418 commented Mar 19, 2025

@matouskozak No, I don't know any other reason besides trying to fix the issue that the PR targeted. Maybe we should split it into separate functions, one using the preferredLanguage and the other to use the currentLocale.

@tipa
Copy link

tipa commented May 5, 2025

I found a perhaps related problem. Given these macOS settings, I get CultureInfo.CurrentCulture.Name = "en-DE". I think this is the expected behavior, right?

Image

In a similar setup on iOS (see screenshot below), I get CultureInfo.CurrentCulture.Name = "en-DE" when running the app in Debug mode BUT CultureInfo.CurrentCulture.Name = "en" when running the app in Release mode (Native AOT). This causes incorrect results when trying to format (double.ToString()) or parse decimal values (double.TryParse()), among other things.

  • Is this problem covered by this issue as well?
  • Is it safe to construct my own CultureInfo with new CultureInfo(CultureInfo.CurrentCulture.TwoLetterISOLanguageName + "-" + NSLocale.CurrentLocale.RegionCode) until this issue is (hopefully) fixed with .net10 or could this cause problems in certain situations?

Image

@matouskozak
Copy link
Member Author

matouskozak commented May 5, 2025

In a similar setup on iOS (see screenshot below), I get CultureInfo.CurrentCulture.Name = "en-DE" when running the app in Debug mode BUT CultureInfo.CurrentCulture.Name = "en" when running the app in Release mode (Native AOT).

This is a new and different issue I haven't seen before (different behavior in debug and release builds). Could you please open an issue for it with a repro steps?

About the workaround, yes, you could also NSLocale.CurrentLocale.LanguageCode to get the language from the device if that fits your purpose.

@tipa
Copy link

tipa commented May 5, 2025

Thanks - I filed a new issue here: #115302
I think NSLocale.CurrentLocale.LanguageCode is not what I want, it returns "en" for the language/region settings I showed in my screenshots, so my constructed CultureInfo would have the Name "en-en", leading to the same problems as before (e.g. decimals being formatted with a period character as decimal separator)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants