On MSW, wxApp::GetLayoutDirection() incorrectly returns RTL when display language is LTR and region is RTL (Issue #26274)

46 views
Skip to first unread message

Steve Cornett

unread,
Mar 6, 2026, 7:43:17 PMMar 6
to wx-...@googlegroups.com, Subscribed
stevecor created an issue (wxWidgets/wxWidgets#26274)

The function wxApp::GetLayoutDirection() incorrectly returns wxLayout_RightToLeft when the "Windows display setting" is a LTR language and the "Regional format" is set to a RTL language. The return value should be wxLayout_LeftToRight when the display language is LTR.

To reproduce this problem on Windows 11:

  1. go to Windows Settings
  2. go to Time and language
  3. go to Language & region
  4. for the "Windows display language", select a LTR language, such as English
  5. for the "Regional format", select an RTL language, such as Hebrew
  6. run the calendar sample. It is incorrectly in RTL mode.
image.png (view on web)

The cause of the problem is wxWidgets uses LOCALE_NAME_USER_DEFAULT as the locale name, which refers to the region language rather than the display language.

The solution is instead of using LOCALE_NAME_USER_DEFAULT, the locale name should be retrieved using the GetUserPreferredUILanguages API. For example:

ULONG bufferSize = LOCALE_NAME_MAX_LENGTH;
wchar_t localeName[LOCALE_NAME_MAX_LENGTH];
ULONG numLanguages = 1;
GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &numLanguages, localeName, &bufferSize);
GetLocaleInfoEx(localeName, LOCALE_IREADINGLAYOUT, …)

Reproduced with wxWidgets 3.3.2


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274@github.com>

VZ

unread,
Mar 7, 2026, 8:58:09 AMMar 7
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

I didn't try it yet, but wouldn't the proposed fix result in not using proper regional format in this setup?

It looks like we can't be using the same locale for GetLayoutDirection() and GetNumberFormatting() implementation but need to use (at least) 2 different ones...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4016567296@github.com>

Ulrich Telle

unread,
Mar 31, 2026, 11:57:35 AM (3 days ago) Mar 31
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

I discovered this issue just a couple of days ago, because I was very busy with other matters.

I didn't try it yet, but wouldn't the proposed fix result in not using proper regional format in this setup?

Actually, I reproduced the issue today on my Windows 11 development system.

Calling wxUILocale::UseDefault() uses the symbol LOCALE_NAME_USER_DEFAULT under the hood and this locale name corresponds to the locale for regional formatting, not the UI locale (preferred UI language), unfortunately.

@vadz: You are absolutely right that the proposed fix doesn't resolve the issue at all, because then the wrong locale would be used for the regional formatting.

It looks like we can't be using the same locale for GetLayoutDirection() and GetNumberFormatting() implementation but need to use (at least) 2 different ones...

That is true. Under Windows we need 2 different locales under the hood to retrieve the UI language related information (not just the layout direction, BTW) resp the regional formatting related info. That is, we have to adjust the wxUILocale implementation for MSW to use the correct locales under the hood.

On Linux, wxWidgets relies on the behavior of glibc (which will merge different locales depending on the user settings for LC_MESSAGES, LC_TIME, LC_NUMERIC, and LC_MONETARY. That is, on Linux we shouldn't have such issues.

On MacOS, it is most likely necessary to use 2 different locales, too, to be fully generic, if the user has selected a UI language like en or de, but a region setting of IL, for example. AFAIK MacOS would use English resp German as the UI language, but the locale he-IL for the regional formatting.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4163690249@github.com>

Ulrich Telle

unread,
Apr 2, 2026, 5:56:27 AM (yesterday) Apr 2
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

@vadz For Windows I locally adjusted the wxUILocaleImplName, so that it determines internally both locales (UI language and Regional formatting) in case of the default locale (wxUILocaleImpl::CreateUserDefault()). The UI language locale is then used for all language dependent settings (like layout direction or locale names), the locale for regional formatting is used for formatting numbers, dates, times... This is done by directing locale info requests to the appropriate locale internally.

In principle, this works just fine. However, we need to discuss how exactly wxUILocale should behave, if Windows is configured to use different locales for the UI language and the regional formatting:

  • Which locale name should be returned, when calling wxUILocale::GetName()?
    The name of the UI language locale or the locale for regional formatting? IMHO it should be the UI language locale, but then there is the problem that there is no method to determine the name of the locale for regional formatting. Should such a method be added? If yes, this affects also the Linux implementation. And on Linux the situation is even more complex, because one can have different locales for various aspects (LC_TIME, LC_NUMERIC, LC_MONETARY - they all could be different).
  • Which names should be returned for month and weekday names?
    By default Windows uses the values from the locale for regional formatting, but the user might want to retrieve the names conforming to the UI language locale. That is, we may need additional methods.

And there may be other subtleties I'm not yet aware of.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4176064487@github.com>

VZ

unread,
Apr 2, 2026, 5:28:39 PM (yesterday) Apr 2
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

Thanks for looking into this, I didn't have time to really do it myself yet, so I wonder if we really care about what GetName() returns, i.e. what does it change? Could we just return a string combining the 2 names perhaps, e.g. something like UI+Formatting (please free to substitute "+" for any other character or string)?

For the month/weekday names we already have NameForm::Formatting() and Standalone() which seem to map naturally to formatting/UI locale?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4180579267@github.com>

Ulrich Telle

unread,
3:16 AM (17 hours ago) 3:16 AM
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

Thanks for looking into this, I didn't have time to really do it myself yet, so I wonder if we really care about what GetName() returns, i.e. what does it change?

Well GetName() is supposed to return the locale name as used by the operating system. The value should be usable to explicitly set a locale - even if it is non-standard.

Could we just return a string combining the 2 names perhaps, e.g. something like UI+Formatting (please free to substitute "+" for any other character or string)?

IMHO we shouldn't do that.

A clean solution would be to provide a separate API method to retrieve the "formatting" locale name.

However, the question is: Do we really need that?

For example, on Linux a user could have set LC_TIME, LC_NUMERIC, LC_MONETARY to any value of his liking. It would work as expected (at least, I think so), and a wxWidgets application wouldn't know which locale is actually associated with the specific categories.

For the month/weekday names we already have NameForm::Formatting() and Standalone() which seem to map naturally to formatting/UI locale?

Unfortunately, this is not how the operating system itself is handling month/weekday names - AFAIK. For example, if the locale for regional formatting is set to he-IL on Windows, the system calendar control uses Hebrew names for month/weekday names.

  • Formatting context
    • Linux / glibc: Month names, in the grammatical form used when the month is a part of a complete date. (No separate values for weekdays)
    • Windows: Retrieve the genitive names of months, which are the names used when the month names are combined with other items. Note: Genitive month names do not exist in all languages
  • StandAlone context: Month names, in the grammatical form used when the month is named by itself.

If no specific values are available for the formatting context the values from the standalone context will be used for formatting. That is, we can't use the values from the UI language locale without breaking date/time formatting.

If we want to support retrieving month/weekday names in the UI language, we need additional methods.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4182272249@github.com>

Ulrich Telle

unread,
9:42 AM (11 hours ago) 9:42 AM
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

@vadz: I ran into a problem while implementing the fix. To adjust the display format of a date/time picker control I need to be able to determine the name of the locale for regional formatting, because wxUILocale::GetName() will now return the locale for the display language, but the internal function wxGetMSWDateTimeFormat() needs to retrieve the raw info for the date/time format from the regional settings. The API method GetInfo() can't be used unfortunately, because it retrieves an already converted format string.

Actually, this is only relevant, if wxUILocale::UseDefault() was called. Unfortunately, it is not possible to determine whether the current locale was instantiated via wxUILocale::UseDefault().

I see 3 possible approaches to solve the problem:

  1. Add a method IsDefault() to wxUILocale, which returns true if the locale was instantiated via UseDefault(), otherwise false
  2. Add a method GetNameRegional() (or whatever name seems appropriate) to retrieve the name of the locale for regional formatting
  3. Add a friend function to the class definition of wxUILocale to allow that function to access private members of wxUILocale

Option (1) would incur the least effort.

Do you have any preferences? Or do you know a better approach?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4183532785@github.com>

VZ

unread,
10:35 AM (10 hours ago) 10:35 AM
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

Thanks for looking into this, I didn't have time to really do it myself yet, so I wonder if we really care about what GetName() returns, i.e. what does it change?

Well GetName() is supposed to return the locale name as used by the operating system. The value should be usable to explicitly set a locale - even if it is non-standard.

By packing both locales into it (in some way), we could then unpack them when creating the locale and set them correctly.

Could we just return a string combining the 2 names perhaps, e.g. something like UI+Formatting (please free to substitute "+" for any other character or string)?

IMHO we shouldn't do that.

I'm not sure why, it's definitely a hack but it doesn't seem that bad to me. Maybe we should use the form UI=loc1|REGION=loc2 or something like this, which could also be used for Unix where we could return strings like CTYPE=loc1|NUMERIC=loc2|....

A clean solution would be to provide a separate API method to retrieve the "formatting" locale name.

But this wouldn't help with creating the locale, would it? And if the value returned by GetName() can't be used to create an identical locale, it doesn't seem very useful.

However, the question is: Do we really need that?

For example, on Linux a user could have set LC_TIME, LC_NUMERIC, LC_MONETARY to any value of his liking. It would work as expected (at least, I think so), and a wxWidgets application wouldn't know which locale is actually associated with the specific categories.

I'm not 100% sure that it works as expected to be honest...

For the month/weekday names we already have NameForm::Formatting() and Standalone() which seem to map naturally to formatting/UI locale?

Unfortunately, this is not how the operating system itself is handling month/weekday names - AFAIK. For example, if the locale for regional formatting is set to he-IL on Windows, the system calendar control uses Hebrew names for month/weekday names.

I wonder where does it use the English (UI locale) names...

If we want to support retrieving month/weekday names in the UI language, we need additional methods.

We can add additional methods to NameForm, although I have trouble coming up with the good names for them.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4183738056@github.com>

VZ

unread,
11:00 AM (9 hours ago) 11:00 AM
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

I see 3 possible approaches to solve the problem:

1. Add a method `IsDefault()` to `wxUILocale`, which returns `true` if the locale was instantiated via `UseDefault()`, otherwise `false`

I have no problem with adding wxUILocale::IsDefault() but it seems a bit strange to use it to solve this problem. If we ever allow explicitly setting locales using different UI and regional formats, this wouldn't work.

2. Add a method `GetNameRegional()` (or whatever name seems appropriate) to retrieve the name of the locale for regional formatting

I still think it would be better to return this as part of GetName(). For example, I have no idea what GetNameRegional() could possibly return under Unix.

3. Add a `friend` function to the class definition of `wxUILocale` to allow that function to access private members of `wxUILocale`

A bit ugly but at least this doesn't involve any changes in the API, so we can always do this and then replace it with something better later...

Do you have any preferences? Or do you know a better approach?

I think (3) should provide the fastest solution to the problem, but I could be wrong.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4183838969@github.com>

Ulrich Telle

unread,
12:45 PM (8 hours ago) 12:45 PM
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

Well GetName() is supposed to return the locale name as used by the operating system. The value should be usable to explicitly set a locale - even if it is non-standard.

By packing both locales into it (in some way), we could then unpack them when creating the locale and set them correctly.

IMHO we shouldn't make things more complicated than necessary. The problem, we want to solve, is the situation, when a user has configured his Windows system to use one locale for the UI language (Windows Display Language) and a different one for the regional formatting. My guess is that > 99% of the wxWidgets users are not affected, because the same locale is used for both, UI language and regional formatting - otherwise you would have received many complaints much earlier.

A wxWidgets application will be confronted with such a situation, if and only if wxUILocale::UseDefault() is used. If the application uses wxUILocale::UseLocaleName() to instantiate the locale, that locale will be used for the UI language and the regional formatting. Up to now wxWidgets hasn't supported to use more than one locale. And I wouldn't change that, unless there is a real demand.

IMHO supporting full flexibilty in a portable way would be a major effort. On Linux, it would require up to 4 different locales (corresponding to LC_MESSAGES, LC_TIME, LC_NUMERIC, and LC_MONETARY, on Windows and MacOS, it would require 2 different locales.

Could we just return a string combining the 2 names perhaps, e.g. something like UI+Formatting (please free to substitute "+" for any other character or string)?

IMHO we shouldn't do that.

I'm not sure why, it's definitely a hack but it doesn't seem that bad to me. Maybe we should use the form UI=loc1|REGION=loc2 or something like this, which could also be used for Unix where we could return strings like CTYPE=loc1|NUMERIC=loc2|....

Well, currently the locale name is used in deriving the locale id. Typically, the name could be used directly in a call to setlocale(). If we change that behaviour we would have to add code to analyze the name for each supported platform.

And if the internal settings are communicated to the outside, users will expect that they can create a new locale based on that information.

So, I'm strictly against that. Of course, this could be reconsidered if many (maybe 100+ or so) users vote for the general locale feature.

For now, we shouldn't change more than absolutely necessary.

A clean solution would be to provide a separate API method to retrieve the "formatting" locale name.

But this wouldn't help with creating the locale, would it? And if the value returned by GetName() can't be used to create an identical locale, it doesn't seem very useful.

On Windows, the default locale is created with an empty name (nullptr). However, wxUILocale::GetName() will return the locale identifier associated with the default locale. The problem of this issue here arrises from the fact that currently the locale id of the regional formatting locale is returned, not that of the UI language locale (display language).

For most users both locales are identical, but here we have different locales which even have a different layout direction. Using the regional formatting locale for determining the layout direction results in unexpected behaviour.

For most info items we know from which locale they have to be retrieved. So, the adjusted code just uses the appropriate locale internally. To the outside only the (more important) UI language locale name is presented.

However, the question is: Do we really need that?
For example, on Linux a user could have set LC_TIME, LC_NUMERIC, LC_MONETARY to any value of his liking. It would work as expected (at least, I think so), and a wxWidgets application wouldn't know which locale is actually associated with the specific categories.

I'm not 100% sure that it works as expected to be honest...

Neither am I. But I will test that later.

At least on systems with glibc it should work as expected, because glibc merges the final locale by respecting the environment variables LC_*.

Unfortunately, this is not how the operating system itself is handling month/weekday names - AFAIK. For example, if the locale for regional formatting is set to he-IL on Windows, the system calendar control uses Hebrew names for month/weekday names.

I wonder where does it use the English (UI locale) names...

On Windows, the native calendar control will use the locale as specified by the regional formatting locale as defined in the Windows settings.

If we want to support retrieving month/weekday names in the UI language, we need additional methods.

We can add additional methods to NameForm, although I have trouble coming up with the good names for them.

wxDateTime has methods to retrieve the English month/weekday names. For now, this should be enough, because an application could provide translations for month/weekday names if necessary. At least on Linux I'm not sure whether the UI language month/weekday names could be retrieved easily, if the locale settings were configured via different values by LC_* variables.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4184222628@github.com>

Ulrich Telle

unread,
1:07 PM (7 hours ago) 1:07 PM
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

I have no problem with adding wxUILocale::IsDefault() but it seems a bit strange to use it to solve this problem. If we ever allow explicitly setting locales using different UI and regional formats, this wouldn't work.

wxUILocale::IsDefault() would always refer to the default locale settings of the operating system. Never to a locale explicitly set by the application. The default locale can be only instantiated via wxUILocale::UseDefault() - the user has no way to manipulate those locale settings other than manipulating the settings in his operating system.

Even if wxWidgets would allow to explicitly set locales using different locales for the UI language and the regional formatting, that wouldn't matter, because it wouldn't be the default locale of the operating system. That is, the isDefault property would always be false for an explicitly created locale.

Since you say you don't have a problem with adding such a method, I will use that approach.

In any case, the method wxUILocale::IsDefault() might be useful, if an application wants to know for whatever reason whether the application currently uses the default system locale or an explicitly created locale (controlled by the application).

  1. Add a method GetNameRegional() (or whatever name seems appropriate) to retrieve the name of the locale for regional formatting

I still think it would be better to return this as part of GetName(). For example, I have no idea what GetNameRegional() could possibly return under Unix.

Yes, Linux would be a problem, because there could be up to 3 different locales active for regional formatting.

Therefore I would prefer the IsDefault approach for now.

  1. Add a friend function to the class definition of wxUILocale to allow that function to access private members of wxUILocale

A bit ugly but at least this doesn't involve any changes in the API, so we can always do this and then replace it with something better later...

Yes, indeed, it is very ugly, because we would have a friend function definition in the public header file for wxUILocale. No chance to hide it in a private header file.

Do you have any preferences? Or do you know a better approach?

I think (3) should provide the fastest solution to the problem, but I could be wrong.

As said above, I will add method wxUILocale::IsDefault(). It is easy to implement and does no harm to anyone. But it allows to solve this issue without having to jump through hoops.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4184295471@github.com>

VZ

unread,
1:30 PM (7 hours ago) 1:30 PM
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

I think we have no choice but to support Windows systems using different locales for the "display" and "region" and, similarly, for Unix systems using different locales for LC_CTYPE and LC_COLLATE or whatever. Even if few people use such systems, we have no reasonable rationale for telling them that their systems are not supported by wxWidgets because it's not that hard to support them.

And it also seems hard to argue that we should support systems already set up like this but not allow the program to use the same settings. So I think that sooner or later we will need to implement support for this too. Of course, it doesn't have to be done right now, but we should leave it possible to implement this in the future.

And IsDefault() won't help when this is done, which is why I don't like using it for this. More I think about it, less I like it, in fact, because I just don't see any reasonable use for this function: why should the program care if it's using the default locale or not? It seems to me that any use of this function would indicate a broken, or missing, functionality.

So I think we should make IsDefault() private/accessible to friends only for now.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4184405789@github.com>

Ulrich Telle

unread,
4:26 PM (4 hours ago) 4:26 PM
to wx-...@googlegroups.com, Subscribed
utelle left a comment (wxWidgets/wxWidgets#26274)

I think we have no choice but to support Windows systems using different locales for the "display" and "region"

Actually, we have to solve this issue, because currently wxUILocale uses the wrong locale to determine UI language specific parameters, if the operating system is configured with different locales for UI language and regional formatting.

Compared to Linux we need to query different locales on Windows. On Linux, we don't have this problem, because glibc merges the default locale based on the specification given by the environment variables LC_*.

On MacOS, we most likely have to take action, too, if a different region was configured for regional formatting.

and, similarly, for Unix systems using different locales for LC_CTYPE and LC_COLLATE or whatever. Even if few people use such systems, we have no reasonable rationale for telling them that their systems are not supported by wxWidgets because it's not that hard to support them.

AFAICT things should work on Linux systems with the current implementation (but I will verify that, too, of course).

At the moment I don't have access to a MacOS system. So, I can't currently test what needs to be done on MacOS.

And it also seems hard to argue that we should support systems already set up like this but not allow the program to use the same settings.

Sure.

So I think that sooner or later we will need to implement support for this too.

Well, the wxWidgets documentation recommends to use wxUILocale::UseDefault() - and that will be fully supported (after I have finished to adjust the current implementation). Using wxUILocale::UseLocaleName() is possible, but not recommended - and as the documentation notes, it can't be guaranteed that really all controls will obey the locale setting. And currently the same locale will be used for the UI language and the regional formatting.

Of course, it doesn't have to be done right now, but we should leave it possible to implement this in the future.

Supporting to set up different locales for UI language and for regional formatting from within a wxWidgets application via a new API method wxUILocale::UseLocalesForDisplayAndRegionalSettings() (or some other name) would be a major task - probably just for a handful of people. - Personally, I wouldn't do that - out of preemptive obedience - unless a significant number of people are actually requesting this feature.

And IsDefault() won't help when this is done, which is why I don't like using it for this. More I think about it, less I like it, in fact, because I just don't see any reasonable use for this function: why should the program care if it's using the default locale or not? It seems to me that any use of this function would indicate a broken, or missing, functionality.

So I think we should make IsDefault() private/accessible to friends only for now.

Is it really better to make a pure internal (platform dependent) function visible as a friend in the public header file of the wxUILocale class? I don't think so. IMHO being the default os locale is a property of a locale instance, which can't be determined in the current implementation, but is needed to be able to correctly implement access to other locale attributes - to cover use cases as given in this issue.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4185073204@github.com>

VZ

unread,
5:33 PM (3 hours ago) 5:33 PM
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26274)

If the only question is whether IsDefault() should be public or not, let's make it public, while I don't see any reasonable use case for calling it from the application, it probably won't do any harm.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/26274/4185284646@github.com>

Reply all
Reply to author
Forward
0 new messages