-
Notifications
You must be signed in to change notification settings - Fork 383
[MRTCore] Add Microsoft.Windows.Globalization.ApplicationLanguages class #4181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
5259292
410c575
7053cb8
3f8a0d7
e3b424e
108def9
a344d8a
b710e14
544211d
acbcd27
b273263
2d1c892
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright (c) Microsoft Corporation and Contributors. | ||
// Licensed under the MIT License. | ||
|
||
#include "pch.h" | ||
#include "ApplicationLanguages.h" | ||
#include "Microsoft.Windows.Globalization.ApplicationLanguages.g.cpp" | ||
|
||
#include <winrt/Windows.Globalization.h> | ||
|
||
#include <AppModel.Identity.h> | ||
|
||
#include "Helper.h" | ||
|
||
namespace winrt::Microsoft::Windows::Globalization::implementation | ||
{ | ||
hstring ApplicationLanguages::m_language; | ||
|
||
winrt::Windows::Foundation::Collections::IVectorView<hstring> ApplicationLanguages::Languages() | ||
{ | ||
return winrt::Windows::Globalization::ApplicationLanguages::Languages(); | ||
} | ||
|
||
winrt::Windows::Foundation::Collections::IVectorView<hstring> ApplicationLanguages::ManifestLanguages() | ||
{ | ||
if (AppModel::Identity::IsPackagedProcess()) | ||
{ | ||
return winrt::Windows::Globalization::ApplicationLanguages::ManifestLanguages(); | ||
} | ||
else | ||
{ | ||
return {}; | ||
} | ||
} | ||
|
||
hstring ApplicationLanguages::PrimaryLanguageOverride() | ||
{ | ||
static wil::srwlock lock; | ||
|
||
auto criticalSection{ lock.lock_shared() }; | ||
return m_language; | ||
} | ||
|
||
void ApplicationLanguages::PrimaryLanguageOverride(hstring const& language) | ||
{ | ||
bool isValidLanguageTag = IsWellFormedLanguageTag(language.c_str()); | ||
|
||
THROW_HR_IF_MSG(E_INVALIDARG, !isValidLanguageTag, "The parameter is incorrect"); | ||
|
||
static wil::srwlock lock; | ||
|
||
auto criticalSection {lock.lock_exclusive()}; | ||
m_language = language; | ||
|
||
if (AppModel::Identity::IsPackagedProcess()) | ||
{ | ||
winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride(language); | ||
stefansjfw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} // namespace winrt::Microsoft::Windows::Globalization::implementation |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright (c) Microsoft Corporation and Contributors. | ||
// Licensed under the MIT License. | ||
|
||
#pragma once | ||
#include "Microsoft.Windows.Globalization.ApplicationLanguages.g.h" | ||
|
||
namespace winrt::Microsoft::Windows::Globalization::implementation | ||
{ | ||
struct ApplicationLanguages | ||
{ | ||
ApplicationLanguages() = delete; | ||
|
||
static winrt::Windows::Foundation::Collections::IVectorView<hstring> Languages(); | ||
static winrt::Windows::Foundation::Collections::IVectorView<hstring> ManifestLanguages(); | ||
static hstring PrimaryLanguageOverride(); | ||
static void PrimaryLanguageOverride(hstring const& language); | ||
|
||
private: | ||
static hstring m_language; | ||
}; | ||
} // namespace winrt::Microsoft::Windows::Globalization::implementation | ||
|
||
namespace winrt::Microsoft::Windows::Globalization::factory_implementation | ||
{ | ||
struct ApplicationLanguages : ApplicationLanguagesT<ApplicationLanguages, implementation::ApplicationLanguages> | ||
{ | ||
}; | ||
} // namespace winrt::Microsoft::Windows::Globalization::factory_implementation |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,3 +86,31 @@ HRESULT GetDefaultPriFile(winrt::hstring& filePath) | |
bool isPackaged = (hr != HRESULT_FROM_WIN32(APPMODEL_ERROR_NO_PACKAGE)); | ||
return GetDefaultPriFileForCurentModule(isPackaged, filePath); | ||
} | ||
|
||
bool IsWellFormedLanguageTag(const wchar_t* languageTag) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done. I don't have this header, so I reused the logic to load the DLL manually as in platform.h/.cpp. Tested. Works as expected. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the header should be in SDK. The LoadLibrary code was written before it's added into SDK. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. according to the docs it should be there since Windows 10 Build 17763, but I don't have it on machine (OS version 10.0.22631 Build 22631), VS 22 installed with multiple SDK versions. I double-checked on another machine with the same software versions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I double-checked again, the header is present in SDK v10.0.20348.0 (and later), even though docs says it should be there before There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is bumping WindowsTargetPlatformVersion to 10.0.20348.0 for this specific project ok to do ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pushed the change (including WindowsTargetPlatformVersion bump). I'll revert if it's not ok |
||
{ | ||
// Implementation taken from Platform.h, without accepting semi-colon, as it must be a single language tag | ||
if (languageTag == nullptr || *languageTag == L'\0') | ||
{ | ||
return FALSE; | ||
} | ||
|
||
BOOLEAN ok = TRUE; | ||
PCWSTR test = languageTag; | ||
|
||
while (ok && (*test != L'\0')) | ||
{ | ||
// we accept letters, numbers and dash | ||
if (((*test >= L'0') && (*test <= L'9')) || ((*test >= L'a') && (*test <= L'z')) || ((*test >= L'A') && (*test <= L'Z')) || | ||
(*test == L'-')) | ||
{ | ||
test++; | ||
} | ||
else | ||
{ | ||
ok = FALSE; | ||
} | ||
} | ||
|
||
return ok && ((test - languageTag) >= 2); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,10 @@ | |
|
||
const wchar_t c_languageQualifierName[] = L"Language"; | ||
|
||
#include "ApplicationLanguages.h" | ||
|
||
using namespace winrt::Microsoft::Windows::Globalization; | ||
|
||
namespace winrt::Microsoft::Windows::ApplicationModel::Resources::implementation | ||
{ | ||
void ResourceContext::InitializeQualifierNames() | ||
|
@@ -97,6 +101,10 @@ void ResourceContext::Apply() | |
winrt::check_hresult(MrmSetQualifier(m_resourceContext, eachValue.Key().c_str(), eachValue.Value().c_str())); | ||
} | ||
} | ||
if (!ApplicationLanguages::PrimaryLanguageOverride().empty()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With W.G.PrimaryLanguageOverride set, newly created ResourceContext takes PrimaryLanguageOverride into account, i.e. does not override language QualifierValue to default language. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. e.g. if default language is "en-US", PrimaryLanguageOverride is "de-DE", and ResourceContext["Lanauge"]="fr-FR", what's the language that will take effect? I'd think "fr-FR" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. according to this logic, no, PrimaryLanguageOverride should take precedence over ResourceContext["Language"]. GetLangugageContext returns Windows::Globalization::ApplicationLanguages::Languages() which is affected if W.G.PrimaryLanguageOverride is set. This behavior remains the same with this change There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think in that logic ResourceContext["Language"] still takes precedence. It would be strange to the caller that an explicit request is not honored There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Got it now. You're right. Fixed by latest change. Now explicit set of context Language is not overridden by PrimaryLanguageOverride. I tested with this WinAppSDK sample. Default language is PrimaryLanguageOverride - de-DE, but fetching resources with m_overrideResourceContext passed is fetching it-IT resources: |
||
{ | ||
winrt::check_hresult(MrmSetQualifier(m_resourceContext, c_languageQualifierName, ApplicationLanguages::PrimaryLanguageOverride().c_str())); | ||
} | ||
} | ||
|
||
hstring ResourceContext::GetLangugageContext() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have to use the same lock for reading and writing. Otherwise the setter could take an exclusive lock, but another thread could still read the data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦 fixed