GetUserPreferredUILanguages() 从不 returns 两种以上的语言
GetUserPreferredUILanguages() never returns more than two languages
我正在尝试从 C++/Qt 应用程序中检索用户首选语言的完整列表,如用户首选项的 "Region & language" 页面中所配置:
为此,我尝试在最新的 Windows 10 Pro 系统上使用 WinAPI 功能 GetUserPreferredUILanguages()。
但是,函数总是只returns第一个条目(主要Windows显示语言),而"en-US"。如果将英语配置为主要语言,则仅返回 "en-US"。例如,如果我配置了 (German, French, English),则返回 ["de-de", "en-US"],省略法语。如果我在列表中添加更多语言,它们也会被忽略。
我还看了 User Interface Language Management, but to no avail. GetSystemPreferredUILanguages() for example only returns "en-US". GetUILanguageFallbackList() returns ["de-de", "de", "en-US", "en"].
我使用的代码:
// calling GetUserPreferredUILanguages() twice, once to get number of
// languages and required buffer size, then to get the actual data
ULONG numberOfLanguages = 0;
DWORD bufferLength = 0;
const auto result1 = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
&numberOfLanguages,
nullptr,
&bufferLength);
// result1 is true, numberOfLanguages=2
QVector<wchar_t> languagesBuffer(static_cast<int>(bufferLength));
const auto result2 = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
&numberOfLanguages,
languagesBuffer.data(),
&bufferLength);
// result2 is true, languageBuffer contains "de-de", "en-US"
这不是正确使用的功能,还是我误解了 Windows 10 中的语言配置?如何获得首选语言的完整列表?我看到 UWP API 可以完成这项工作,但如果可能的话,我想使用 C API,因为它更容易与手头的 C++ 代码库集成。 (非托管 C++,即)
GlobalizationPreferences.Languages
可用于非托管 C++,因为 GlobalizationPreferences
具有 DualApiPartitionAttribute
。
这是使用 GlobalizationPreferences.Languages
:
的 C++/WinRT 示例
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.System.UserProfile.h>
#include <iostream>
#pragma comment(lib, "windowsapp")
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::System::UserProfile;
int main()
{
winrt::init_apartment();
for (const auto& lang : GlobalizationPreferences::Languages()) {
std::wcout << lang.c_str() << std::endl;
}
}
以及为那些无法迁移到 C++ 17 的人提供的 WRL 示例:
#include <roapi.h>
#include <wrl.h>
#include <Windows.System.UserProfile.h>
#include <iostream>
#include <stdint.h>
#pragma comment(lib, "runtimeobject.lib")
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::System::UserProfile;
int main()
{
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize)) {
std::cerr << "RoInitialize failed" << std::endl;
return 1;
}
ComPtr<IGlobalizationPreferencesStatics> gps;
HRESULT hr = RoGetActivationFactory(
HStringReference(
RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences)
.Get(),
IID_PPV_ARGS(&gps));
if (FAILED(hr)) {
std::cerr << "RoGetActivationFactory failed" << std::endl;
return 1;
}
ComPtr<IVectorView<HSTRING>> langs;
hr = gps->get_Languages(&langs);
if (FAILED(hr)) {
std::cerr << "Could not get Languages" << std::endl;
return 1;
}
uint32_t size;
hr = langs->get_Size(&size);
if (FAILED(hr)) {
std::cerr << "Could not get Size" << std::endl;
return 1;
}
for (uint32_t i = 0; i < size; ++i) {
HString lang;
hr = langs->GetAt(i, lang.GetAddressOf());
if (FAILED(hr)) {
std::cerr << "Could not get Languages[" << i << "]" << std::endl;
continue;
}
std::wcout << lang.GetRawBuffer(nullptr) << std::endl;
}
}
我正在尝试从 C++/Qt 应用程序中检索用户首选语言的完整列表,如用户首选项的 "Region & language" 页面中所配置:
为此,我尝试在最新的 Windows 10 Pro 系统上使用 WinAPI 功能 GetUserPreferredUILanguages()。
但是,函数总是只returns第一个条目(主要Windows显示语言),而"en-US"。如果将英语配置为主要语言,则仅返回 "en-US"。例如,如果我配置了 (German, French, English),则返回 ["de-de", "en-US"],省略法语。如果我在列表中添加更多语言,它们也会被忽略。 我还看了 User Interface Language Management, but to no avail. GetSystemPreferredUILanguages() for example only returns "en-US". GetUILanguageFallbackList() returns ["de-de", "de", "en-US", "en"].
我使用的代码:
// calling GetUserPreferredUILanguages() twice, once to get number of
// languages and required buffer size, then to get the actual data
ULONG numberOfLanguages = 0;
DWORD bufferLength = 0;
const auto result1 = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
&numberOfLanguages,
nullptr,
&bufferLength);
// result1 is true, numberOfLanguages=2
QVector<wchar_t> languagesBuffer(static_cast<int>(bufferLength));
const auto result2 = GetUserPreferredUILanguages(MUI_LANGUAGE_NAME,
&numberOfLanguages,
languagesBuffer.data(),
&bufferLength);
// result2 is true, languageBuffer contains "de-de", "en-US"
这不是正确使用的功能,还是我误解了 Windows 10 中的语言配置?如何获得首选语言的完整列表?我看到 UWP API 可以完成这项工作,但如果可能的话,我想使用 C API,因为它更容易与手头的 C++ 代码库集成。 (非托管 C++,即)
GlobalizationPreferences.Languages
可用于非托管 C++,因为 GlobalizationPreferences
具有 DualApiPartitionAttribute
。
这是使用 GlobalizationPreferences.Languages
:
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.System.UserProfile.h>
#include <iostream>
#pragma comment(lib, "windowsapp")
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::System::UserProfile;
int main()
{
winrt::init_apartment();
for (const auto& lang : GlobalizationPreferences::Languages()) {
std::wcout << lang.c_str() << std::endl;
}
}
以及为那些无法迁移到 C++ 17 的人提供的 WRL 示例:
#include <roapi.h>
#include <wrl.h>
#include <Windows.System.UserProfile.h>
#include <iostream>
#include <stdint.h>
#pragma comment(lib, "runtimeobject.lib")
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::System::UserProfile;
int main()
{
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize)) {
std::cerr << "RoInitialize failed" << std::endl;
return 1;
}
ComPtr<IGlobalizationPreferencesStatics> gps;
HRESULT hr = RoGetActivationFactory(
HStringReference(
RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences)
.Get(),
IID_PPV_ARGS(&gps));
if (FAILED(hr)) {
std::cerr << "RoGetActivationFactory failed" << std::endl;
return 1;
}
ComPtr<IVectorView<HSTRING>> langs;
hr = gps->get_Languages(&langs);
if (FAILED(hr)) {
std::cerr << "Could not get Languages" << std::endl;
return 1;
}
uint32_t size;
hr = langs->get_Size(&size);
if (FAILED(hr)) {
std::cerr << "Could not get Size" << std::endl;
return 1;
}
for (uint32_t i = 0; i < size; ++i) {
HString lang;
hr = langs->GetAt(i, lang.GetAddressOf());
if (FAILED(hr)) {
std::cerr << "Could not get Languages[" << i << "]" << std::endl;
continue;
}
std::wcout << lang.GetRawBuffer(nullptr) << std::endl;
}
}