Skip to content

Add persistent output locale override setting - #6310

Open
Kaleb Luedtke (Trenly) wants to merge 17 commits into
microsoft:masterfrom
Trenly:trenly/fix-422-output-locale-override
Open

Add persistent output locale override setting#6310
Kaleb Luedtke (Trenly) wants to merge 17 commits into
microsoft:masterfrom
Trenly:trenly/fix-422-output-locale-override

Conversation

@Trenly

@Trenly Kaleb Luedtke (Trenly) commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

📖 Description

Add a persistent output.locale user setting that allows overriding winget interface string resolution by BCP47 tag.

Current implementation details:

  • Reads .output.locale at CLI startup and applies the override only when the setting is non-empty.
  • Applies the override through Resource::SetLanguageOverride, which sets the MRT Language qualifier for winget resource loading.
  • Treats override failures as non-fatal (logs warning and continues without the override).
  • Uses wil::srwlock in the shared resource loader for synchronized read/write access when resolving strings and updating locale override.
  • Does not apply this setting in server initialization.

This PR also updates settings schema/documentation and local package resource fallback handling for localized winget.resw files.

🔗 References

Resolves #422

🤖 Copilot Assistance

This PR includes changes authored with GitHub Copilot assistance.

🔍 Validation

  • Added/updated unit tests for OutputLocale setting parsing/normalization behavior.
  • Added E2E coverage verifying help output changes when output.locale changes.

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task
Microsoft Reviewers: Open in CodeFlow

* Add output.locale setting and schema support
* Apply runtime language qualifier override for resource resolution
* Include localized resw fallbacks in dev package and update docs/release notes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Trenly
Kaleb Luedtke (Trenly) changed the base branch from release-v1.29 to master June 21, 2026 04:51
@microsoft-github-policy-service microsoft-github-policy-service Bot added Issue-Feature This is a feature request for the Windows Package Manager client. Area-Settings Issue related to WinGet Settings labels Jun 21, 2026
Comment thread src/AppInstallerCLIPackage/AppInstallerCLIPackage.wapproj
@Trenly
Kaleb Luedtke (Trenly) marked this pull request as ready for review June 21, 2026 05:10
@Trenly
Kaleb Luedtke (Trenly) requested a review from a team as a code owner June 21, 2026 05:10
Comment thread src/AppInstallerCLICore/Core.cpp Outdated
Comment thread src/AppInstallerCLICore/Core.cpp Outdated
Comment thread src/AppInstallerCLICore/Core.cpp Outdated
Comment thread src/AppInstallerCommonCore/UserSettings.cpp Outdated
Comment thread src/AppInstallerCLITests/UserSettings.cpp
Comment thread doc/windows/package-manager/winget/settings.md
Comment thread src/AppInstallerCLICore/Core.cpp Outdated
Comment thread src/AppInstallerCommonCore/Public/winget/UserSettings.h Outdated
Comment thread src/AppInstallerCLICore/Core.cpp Outdated
@microsoft-github-policy-service microsoft-github-policy-service Bot added Needs-Author-Feedback Issue needs attention from issue or PR author Needs-Attention Issue needs attention from Microsoft and removed Needs-Author-Feedback Issue needs attention from issue or PR author labels Jun 30, 2026

@florelis Flor Chacón (florelis) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, but I'd want to hold off on merging until we have a plan for what to do with App Installer.

Comment thread src/AppInstallerCommonCore/UserSettings.cpp Outdated
@florelis

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@Trenly

This comment was marked as outdated.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new persisted output.locale user setting that lets WinGet override the UI/output language (via a supported BCP47 tag), and wires the setting into startup initialization so localized resources resolve accordingly. It also updates schema/docs/release notes and adjusts packaging to pick up localized winget.resw files during local builds.

Changes:

  • Introduces Setting::OutputLocale (settings mapping + validation/normalization against supported locale tags).
  • Applies the locale override at CLI startup via ApplicationLanguages::PrimaryLanguageOverride.
  • Updates the settings schema + documentation + release notes, and adds packaging fallback to include localized winget.resw from Localization\Resources\<locale> when Shared\Strings\<locale> is absent.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/AppInstallerCommonCore/UserSettings.cpp Adds supported-locale normalization and validation for the new output.locale setting.
src/AppInstallerCommonCore/Public/winget/UserSettings.h Adds the OutputLocale setting enum value and JSON mapping to .output.locale.
src/AppInstallerCLITests/UserSettings.cpp Adds unit tests covering default/valid/case-insensitive/invalid locale values.
src/AppInstallerCLIPackage/AppInstallerCLIPackage.wapproj Adds build-time fallback PRIResource includes from Localization\\Resources\\<locale> for local builds.
src/AppInstallerCLICore/Core.cpp Applies the persisted output locale override during startup initialization.
schemas/JSON/settings/settings.schema.0.2.json Adds output.locale to the public settings schema with supported enum values.
doc/windows/package-manager/winget/settings.md Documents the new output.locale setting for end users.
doc/Settings.md Documents the new output.locale setting in the repo’s settings documentation.
doc/ReleaseNotes.md Adds a release note entry for the new output locale override feature.

