Skip to content
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

[MRTCore] Add Microsoft.Windows.Globalization.ApplicationLanguages class #4181

Closed
1 change: 1 addition & 0 deletions BuildAll.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ Try {
Copy-Item -path "BuildOutput\$configurationForMrtAndAnyCPU\$platformToRun\Microsoft.Windows.ApplicationModel.Resources.Projection\Microsoft.Windows.ApplicationModel.Resources.Projection.dll" -destination "$BasePath\lib\net6.0-windows10.0.17763.0" -force
Copy-Item -path "BuildOutput\$configurationForMrtAndAnyCPU\$platformToRun\Microsoft.Windows.ApplicationModel.Resources.Projection\Microsoft.Windows.ApplicationModel.Resources.Projection.pdb" -destination "$BasePath\lib\net6.0-windows10.0.17763.0" -force
Copy-Item -path "BuildOutput\$configurationForMrtAndAnyCPU\$platformToRun\Microsoft.Windows.ApplicationModel.Resources\Microsoft.Windows.ApplicationModel.Resources.winmd" -destination "$BasePath\lib\uap10.0" -force
Copy-Item -path "BuildOutput\$configurationForMrtAndAnyCPU\$platformToRun\Microsoft.Windows.ApplicationModel.Resources\Microsoft.Windows.Globalization.winmd" -destination "$BasePath\lib\uap10.0" -force
}
}

Expand Down
1 change: 1 addition & 0 deletions build/NuSpecs/AppxManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.Resources.ResourceCandidate" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.Resources.ResourceLoader" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.ApplicationModel.Resources.ResourceManager" ThreadingModel="both" />
<ActivatableClass ActivatableClassId="Microsoft.Windows.Globalization.ApplicationLanguages" ThreadingModel="both" />
</InProcessServer>
</Extension>
<Extension Category="windows.activatableClass.inProcessServer">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows10.0.17763.0</TargetFramework>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
Expand All @@ -21,7 +21,7 @@
</ItemGroup>

<PropertyGroup>
<CSWinRTIncludes>Microsoft.Windows.ApplicationModel.Resources</CSWinRTIncludes>
<CSWinRTIncludes>Microsoft.Windows.Globalization;Microsoft.Windows.ApplicationModel.Resources</CSWinRTIncludes>
<CSWinRTWindowsMetadata>10.0.17763.0</CSWinRTWindowsMetadata>
<NoWarn>MSB3271</NoWarn>
</PropertyGroup>
Expand All @@ -30,10 +30,11 @@
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>pdbonly</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
</PropertyGroup>

<ItemGroup>
<CsWinRTInputs Include="$(OutDir)/**/*.winmd" />
<CsWinRTInputs Include="$(BaseOutputPath)/Microsoft.Windows.ApplicationModel.Resources/Microsoft.Windows.Globalization.winmd" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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 <bcp47mrm.h>
#include <winrt/Windows.Globalization.h>

#include <AppModel.Identity.h>

namespace winrt::Microsoft::Windows::Globalization::implementation
{
hstring ApplicationLanguages::m_language;
wil::srwlock ApplicationLanguages::m_lock;


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()
{
auto criticalSection{ m_lock.lock_shared() };
return m_language;
}

void ApplicationLanguages::PrimaryLanguageOverride(hstring const& language)
{
bool isValidLanguageTag = IsWellFormedTag(language.c_str());

THROW_HR_IF_MSG(E_INVALIDARG, !isValidLanguageTag, "The parameter is incorrect");

auto criticalSection {m_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,29 @@
// 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;
static wil::srwlock m_lock;
};
} // 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
Expand Up @@ -114,3 +114,18 @@ namespace Microsoft.Windows.ApplicationModel.Resources
static String Theme { get; };
}
} // namespace Microsoft.Windows.ApplicationModel.Resources

