From 7d8f7eb42994829e9f6f7a9d1d2a572b4b13e4ef Mon Sep 17 00:00:00 2001 From: "Dustin L. Howett" Date: Fri, 14 Mar 2025 17:03:26 -0500 Subject: [PATCH] Add support for language override to unpackaged/portable builds (#18684) It turns out that we *can* support language overrides--fairly easily, in fact!--by simply changing the default Language qualifier. I elected not to change how packaged language override works until we are certain this works properly everywhere. Consider it a healthy distrust of the Windows App Platform. Closes #18419 Closes #18336 Closes #17619 --- src/cascadia/TerminalApp/AppLogic.cpp | 10 ++++-- src/cascadia/TerminalApp/pch.h | 1 + .../TerminalSettingsEditor/Launch.xaml | 3 +- .../LaunchViewModel.cpp | 33 +++++++------------ .../TerminalSettingsEditor/LaunchViewModel.h | 1 - .../LaunchViewModel.idl | 1 - 6 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index b892c10cb5..b7e0eae91a 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -331,8 +331,16 @@ namespace winrt::TerminalApp::implementation void AppLogic::_ApplyLanguageSettingChange() noexcept try { + const auto language = _settings.GlobalSettings().Language(); + if (!IsPackaged()) { + if (!language.empty()) + { + // We cannot use the packaged app API, PrimaryLanguageOverride, but we *can* tell the resource loader + // to set the Language for all loaded resources to the user's preferred language. + winrt::Windows::ApplicationModel::Resources::Core::ResourceContext::SetGlobalQualifierValue(L"Language", language); + } return; } @@ -340,8 +348,6 @@ namespace winrt::TerminalApp::implementation // NOTE: PrimaryLanguageOverride throws if this instance is unpackaged. const auto primaryLanguageOverride = ApplicationLanguages::PrimaryLanguageOverride(); - const auto language = _settings.GlobalSettings().Language(); - if (primaryLanguageOverride != language) { ApplicationLanguages::PrimaryLanguageOverride(language); diff --git a/src/cascadia/TerminalApp/pch.h b/src/cascadia/TerminalApp/pch.h index 394990ee34..85b7090a93 100644 --- a/src/cascadia/TerminalApp/pch.h +++ b/src/cascadia/TerminalApp/pch.h @@ -27,6 +27,7 @@ #include #include +#include #include #include #include diff --git a/src/cascadia/TerminalSettingsEditor/Launch.xaml b/src/cascadia/TerminalSettingsEditor/Launch.xaml index 8aeca2f92b..44feee7016 100644 --- a/src/cascadia/TerminalSettingsEditor/Launch.xaml +++ b/src/cascadia/TerminalSettingsEditor/Launch.xaml @@ -140,8 +140,7 @@ - + diff --git a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.cpp b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.cpp index 440f43211a..cf99cadb9a 100644 --- a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.cpp +++ b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.cpp @@ -82,16 +82,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return language.NativeName(); } - // Returns whether the language selector is available/shown. - // - // winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride() - // doesn't work for unpackaged applications. The corresponding code in TerminalApp is disabled. - // It would be confusing for our users if we presented a dysfunctional language selector. - bool LaunchViewModel::LanguageSelectorAvailable() - { - return IsPackaged(); - } - // Returns the list of languages the user may override the application language with. // The returned list are BCP 47 language tags like {"und", "en-US", "de-DE", "es-ES", ...}. // "und" is short for "undefined" and is synonymous for "Use system language" in this code. @@ -102,12 +92,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _languageList; } - if (!LanguageSelectorAvailable()) - { - _languageList = {}; - return _languageList; - } - // In order to return the language list this code does the following: // [1] Get all possible languages we want to allow the user to choose. // We have to acquire languages from multiple sources, creating duplicates. See below at [1]. @@ -179,19 +163,24 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation return _currentLanguage; } - if (!LanguageSelectorAvailable()) + winrt::hstring currentLanguage; + if (IsPackaged()) { - _currentLanguage = {}; - return _currentLanguage; + // NOTE: PrimaryLanguageOverride throws if this instance is unpackaged. + currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride(); + } + else + { + if (_Settings.GlobalSettings().HasLanguage()) + { + currentLanguage = _Settings.GlobalSettings().Language(); + } } - // NOTE: PrimaryLanguageOverride throws if this instance is unpackaged. - auto currentLanguage = winrt::Windows::Globalization::ApplicationLanguages::PrimaryLanguageOverride(); if (currentLanguage.empty()) { currentLanguage = systemLanguageTag; } - _currentLanguage = winrt::box_value(currentLanguage); return _currentLanguage; } diff --git a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.h b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.h index d96046524f..98851b74dc 100644 --- a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.h +++ b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.h @@ -20,7 +20,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // "Deutsch (Deutschland)". This works independently of the user's locale. static winrt::hstring LanguageDisplayConverter(const winrt::hstring& tag); - bool LanguageSelectorAvailable(); winrt::Windows::Foundation::Collections::IObservableVector LanguageList(); winrt::Windows::Foundation::IInspectable CurrentLanguage(); void CurrentLanguage(const winrt::Windows::Foundation::IInspectable& tag); diff --git a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.idl b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.idl index 3781c24b87..fe39cbccb1 100644 --- a/src/cascadia/TerminalSettingsEditor/LaunchViewModel.idl +++ b/src/cascadia/TerminalSettingsEditor/LaunchViewModel.idl @@ -10,7 +10,6 @@ namespace Microsoft.Terminal.Settings.Editor runtimeclass LaunchViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged { static String LanguageDisplayConverter(String tag); - Boolean LanguageSelectorAvailable { get; }; Windows.Foundation.Collections.IObservableVector LanguageList { get; }; IInspectable CurrentLanguage;