Comment thread src/AppInstallerCLICore/Core.cpp Outdated
@florelis

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@florelis

Copy link
Copy Markdown
Member

Looks like we will need to reset the override in App Installer. Internal PR number for that: 16173490
I won't merge this until that other change is in place.

@florelis

Copy link
Copy Markdown
Member

Question from internal discussion:
Instead of overriding the primary language like this, would it be possible to just add the locale qualifier when creating the resource loader? That would avoid setting the locale package-wide, and we wouldn't need to make any changes to App Installer.


bool SetLanguageOverride(std::string_view localeTag)
{
return Loader::Instance().SetLanguageOverride(Utility::ConvertToUTF16(localeTag));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: Assuming this is done before any localized strings are fetched, this is going to create a loader with default options, and then immediately overwrite it with a new one that uses the locale. We could make it so that we only needed to create it once, but that's probably too small a gain to care.

@florelis

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@Trenly

Copy link
Copy Markdown
Contributor Author

Grrr, pesky build failures

@Trenly

Copy link
Copy Markdown
Contributor Author

@florelis - I've merged the latest changes from master to see if that resolves the ADO build issue despite it building locally without them. I've verified it builds locally after the merge:

image

@florelis

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

ApplyOutputLocaleOverride() unconditionally triggered Loader::Instance()
at startup for every command, including dscv3 --manifest which runs
winget.exe unpackaged during the WinGetGenerateDSCv3Manifests build step.

The Loader() constructor had been refactored to call CreateLoader({}),
which calls ResourceContext::ResetGlobalQualifierValues() before
ResourceLoader(). This broke the safety guard that the original code
relied on: when unpackaged and resource.pri is not found, ResourceLoader()
throws a catchable hresult_error, preventing execution from reaching
ResourceLoader::GetForViewIndependentUse which fast-fails with an
uncatchable crash (0xC0000409 STATUS_STACK_BUFFER_OVERRUN) when not
under a debugger.

Two fixes:
- Restore the original constructor initialization path (without calling
  CreateLoader) so the ResourceLoader() probe is not interfered with
- Guard ApplyOutputLocaleOverride to skip loader initialization entirely
  when no locale override is configured (the common case)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Trenly

Kaleb Luedtke (Trenly) commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Root Cause Analysis

Note

This comment was authored by GitHub Copilot.

Root cause: ApplyOutputLocaleOverride() unconditionally accessed Loader::Instance() at startup for every command. The WinGetGenerateDSCv3Manifests build step runs winget.exe dscv3 --manifest as an unpackaged process (before MSIX packaging), and the refactored Loader() constructor now calls CreateLoader({}) which calls ResourceContext::ResetGlobalQualifierValues() before the ResourceLoader() probe.

The original code relied on ResourceLoader() throwing a catchable hresult_error when resource.pri is not found (unpackaged context) — this prevented execution from ever reaching ResourceLoader::GetForViewIndependentUse, which fast-fails with an uncatchable crash (0xC0000409) when no debugger is attached. Calling ResetGlobalQualifierValues first changed the WinRT resource state and broke this safety guard.

Fix

Two changes applied in commit 25c246a:

  1. Resources.cpp: Restored the original constructor initialization path — no ResetGlobalQualifierValues call, preserving the ResourceLoader() probe guard
  2. Core.cpp: Guard ApplyOutputLocaleOverride() to return early when the locale setting is empty, avoiding Loader::Instance() initialization at startup for commands that don't need UI output (like dscv3 --manifest)

Comment thread src/AppInstallerSharedLib/Resources.cpp Outdated
return {};
}

if (!AppInstaller::Resource::SetLanguageOverride(localeTag))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can throw; do we think it important enough to respect the target locale that we should terminate the winget.exe process if we cannot?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Right now the throw should be caught internally to the function and result in the false return, walking through the warning path here. My thought was that this should be best-effort and not breaking. This would most closely match the behavior today where if the Locale coming from the OS doesn't map to an avaliable resource file it falls back to whatever the resource loader deems is the best fit.

I'm not opposed to making it a hard failure, but without knowing how often it would or could throw, just makes me a bit uneasy. Is this a decision that needs to be made now? Could we do something in the future like adding a telemetry event sampling language overrides as a what-if to better understand the potential impact of making it a terminating failure?

Kaleb Luedtke (Trenly) and others added 2 commits August 5, 2026 21:37
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Settings Issue related to WinGet Settings Issue-Feature This is a feature request for the Windows Package Manager client. Needs-Attention Issue needs attention from Microsoft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow the user to override winget's locale setting

4 participants