Page MenuHome GnuPG

Kleopatra, Libgpg-error: Let the GUI change the language on Windows
Open, NormalPublic

Description

This task description has been updated by aheinecke.

The GnuPG System and GpgOL / GpgEX detect the language through GetThreadLocale or Environment variables on Windows (libgpg-error is responsible for that). This might not be the configured display language and it might also differ from Kleopatra which has a dedicated setting.

A good fix could be that Kleopatra would write a registry Key that notes "it's" Language and that libgpg-error "my_nl_locale_name" would read / respect that language. This would also make it easier for admins to globally configure languages.

Original report was: "Wrong Display Language":
Hi
GPGOL shows the wrong display language. My OS and Office is English and the GPGOL is always german.


Thanks
Martin

Details

Version
gpgol 2.0.6-beta9

Event Timeline

Mak created this object in space S1 Public.
aheinecke added a subscriber: aheinecke.

GpgOL should use the same language detection code that GnuPG also uses. If you open a command line (cmd) and run "gpg" in that command line is it also in german?

Hi @aheinecke
Its also german:

C:\WINDOWS\system32>dism /online /get-intl

Deployment Image Servicing and Management tool
Version: 10.0.16299.15

Image Version: 10.0.16299.125

Reporting online international settings.

Default system UI language : en-GB
The UI language fallback is : en-US
System locale : de-CH
Default time zone : W. Europe Standard Time
Active keyboard(s) : 0807:00000807, 0809:00000807, 100c:0000100c
Keyboard layered driver : PC/AT Enhanced Keyboard (101/102-Key)

Installed language(s): de-DE
  Type : Partially localized language, MUI type.
  Fallback Languages en-US
Installed language(s): en-GB
  Type : Partially localized language, MUI type.
  Fallback Languages en-US

The operation completed successfully.
aheinecke lowered the priority of this task from Low to Wishlist.Jan 12 2018, 8:48 AM
System locale : de-CH

For windows we either look at the standard POSIX environment variables (LC_ALL, LANG etc.) and if they are not set we use "GetThreadLocale"

The most "unsurprising" behavior would probably be if the gnupg system and GpgOL / GpgEX would also switch the language if Kleopatra's language is changed. I'll update the task description accordingly.

aheinecke renamed this task from Wrong display language to Kleopatra, Libgpg-error: Let the GUI change the language on Windows.Jan 12 2018, 8:52 AM
aheinecke claimed this task.
aheinecke updated the task description. (Show Details)
aheinecke edited projects, added gpg4win, gpgrt; removed gpgol.

Thanks. In the meantime GpgOL takes it's language from the Outlook configured display language setting. I'll add support for override locale to gpgol so that the locale is set accordingly

Use that function as early as possible. The gpg-error tool has also be enahnced on Windows:

gpg-error --locale

prints the used locale in XPG form (e.g. de_DE) and

gpg-error --locate 0x200c

prints "fr_RE". If the given language is not supported by libgpg-error, "C" is printed.

I don't think this works for me in that way.

I'm calling everything through GPGME and so it does not help much if my gpgrt locale inside of gpgol is different. E.g. for gpgconf this does not change the output of the configuration options.

I think I have to look into the GPGME locale override and then we would need to pass it somehow. I wonder: Why don't I just setenv("LANG " ... early in my program?

Note: If you want to set this early in your program you need to make sure that there is only one thread running.

ebo raised the priority of this task from Wishlist to Normal.Nov 28 2023, 9:14 AM
ebo added projects: vsd33, Restricted Project.
ebo added a subscriber: ebo.

Raising prio in reaction to some customer feedback

Some technical details:

  • KDE's ki18n uses the LANGUAGE variable to set/get the language to use. On Unix, we simply use QLocale::system(), but on Windows and macOS we look directly at the LANGUAGE variable because Qt ignores this variable on those systems. See https://invent.kde.org/frameworks/ki18n/-/blob/kf5/src/i18n/main.cpp#L63
  • KDE's kxmlgui reads the application-specific override language from the file QStandardPaths::GenericConfigLocation + "/klanguageoverridesrc" and sets the LANGUAGE variable accordingly (which is then picked up by ki18n). Example from my system:
[Language]
kmymoney=@ByteArray(de)

