In the "language settings" control panel in Windows 10 (and older versions -- this appears to have been introduced in Win8?) there is a list of "Preferred Languages". What is the correct way to programmatically obtain that list?
I can see it stored in the registry at HKEY_CURRENT_USER\Control Panel\International\User Profile\Languages
, but I assume that it is not intended that this be read directly.
I found an API GetUserPreferredUILanguages
that sounds like the right thing -- but it returns the wrong results.
Specifically, in the control panel and registry key I currently have the list en-NZ en-US it-IT
, but the API returns en-GB
en-US
. I have no idea where it's getting that from. (Or why Italian is missing.)
The GetUserDefaultLocaleName
API does correctly return en-NZ
, but it also seems to be getting that from somewhere else -- when I rearrange the language list in the control panel, the registry updates but the API return value doesn't change.
I do want the full list of languages, not just a single answer. (Also, out of curiosity, which control panel is the API getting its answers from?)
You can use undocumented GetUserLanguages
API from bcp47langs.dll
that is available since Windows 8.
#include <hstring.h>
#include <winstring.h>
typedef int (WINAPI* GetUserLanguagesFn)(char Delimiter, HSTRING* UserLanguages);
int main()
{
auto h = LoadLibrary(L"bcp47langs.dll");
auto fn = (GetUserLanguagesFn)GetProcAddress(h, "GetUserLanguages");
HSTRING str;
fn(',', &str);
WindowsDeleteString(str);
return 0;
}
public static void Main(string[] args)
{
GetUserLanguages(',', out var langs);
Console.WriteLine(langs);
}
[DllImport("bcp47langs.dll", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetUserLanguages(char Delimiter, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(HStringMarshaler))] out string UserLanguages);
PS: there is also GetUserLanguageInputMethods
exists that can get list of input methods for a language in:
[DllImport("bcp47langs.dll", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetUserLanguageInputMethods(string Language, char Delimiter, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(HStringMarshaler))] out string InputMethods);
The string format of the keyboard layout:
<LangID>:<KLID>
The string format of the text service is:
<LangID>:{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
Posing on behalf of @Simon Mourier.