namespace Microsoft.Windows.Globalization
{
[contractversion(1)]
apicontract MrtCoreContract{};

[contract(MrtCoreContract, 2)]
runtimeclass ApplicationLanguages
stefansjfw marked this conversation as resolved.
Show resolved Hide resolved
{
static IVectorView<String> Languages { get; };
static IVectorView<String> ManifestLanguages { get; };
static String PrimaryLanguageOverride;
stefansjfw marked this conversation as resolved.
Show resolved Hide resolved
stefansjfw marked this conversation as resolved.
Show resolved Hide resolved
}

} // namespace Microsoft.Windows.Globalization
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.20348.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
<!-- Need to add this otherwise the ADO build won't copy mrm.dll to output directory, and eventually the file will miss in ManagedTest.build.appxrecipe and make
the tests fail to run in ADO pipeline -->
Expand Down Expand Up @@ -90,12 +90,13 @@
</DisableSpecificWarnings>
<PreprocessorDefinitions>_WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalIncludeDirectories>$(RepoRoot)\dev\Common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<ModuleDefinitionFile>Microsoft.Windows.ApplicationModel.Resources.def</ModuleDefinitionFile>
<AdditionalDependencies>$(OutDir)..\mrm\MRM.lib;onecoreuap.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(OutDir)..\mrm\MRM.lib;onecoreuap.lib;bcp47mrm.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
Expand All @@ -109,6 +110,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ApplicationLanguages.h" />
<ClInclude Include="Helper.h" />
<ClInclude Include="KnownResourceQualifierName.h" />
<ClInclude Include="pch.h" />
Expand All @@ -120,6 +122,7 @@
<ClInclude Include="ResourceNotFoundEventArgs.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ApplicationLanguages.cpp" />
<ClCompile Include="Helper.cpp" />
<ClCompile Include="KnownResourceQualifierName.cpp" />
<ClCompile Include="pch.cpp">
Expand All @@ -140,7 +143,7 @@
<None Include="Microsoft.Windows.ApplicationModel.Resources.def" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Microsoft.Windows.ApplicationModel.Resources.rc">
<ResourceCompile Include="Microsoft.Windows.ApplicationModel.Resources.rc">
<AdditionalIncludeDirectories>$(RepoRoot);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemGroup>
Expand Down Expand Up @@ -171,6 +174,7 @@
<Import Project="$(NugetPackageDirectory)\Microsoft.SourceLink.Common.$(MicrosoftSourceLinkCommonVersion)\build\Microsoft.SourceLink.Common.targets" Condition="Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.Common.$(MicrosoftSourceLinkCommonVersion)\build\Microsoft.SourceLink.Common.targets')" />
<Import Project="$(NugetPackageDirectory)\Microsoft.Build.Tasks.Git.$(MicrosoftBuildTasksGitVersion)\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('$(NugetPackageDirectory)\Microsoft.Build.Tasks.Git.$(MicrosoftBuildTasksGitVersion)\build\Microsoft.Build.Tasks.Git.targets')" />
<Import Project="$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets')" />
<Import Project="$(NugetPackageDirectory)\Microsoft.Windows.ImplementationLibrary.$(MicrosoftWindowsImplementationLibraryVersion)\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('$(NugetPackageDirectory)\Microsoft.Windows.ImplementationLibrary.$(MicrosoftWindowsImplementationLibraryVersion)\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
Expand All @@ -185,5 +189,6 @@
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.Build.Tasks.Git.$(MicrosoftBuildTasksGitVersion)\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.Build.Tasks.Git.$(MicrosoftBuildTasksGitVersion)\build\Microsoft.Build.Tasks.Git.targets'))" />
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets'))" />
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.Windows.ImplementationLibrary.$(MicrosoftWindowsImplementationLibraryVersion)\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.Windows.ImplementationLibrary.$(MicrosoftWindowsImplementationLibraryVersion)\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
<ClCompile Include="KnownResourceQualifierName.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ApplicationLanguages.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
Expand Down Expand Up @@ -58,6 +61,9 @@
<ClInclude Include="KnownResourceQualifierName.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ApplicationLanguages.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="Microsoft.Windows.ApplicationModel.Resources.idl" />
Expand All @@ -75,4 +81,7 @@
<UniqueIdentifier>{54696afe-f42a-494a-bc24-3fd0d4192122}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Microsoft.Windows.ApplicationModel.Resources.rc" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PrimaryLanguageOverride

explicit language context should trump PrimaryLanguageOverride

Copy link
Contributor Author

@stefansjfw stefansjfw Jun 26, 2024

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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"

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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

Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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:

image

{
winrt::check_hresult(MrmSetQualifier(m_resourceContext, c_languageQualifierName, ApplicationLanguages::PrimaryLanguageOverride().c_str()));
}
}

hstring ResourceContext::GetLangugageContext()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
<package id="Microsoft.SourceLink.Common" version="1.1.1" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.SourceLink.GitHub" version="1.1.1" targetFramework="native" developmentDependency="true" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.230706.1" targetFramework="native" />
</packages>
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220914.1" targetFramework="native" />
</packages>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <winrt/Windows.Foundation.Collections.h>
#include "..\..\core\src\MRM.h"

#include <wil/result_macros.h>
#include <wil/resource.h>

struct StringResourceFreer
{
void operator()(wchar_t* resource) { MrmFreeResource(resource); }
Expand Down
Loading