Regarding the format, =de would probably also work.
See https://invent.kde.org/frameworks/kxmlgui/-/blob/kf5/src/kswitchlanguagedialog_p.cpp#L64

In GpgOL at least I have an API call to query the display language of outlook. I just need to pass it through to gpgme early and forgot about it. Also I don't think this would actually help completely if gpg-agent is running already.

On Linux, gpgme already passes the locale (set with gpgme_set_locale) to gpg which should pass it with every session to gpg-agent. No idea if this also happens on Windows because there are some ifdef's. The gpgme documentation mentions that the locale should be set immediately after gpgme has been initialized and that gpgme doesn't do it itself because it wouldn't be thread safe.

I notices this again, even though my display language is german and Kleopatra is german the GnuPG system is using english (gpg-error --locale says en_IE). en_IE was set by virtualbox during windows installation. No environment variables are set related to language.

This causes pinentry and GnuPG to be english and Kleopatra to show the english compliance string. Otherwise the Kleopatra UI is in german. Ebo had the opossite problem, that Kleopatra showed the german compliance string even after Kleopatra was changed to English. Since this is assigned to me anyway I look into it further. Although I think that gpg-error locale detection is wrong here if you look at the screenshot and the settings, we might be able to fix the symptoms in Kleopatra.

With debug output I have confirmed that KConfig uses the defaultLocale at this point to read the VS-NfD name. So one issue here is that KConfig needs to use the Language configured for translations when reading out the config from which we take the VS-NfD name.

The second part is that Qt uses GetUserDefaultLCID https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getuserdefaultlcid to determine the system locale. This returns the code for en-IE. This is correct but for the displayLanguage it should be a different one as selected by the user. So GetUserPreferredUILanguages returns on my System "de-DE" followed by "en-US".
So I would say we need to tell kconfig that it should use the display language when reading the config.
I have tested it and it works if we do that early in Kleopatra, but what has me confused still is that. For me QLocale::system().uiLanguages(); list for my test system en-IE, en-Latn-IE, de-DE, de-Latn-DE, en-US, en-Latn-US so german only on second place. Even though when I look at the Qt Code this also uses GetUserPreferredUILanguages and I do not know yet where the primary en-IE comes from there.

Anyway that would be the part of the default language detection. If the user has changed the language through settings we need to make sure that this is also respected by KConfig. For that I think the easiest way would be to change the default locale, but I expect that this will break other locale specific settings like date/time format.
Another thing then is to pass that language to GnuPG using:

gpgrt_w32_override_locale (nullptr, langId)

To then set the locale to german, but this also did not work right away, if I generated a new key it was still queried in English. So I think what we want is that in the end for GnuPG and Kleopatra regarding the language:

  1. We take the value of the environment variable LANG, as an override.
  2. A configured language in Kleopatra.
  3. The first return value of GetUserPreferredUILanguages (That is the language all Windows UI elements are in.)

And that needs to be respected by Kleopatra and the background libaries like KConfig, the QtTranslations and the KDE Translations and additionally by the GnuPG system.
In the past I have also seen quite often that the Qt Translations with standard actions like OK and Cancel were translated differently then KDE Strings. So there is also some difference with that on Windows.

Don't change the existing KDE behavior for loading the correct Qt translations which is the same as gettext's behavior. It took quite some time to get it right on Windows for KDE. The important bits for making the language configured by the user work are in
https://invent.kde.org/frameworks/kxmlgui/-/blob/master/src/kswitchlanguagedialog_p.cpp?ref_type=heads#L64
where the user-configured languages are prepended to LANGUAGE and in
https://invent.kde.org/frameworks/ki18n/-/blob/master/src/i18n/main.cpp?ref_type=heads#L65
where we make sure that we load the correct Qt translations also on non-Linux systems (where Qt doesn't respect LANGUAGE).

We need to use a copy of getSystemLocale() to get the language we need to use for libgpg-error.

gpgrt_w32_override_locale probably sets the language only for the current thread. At least, that's how gettext_use_utf8 works why I made sure that Kleopatra only asks libgpg-error for error strings shown to the user in the main thread. (Update: It seems that the override locale is used for all threads, i.e. it doesn't use thread-local storage, but that setting the override locale is not thread-safe.)

