Skip to content

fix: Stale inline localized-string fallback shadows Messages.psd1 on Windows PowerShell 5.1 #185

Description

@tablackburn

Summary

PowerShellBuild.psm1 carries a hand-maintained second copy of the localized strings in an inline
data LocalizedData { ConvertFrom-StringData @'...'@ } block, introduced with the comment
# Load here in case Import-LocalizedData is not available. It has drifted from
PowerShellBuild/en-US/Messages.psd1, and on Windows PowerShell 5.1 with a non-English UI culture
it is the copy consumers actually get.

Evidence

Import-LocalizedData is called with -ErrorAction SilentlyContinue, so a lookup that resolves
nothing leaves the stale inline table bound and says nothing about it. The two supported hosts do
not agree on when that lookup misses.

Probe module with en-US/Messages.psd1 (Source=en-US-file) and de-DE/Messages.psd1
(Source=de-DE-file) next to a script that seeds $LocalizedData with Source=inline-fallback
and then runs the same splat the module uses:

pwsh 7 (PowerShell 7.5)                powershell.exe (5.1.26100.9168)
  en-US -> en-US-file                    en-US -> en-US-file
  de-DE -> de-DE-file                    de-DE -> de-DE-file
  de-AT -> en-US-file                    de-AT -> inline-fallback
  fr-FR -> en-US-file                    fr-FR -> inline-fallback
  ja-JP -> en-US-file                    ja-JP -> inline-fallback

PowerShell 7 has a final en-US fallback (confirmed by hiding the en-US directory, after which
fr-FR also lands on inline-fallback). Windows PowerShell 5.1 has no such fallback: it walks the
culture's own parent chain and stops.

Against the real module on Windows PowerShell 5.1:

en-US: Keys=41 HasModuleLandingPageNotFound=True  requires Pester 6.0.0 or newer.
fr-FR: Keys=25 HasModuleLandingPageNotFound=False requires Pester 5.0.0 or newer.
ja-JP: Keys=25 HasModuleLandingPageNotFound=False requires Pester 5.0.0 or newer.

Sixteen of the forty-one shipped strings are missing, and PesterVersionNotSupported still names
the pre-#182 floor of 5.0.0.

Impact

Missing keys do not throw -- $null -f $arguments returns an empty string rather than raising --
so the failure is silent and worse to diagnose:

  • Write-Warning ($LocalizedData.ModuleLandingPageNotFound -f $path, $locale) in
    Build-PSBuildUpdatableHelp emits a blank WARNING: line.
  • Write-Warning ($LocalizedData.HelpInfoUriRequired -f $Module) does the same.
  • throw $LocalizedData.NoCertificateFound in IB.tasks.ps1 raises ScriptHalted with no
    explanation of what went wrong.
  • Assert ($null -ne $certificate) $LocalizedData.NoCertificateFound in psakeFile.ps1 asserts
    with no message.
  • Test-PSBuildPester reports a floor of 5.0.0 when the real requirement is 6.0.0.

Windows PowerShell 5.1 is a supported host (PowerShellVersion = '5.1',
CompatiblePSEditions = @('Desktop', 'Core')), and non-English Windows installations are common,
so this is reachable rather than theoretical.

en-US/Messages.psd1 itself is shipped correctly -- the root Build task copies the whole source
tree -- so the file is always present; only the lookup misses.

Fix direction

The duplication is the defect. Delete the inline copy and make the lookup deterministic by asking
for en-US by name when the culture-based lookup binds nothing, with -ErrorAction Stop on that
fallback so genuinely missing strings fail at import instead of blanking every message. Add tests
that pin both halves: one source of truth, and a complete string table under a non-English UI
culture on every supported host.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions