[GNC-dev] Early locale initialization

John Ralls jralls at ceridwen.us
Sat Mar 20 12:43:01 EDT 2021

> On Mar 20, 2021, at 3:10 AM, Geert Janssens <geert.gnucash at kobaltwit.be> wrote:
> Op vrijdag 19 maart 2021 02:19:46 CET schreef John Ralls:
>>> On Mar 18, 2021, at 6:08 AM, Geert Janssens <geert.gnucash at kobaltwit.be>
>>> wrote:> 
>>> Op donderdag 18 maart 2021 13:56:35 CET schreef Derek Atkins:
>>>> On Thu, March 18, 2021 7:58 am, Geert Janssens wrote:
>>>> [snip]
>>>>> 3. While all three allow to tweak some environment parameters, only
>>>>> linux
>>>>> allows the user to do so via the environment file. For Windows and Macos
>>>>> that
>>>>> file is only read after locale is set. Whether that's a good thing
>>>>> depends
>>>>> on
>>>>> the answer to question 2.
>>>> Are you saying that /etc/gnucash/environment (or the equivalent thereof)
>>>> is not read/used on Windows or Mac?
>>> No, it is used on all platforms. But it's only read after locale
>>> initialization on mac/windows has been done. So for locale initialization
>>> it only will affect linux. The other parameters in there (like
>>> LD_LIBRARY_PATH tweaks and so on) will still affect all platforms.
>> No, it's read after the other initializations so that it will override them.
>> As long as setlocale is called after loading the environment then the last
>> computed locale is what GnuCash starts up with. I've tested that pretty
>> extensively on both macOS and Win32, though not since last fall.
> Running this through a debugger I see setlocale gets called indeed afterwards 
> but more by chance than by choice (the first time during gtk's 
> initialization).
> To zoom in on this: if I get you right the idea is effectively to allow users 
> to set LC_ALL in the environment file and make it override whatever system 
> locale was found (or fallen back to).
> The code and comment in https://github.com/Gnucash/gnucash/blob/maint/gnucash/
> gnucash-core-app.cpp#L424 certainly don't suggest that. For Macos and Windows 
> it explicitly excludes the call to setlocale, with the suggestion it was 
> already done. That's contrary to that intent.
> I guess the part that complicates this area is that on both Windows and Macos 
> there are two locales to take into account - the posix locale and the platform 
> native one.
> The windows branch of this code explicitly tries to set both to the same 
> locale. If it finds LC_ALL, LC_MESSAGES or LANG it will use that for posix and 
> then set the same for the Windows locale. In the absence of any of these it 
> will start from the Windows locate and use that to also set the posix locale. 
> To me that suggests the environment overrides should happen before calling 
> this code. If you do it afterwards like we do now you may end up with out of 
> sync Windows and Posix locales. I have no idea if that would have side-effects 
> but I can imagine this could result in some obscure locale related corner case 
> bugs.
> If I read the mac branch of the code correctly, it always starts from the 
> Macos locale and tries to derive a posix locale from it. A user can afterwards 
> override that posix locale via settings in the environment file. The mac 
> locale will never be updated to match any posix locale though. Again I don't 
> know if that could be cause for issues.
> Do you think a reverse mapping as in the Windows environment would be possible 
> ? I mean if users set LC_ALL (or related), can we use that to set the Macos 
> locale for the gnucash process space ? I don't know enough of the platform to 
> know whether Macos allows an application to change locales.


You're right about the order, but doesn't guile call setlocale before gtk does? That's significant only because Guile spawns a bunch of threads and those keep the locale generated by its setlocale call. The main thread that GnuCash and Gtk use is governed by the last setlocale call in the main thread which is generally the one in gtk_init.

GnuCash uses libc localization and at that level there's no difference at all between Linux and macOS: They're both flavors of unix. macOS has two "native" locales: The low-level standard C one and a more nuanced implemented via (wrapped and renamed) ICU locales. The macOS implementations of bash, csh, tcsh, and zsh set the LC_FOO environment variables from those more nuanced values but since GnuCash doesn't invoke a shell we have to do likewise in set_mac_locale in order to get the libc locale set up to match the user's preferences. Of course the user can also run GnuCash from the command line so we have to respect the environment passed in from the shell, and then there's the environment file.

Windows is a bit different because while it implements the standard C localization functions it does it its own way. Guile complicates it a bit because they call (IIRC via GnuLib, haven't looked at their code in a while) the Win32 function SetThreadLocale() instead of the standard C setlocale so set_win32_thread_locale has to make sure that both are set up to the same locale or things get weird in reports and the QIF importer. I guess that we still have a problem there because the environment file gets read after set_win32_thread_locale runs. If the user sets a locale in there that's different from what we got from the run environment then it's possible that guile and the GUI will be out of sync.

John Ralls

More information about the gnucash-devel mailing list