KConfig uses the default locale instead of the system locale by default it seems:
https://invent.kde.org/frameworks/kconfig/-/blob/master/src/core/kconfig.cpp?ref_type=heads#L118
This should probably also use a copy of ki18n's getSystemLocale() instead. Or we set Qt's default locale to this value to get KConfig to use it.

In the past I have also seen quite often that the Qt Translations with standard actions like OK and Cancel were translated differently then KDE Strings. So there is also some difference with that on Windows.

I have fixed this problem with https://invent.kde.org/frameworks/ki18n/-/commit/fb7d5e2a0433f171229ef58393cbfbf0e23ab2b6 some time ago.

Don't change the existing KDE behavior for loading the correct Qt translations which is the same as gettext's behavior. It took quite some time to get it right on Windows for KDE.

I am working on KDE / Qt translation selection and so on for quite some time now, too 622437410e1a79ec7fe309af8aab78e87a91d778 and mostly it behaves ok. But as I can now clearly observe not all cases are covered, especially those where the UILanguage is involved and that differs from the System Locale.

The important bits for making the language configured by the user work are in
https://invent.kde.org/frameworks/kxmlgui/-/blob/master/src/kswitchlanguagedialog_p.cpp?ref_type=heads#L64
where the user-configured languages are prepended to LANGUAGE and in

Ok Having that code in the dialog, i would have expected that it is only executed in case the dialog is used to change the language.

https://invent.kde.org/frameworks/ki18n/-/blob/master/src/i18n/main.cpp?ref_type=heads#L65
where we make sure that we load the correct Qt translations also on non-Linux systems (where Qt doesn't respect LANGUAGE).

We need to use a copy of getSystemLocale() to get the language we need to use for libgpg-error.

gpgrt_w32_override_locale probably sets the language only for the current thread. At least, that's how gettext_use_utf8 works why I made sure that Kleopatra only asks libgpg-error for error strings shown to the user in the main thread. (Update: It seems that the override locale is used for all threads, i.e. it doesn't use thread-local storage, but that setting the override locale is not thread-safe.)

If the LANGUAGE environment variable is set correctly by Ki18n then AFAIR it should be also respected by GnuPG et.al. automatically since they inherit the environment.

Thanks for pointing out the important places to check.

In the past I have also seen quite often that the Qt Translations with standard actions like OK and Cancel were translated differently then KDE Strings. So there is also some difference with that on Windows.

I have fixed this problem with https://invent.kde.org/frameworks/ki18n/-/commit/fb7d5e2a0433f171229ef58393cbfbf0e23ab2b6 some time ago.

No the problem I meant is the other way around. While KDE Defaults to the correct language or the language is switched in KXMLGui, then the Qt translations are still in the System language which in this case would be wrong. So while a Dialog may have German Text that dialog has OK and Cancel Buttons.
Like:

That is a screenshot with 3.2.2 as I had this installed atm but the Qt6 installation of master also has the same issue.

I mean the system configuration of Windows is just strange and messy. I am only noticing this now more because for my latest Test VMs I used VIrtual Box unattended installation, which installs the system according to the Hosts locale and then you can change the language for your user in Windows. And I ended up with this setting here where the preferred languages differ from the Windows UI language. And we are not alone in a confusion, on this system also Paint is in english, and the Microsoft Calculator, but not Powershell or CMD 🙄 But as GetUserPreferredUILanguages should return (and does according to my tests) the display langue chosen in the drop down as Language[0] and the others with lower priority I think the correct behavior here is to be in German.

But in this configuration also Okular from the Microsoft Store is in english:

But nevertheless, which language to chose by default is a bit unrelated, for now I want to concentrate on having a consistent language depending on the Configuration of Kleopatra.

Yes, the function to load the user-configured language on application start is very well hidden in kxmlgui. :-)

The bug you demonstrate in the screenshot is exactly the problem I fixed. Well, okay. I fixed it for the case that the user has configured a language in the application so that LANGUAGE is set by kxmlgui. (The fix worked for kate and kdenlive for example. At least for Qt 5, but while Qt does things a bit differently in Qt 6, the code in ki18n should still work. After all it sets the locale explicitly if LANGUAGE is set.)

The code in ki18n's main.cpp doesn't consider UI languages when loading the Qt translations. It simply uses the name of the system locale. This could explain why your patch only affects the KDE translations but not the Qt translations.