Skip to content

Commit f8c860b

Browse files
committed
✨ [feat] Add localization-mode selection, on-demand cache validation docs, localized cache-summary rendering, module/help bumps, and tooling updates
- ✨ [feat] Runtime localization mode & env parsing - ✨ ColorScripts-Enhanced.psm1: introduce $script:LocalizationMode and parse COLOR_SCRIPTS_ENHANCED_LOCALIZATION_MODE (supports 'auto', 'full', 'embedded'); honor legacy toggles COLOR_SCRIPTS_ENHANCED_FORCE_LOCALIZATION and COLOR_SCRIPTS_ENHANCED_PREFER_EMBEDDED_MESSAGES. - ✨ ColorScripts-Enhanced.psm1: pass -UseDefaultCandidates to Initialize-ColorScriptsLocalization to enable the new fallback behavior when importing localization resources. - ✨ [feat] Embedded-defaults preference & PSD1 probing - ✨ Private/Initialize-ColorScriptsLocalization.ps1: add -UseDefaultCandidates switch and $useDefaultCandidatesFlag; compute preferredCulture from CurrentUICulture and implement preferEmbeddedDefaults logic for 'Embedded' and 'Auto'+UseDefaultCandidates flows. - ✨ Private/Initialize-ColorScriptsLocalization.ps1: probe candidatePaths for Messages.psd1 (preferred culture chain + fallback en-US/en) and, when no localized resources exist and embedded defaults are preferred, set $script:Messages to the embedded defaults and populate LocalizationDetails.Source = 'EmbeddedDefaults' (with trace output). - 🛠️ [fix] Localize and ANSI-color cache summaries - 🛠️ Public/New-ColorScriptCache.ps1 & Public/Clear-ColorScriptCache.ps1: read format strings from $script:Messages.CacheBuildSummaryFormat and CacheClearSummaryFormat (with sane fallbacks), format summary values, build an ANSI-colored summary segment via New-ColorScriptAnsiText (-Color 'Cyan') and pass that segment to Write-ColorScriptInformation for consistent, localizable output. - 📝 [docs] Document -ValidateCache and localization modes - 📝 README.md, docs/Development.md, docs/MODULE_SUMMARY.md: add usage and guidance for forcing cache validation and for the new localization modes; recommend COLOR_SCRIPTS_ENHANCED_LOCALIZATION_MODE over legacy toggles. - 📝 en-US/Show-ColorScript.md & en-US help XML: add -ValidateCache parameter docs and guidance to force metadata validation before rendering; show examples and environment-variable usage (COLOR_SCRIPTS_ENHANCED_VALIDATE_CACHE). - 🧹 [chore] Add cache-summary message keys to localized resources - 🧹 en-US + localized Messages.psd1 (de, es, fr, it, ja, nl, pt, ru, zh-CN): add CacheBuildSummaryFormat and CacheClearSummaryFormat entries so cache summaries can be localized/overridden via PSD1 files. - 🔧 [build] Bump module manifest and localized help stamps; regenerate release artifacts - 🔧 ColorScripts-Enhanced.psd1: bump ModuleVersion => '2025.11.06.0250' and update Generated on stamp. - 🔧 localized HelpInfo.xml files (en-US, de, es, fr, it, ja, nl, pt, ru, zh-CN): synchronize UICultureVersion => '2025.11.06.0250'. - 🔧 dist/LatestReleaseNotes.md & dist/PowerShellGalleryReleaseNotes.md: regenerate release headers/content to reflect the changes. - 🔧 [build] Formatting/tooling: add PowerShell Prettier plugin - 🔧 .prettierrc: enable "prettier-plugin-powershell" in the plugin list. - 🔧 package.json & package-lock.json: bump prettier-plugin-powershell to ^1.0.5 and update lockfile metadata. - 🧪 [test] Align tests with signature changes - 🧪 Tests/ColorScripts-Enhanced.ModuleImportCoverage.Tests.ps1: update Initialize-ColorScriptsLocalization stubs to accept [switch]$UseDefaultCandidates and null-assign it to keep test stubs compatible with the new signature. - 🧹 [chore] Minor wiring & consistency - 🧹 Ensure module import uses the new -UseDefaultCandidates flag so the embedded-defaults preference path is exercised during import initialization. Signed-off-by: Nick2bad4u <[email protected]>
1 parent 4deea4a commit f8c860b

39 files changed

+353
-405
lines changed

.prettierrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
"prettier-plugin-interpolated-html-tags",
128128
"prettier-plugin-multiline-arrays",
129129
"prettier-plugin-jsdoc",
130+
"prettier-plugin-powershell",
130131
"prettier-plugin-merge"
131132
],
132133
"printWidth": 80,

ColorScripts-Enhanced/ColorScripts-Enhanced.psd1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
#
44
# Generated by: Nick2bad4u
55
#
6-
# Generated on: 11/5/2025
6+
# Generated on: 11/6/2025
77
#
88

99
@{
1010
# Script module or binary module file associated with this manifest.
1111
RootModule = 'ColorScripts-Enhanced.psm1'
1212

1313
# Version number of this module.
14-
ModuleVersion = '2025.11.05.2125'
14+
ModuleVersion = '2025.11.06.0250'
1515

1616
# Supported PSEditions
1717
CompatiblePSEditions = @('Desktop', 'Core')
@@ -211,7 +211,7 @@ PERFECT FOR
211211

212212
# ReleaseNotes of this module
213213
ReleaseNotes = @'
214-
Version 2025.11.05.2125:
214+
Version 2025.11.06.0250:
215215
- Enhanced caching system with OS-wide cache in AppData
216216
- 6-19x performance improvement
217217
- Cache stored in centralized location

ColorScripts-Enhanced/ColorScripts-Enhanced.psm1

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,23 @@ $cultureFallback += 'en-US'
213213
$cultureFallback += 'en'
214214
$cultureFallback = $cultureFallback | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique
215215

216+
$script:LocalizationMode = 'Auto'
217+
$localizationModeEnv = $env:COLOR_SCRIPTS_ENHANCED_LOCALIZATION_MODE
218+
if (-not [string]::IsNullOrWhiteSpace($localizationModeEnv)) {
219+
switch -Regex ($localizationModeEnv.Trim()) {
220+
'^(?i)(embedded|defaults?)$' { $script:LocalizationMode = 'Embedded'; break }
221+
'^(?i)(full|files?|load|disk)$' { $script:LocalizationMode = 'Full'; break }
222+
'^(?i)(auto)$' { $script:LocalizationMode = 'Auto'; break }
223+
default { $script:LocalizationMode = 'Auto' }
224+
}
225+
}
226+
elseif ($env:COLOR_SCRIPTS_ENHANCED_FORCE_LOCALIZATION -match '^(?i)(1|true|yes|full)$') {
227+
$script:LocalizationMode = 'Full'
228+
}
229+
elseif ($env:COLOR_SCRIPTS_ENHANCED_PREFER_EMBEDDED_MESSAGES -match '^(?i)(1|true|yes|embedded)$') {
230+
$script:LocalizationMode = 'Embedded'
231+
}
232+
216233
$script:EmbeddedDefaultMessages = ConvertFrom-StringData @'
217234
# ColorScripts-Enhanced Localized Messages
218235
# English (en-US) - Default Language
@@ -267,6 +284,8 @@ StatusSkippedUpToDate = Skipped (up-to-date)
267284
StatusSkippedByUser = Skipped by user
268285
StatusFailed = Failed
269286
StatusUpToDateSkipped = Up-to-date (skipped)
287+
CacheBuildSummaryFormat = Cache build summary: Processed {0}, Updated {1}, Skipped {2}, Failed {3}
288+
CacheClearSummaryFormat = Cache clear summary: Removed {0}, Missing {1}, Skipped {2}, DryRun {3}, Errors {4}
270289
271290
# Interactive Messages
272291
PressSpacebarToContinue = Press [Spacebar] to continue to next, [Q] to quit`n
@@ -307,7 +326,7 @@ else {
307326
Write-ModuleTrace ("Private script directory '{0}' was not found." -f $privateDirectory)
308327
}
309328

310-
$localizationResult = Initialize-ColorScriptsLocalization -CandidateRoots ($moduleRootCandidates | Select-Object -Unique) -CultureFallbackOverride $cultureFallback
329+
$localizationResult = Initialize-ColorScriptsLocalization -CandidateRoots ($moduleRootCandidates | Select-Object -Unique) -CultureFallbackOverride $cultureFallback -UseDefaultCandidates
311330
if ($localizationResult -and $localizationResult.ModuleRoot) {
312331
$script:ModuleRoot = $localizationResult.ModuleRoot
313332
}

ColorScripts-Enhanced/Private/Initialize-ColorScriptsLocalization.ps1

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
function Initialize-ColorScriptsLocalization {
22
param(
33
[string[]]$CandidateRoots,
4-
[string[]]$CultureFallbackOverride
4+
[string[]]$CultureFallbackOverride,
5+
[switch]$UseDefaultCandidates
56
)
67

78
$null = $CandidateRoots
89
$null = $CultureFallbackOverride
10+
$useDefaultCandidatesFlag = $UseDefaultCandidates.IsPresent
911

1012
return Invoke-ModuleSynchronized $script:LocalizationSyncRoot {
1113
if ($script:LocalizationInitialized -and $script:Messages -and -not $CandidateRoots -and -not $CultureFallbackOverride) {
@@ -22,6 +24,32 @@ function Initialize-ColorScriptsLocalization {
2224
return $script:LocalizationDetails
2325
}
2426

27+
$localizationMode = if ($script:LocalizationMode) { $script:LocalizationMode } else { 'Auto' }
28+
$preferredCulture = $null
29+
if ($CultureFallbackOverride -and $CultureFallbackOverride.Count -gt 0) {
30+
$preferredCulture = $CultureFallbackOverride[0]
31+
}
32+
else {
33+
try {
34+
$preferredCulture = [System.Globalization.CultureInfo]::CurrentUICulture.Name
35+
}
36+
catch {
37+
$preferredCulture = $null
38+
}
39+
}
40+
41+
$preferEmbeddedDefaults = $false
42+
if ($localizationMode -eq 'Embedded') {
43+
$preferEmbeddedDefaults = $true
44+
}
45+
elseif ($localizationMode -eq 'Auto' -and $useDefaultCandidatesFlag) {
46+
if ([string]::IsNullOrWhiteSpace($preferredCulture) -or $preferredCulture.StartsWith('en', [System.StringComparison]::OrdinalIgnoreCase)) {
47+
$preferEmbeddedDefaults = $true
48+
}
49+
}
50+
51+
$preferredCultureDisplay = if ($preferredCulture) { $preferredCulture } else { 'n/a' }
52+
2553
$uniqueCandidates = New-Object System.Collections.Generic.List[string]
2654
if ($CandidateRoots) {
2755
foreach ($candidate in $CandidateRoots) {
@@ -90,6 +118,106 @@ function Initialize-ColorScriptsLocalization {
90118
throw [System.InvalidOperationException]::new('Unable to resolve a module root for localization resources.')
91119
}
92120

121+
if ($preferEmbeddedDefaults) {
122+
$cultureSearchOrder = New-Object System.Collections.Generic.List[string]
123+
if ($CultureFallbackOverride -and $CultureFallbackOverride.Count -gt 0) {
124+
foreach ($cultureName in $CultureFallbackOverride) {
125+
if ([string]::IsNullOrWhiteSpace($cultureName)) { continue }
126+
if (-not $cultureSearchOrder.Contains($cultureName)) {
127+
$null = $cultureSearchOrder.Add($cultureName)
128+
}
129+
}
130+
}
131+
elseif (-not [string]::IsNullOrWhiteSpace($preferredCulture)) {
132+
try {
133+
$cultureInfo = [System.Globalization.CultureInfo]::GetCultureInfo($preferredCulture)
134+
}
135+
catch {
136+
$cultureInfo = $null
137+
}
138+
139+
while ($cultureInfo -and $cultureInfo.Name -and -not [string]::IsNullOrWhiteSpace($cultureInfo.Name)) {
140+
if (-not $cultureSearchOrder.Contains($cultureInfo.Name)) {
141+
$null = $cultureSearchOrder.Add($cultureInfo.Name)
142+
}
143+
144+
if (-not $cultureInfo.Parent -or $cultureInfo.Parent.Name -eq $cultureInfo.Name) {
145+
break
146+
}
147+
148+
$cultureInfo = $cultureInfo.Parent
149+
}
150+
}
151+
152+
foreach ($fallbackCulture in @('en-US', 'en')) {
153+
if (-not [string]::IsNullOrWhiteSpace($fallbackCulture) -and -not $cultureSearchOrder.Contains($fallbackCulture)) {
154+
$null = $cultureSearchOrder.Add($fallbackCulture)
155+
}
156+
}
157+
158+
$localizedResourceExists = $false
159+
foreach ($candidatePath in $candidatePaths) {
160+
if ([string]::IsNullOrWhiteSpace($candidatePath)) { continue }
161+
162+
$probePaths = New-Object System.Collections.Generic.List[string]
163+
$null = $probePaths.Add((Join-Path -Path $candidatePath -ChildPath 'Messages.psd1'))
164+
165+
foreach ($cultureName in $cultureSearchOrder) {
166+
$cultureProbe = Join-Path -Path $candidatePath -ChildPath $cultureName
167+
$null = $probePaths.Add((Join-Path -Path $cultureProbe -ChildPath 'Messages.psd1'))
168+
}
169+
170+
foreach ($probe in ($probePaths | Select-Object -Unique)) {
171+
try {
172+
if (Test-Path -LiteralPath $probe -PathType Leaf) {
173+
$localizedResourceExists = $true
174+
break
175+
}
176+
}
177+
catch {
178+
continue
179+
}
180+
}
181+
182+
if ($localizedResourceExists) { break }
183+
}
184+
185+
if (-not $localizedResourceExists) {
186+
$moduleRootCandidate = $null
187+
if ($candidatePaths.Count -gt 0) {
188+
$moduleRootCandidate = $candidatePaths[0]
189+
}
190+
191+
if (-not $moduleRootCandidate -and $script:ModuleRoot) {
192+
$moduleRootCandidate = $script:ModuleRoot
193+
}
194+
elseif (-not $moduleRootCandidate -and $PSScriptRoot) {
195+
try {
196+
$moduleRootCandidate = (Resolve-Path -LiteralPath $PSScriptRoot -ErrorAction Stop).ProviderPath
197+
}
198+
catch {
199+
$moduleRootCandidate = $PSScriptRoot
200+
}
201+
}
202+
203+
$script:ModuleRoot = $moduleRootCandidate
204+
$script:Messages = if ($script:EmbeddedDefaultMessages) { $script:EmbeddedDefaultMessages.Clone() } else { @{} }
205+
$script:LocalizationInitialized = $true
206+
$script:LocalizationDetails = [pscustomobject]@{
207+
LocalizedDataLoaded = $false
208+
ModuleRoot = $moduleRootCandidate
209+
SearchedPaths = $candidatePaths.ToArray()
210+
Source = 'EmbeddedDefaults'
211+
FilePath = $null
212+
}
213+
214+
Write-ModuleTrace ("Localization using embedded defaults (mode: {0}, culture: {1})" -f $localizationMode, $preferredCultureDisplay)
215+
return $script:LocalizationDetails
216+
}
217+
218+
Write-ModuleTrace ("Embedded localization preference skipped; culture resources detected for {0}" -f $preferredCultureDisplay)
219+
}
220+
93221
$importSucceeded = $false
94222
$selectedRoot = $null
95223
$source = 'Import-LocalizedData'

ColorScripts-Enhanced/Public/Clear-ColorScriptCache.ps1

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,18 @@ function Clear-ColorScriptCache {
448448
$output = $results.ToArray()
449449

450450
if (-not $PassThru) {
451-
$summaryMessage = [string]::Format('Cache clear summary – Removed: {0}, Missing: {1}, Skipped: {2}, DryRun: {3}, Errors: {4}', $summary.Removed, $summary.Missing, $summary.Skipped, $summary.DryRun, $summary.Errors)
452-
Write-ColorScriptInformation -Message $summaryMessage -Quiet:$false
451+
$formatString = $null
452+
if ($script:Messages -and $script:Messages.ContainsKey('CacheClearSummaryFormat')) {
453+
$formatString = $script:Messages.CacheClearSummaryFormat
454+
}
455+
456+
if ([string]::IsNullOrWhiteSpace($formatString)) {
457+
$formatString = 'Cache clear summary: Removed {0}, Missing {1}, Skipped {2}, DryRun {3}, Errors {4}'
458+
}
459+
460+
$summaryMessage = $formatString -f $summary.Removed, $summary.Missing, $summary.Skipped, $summary.DryRun, $summary.Errors
461+
$summarySegment = New-ColorScriptAnsiText -Text $summaryMessage -Color 'Cyan' -NoAnsiOutput:$false
462+
Write-ColorScriptInformation -Message $summarySegment -Quiet:$false
453463
}
454464

455465
return $output

ColorScripts-Enhanced/Public/New-ColorScriptCache.ps1

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,18 @@ function New-ColorScriptCache {
335335
Write-Progress -Activity $activity -Completed -Status 'Completed'
336336

337337
if (-not $PassThru -and $summary.Processed -gt 0) {
338-
$summaryMessage = "Cache build summary: Processed {0}, Updated {1}, Skipped {2}, Failed {3}" -f $summary.Processed, $summary.Updated, $summary.Skipped, $summary.Failed
339-
Write-ColorScriptInformation -Message $summaryMessage -Quiet:$false
338+
$formatString = $null
339+
if ($script:Messages -and $script:Messages.ContainsKey('CacheBuildSummaryFormat')) {
340+
$formatString = $script:Messages.CacheBuildSummaryFormat
341+
}
342+
343+
if ([string]::IsNullOrWhiteSpace($formatString)) {
344+
$formatString = 'Cache build summary: Processed {0}, Updated {1}, Skipped {2}, Failed {3}'
345+
}
346+
347+
$summaryMessage = $formatString -f $summary.Processed, $summary.Updated, $summary.Skipped, $summary.Failed
348+
$summarySegment = New-ColorScriptAnsiText -Text $summaryMessage -Color 'Cyan' -NoAnsiOutput:$false
349+
Write-ColorScriptInformation -Message $summarySegment -Quiet:$false
340350
}
341351

342352
if ($PassThru) {

ColorScripts-Enhanced/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,29 @@ Clear-ColorScriptCache -Name "aurora-*" -Confirm:$false
347347

348348
> Tip: Set `COLOR_SCRIPTS_ENHANCED_CACHE_PATH` to redirect cache files to a custom directory for CI or ephemeral test runs.
349349
350+
### Validate Cache on Demand
351+
352+
```powershell
353+
# Rebuild cache metadata before rendering
354+
Show-ColorScript -Name "bars" -ValidateCache
355+
356+
# Apply validation for the entire session
357+
$env:COLOR_SCRIPTS_ENHANCED_VALIDATE_CACHE = '1'
358+
Import-Module ColorScripts-Enhanced -Force
359+
```
360+
361+
Use the `-ValidateCache` switch (or the `COLOR_SCRIPTS_ENHANCED_VALIDATE_CACHE` environment variable) whenever you suspect stale cache data or when testing new scripts.
362+
363+
### Localization Modes
364+
365+
Auto mode prefers PSD1 resources whenever they exist so you can override English strings without recompiling the module. Fine-tune the behaviour with `COLOR_SCRIPTS_ENHANCED_LOCALIZATION_MODE`:
366+
367+
- `auto` *(default)* – load PSD1 files when present, otherwise fall back to embedded messages.
368+
- `full` – always load from disk, even if embedded defaults would succeed.
369+
- `embedded` – skip PSD1 probes and rely on built-in English messages.
370+
371+
Legacy toggles `COLOR_SCRIPTS_ENHANCED_FORCE_LOCALIZATION` and `COLOR_SCRIPTS_ENHANCED_PREFER_EMBEDDED_MESSAGES` are still honoured, but the consolidated mode variable is recommended.
372+
350373
### Persist Defaults with Configuration
351374

352375
```powershell

ColorScripts-Enhanced/de/ColorScripts-Enhanced_f77548d7-23eb-48ce-a6e0-f64b4758d995_HelpInfo.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<SupportedUICultures>
55
<UICulture>
66
<UICultureName>de</UICultureName>
7-
<UICultureVersion>2025.11.05.2125</UICultureVersion>
7+
<UICultureVersion>2025.11.06.0250</UICultureVersion>
88
</UICulture>
99
</SupportedUICultures>
1010
</HelpInfo>

ColorScripts-Enhanced/de/Messages.psd1

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ StatusSkippedUpToDate = Übersprungen (aktuell)
5656
StatusSkippedByUser = Vom Benutzer übersprungen
5757
StatusFailed = Fehlgeschlagen
5858
StatusUpToDateSkipped = Aktuell (übersprungen)
59+
CacheBuildSummaryFormat = Cache build summary: Processed {0}, Updated {1}, Skipped {2}, Failed {3}
60+
CacheClearSummaryFormat = Cache clear summary: Removed {0}, Missing {1}, Skipped {2}, DryRun {3}, Errors {4}
5961
6062
# Interactive Messages
6163
PressSpacebarToContinue = Drücken Sie [Leertaste] um fortzufahren, [Q] zum Beenden`n

ColorScripts-Enhanced/docs/Development.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,12 @@ Expect to see icons, checkmarks, and box-drawing characters. If they appear as s
513513
- Override cache location for testing/CI with `COLOR_SCRIPTS_ENHANCED_CACHE_PATH`
514514
- Use `New-ColorScriptCache` to warm caches during development
515515
- Use `Clear-ColorScriptCache` to troubleshoot stale outputs
516+
- Force validation when diagnosing cache issues with `Show-ColorScript -ValidateCache` or by setting `COLOR_SCRIPTS_ENHANCED_VALIDATE_CACHE=1`
517+
518+
## Localization Controls
519+
520+
- Auto mode prefers PSD1 resources when available; adjust behavior with `COLOR_SCRIPTS_ENHANCED_LOCALIZATION_MODE` (`auto`, `full`, `embedded`)
521+
- Legacy toggle `COLOR_SCRIPTS_ENHANCED_PREFER_EMBEDDED_MESSAGES` remains supported for compatibility, but prefer the consolidated mode variable going forward
516522

517523
## Branch Policy
518524

0 commit comments

Comments
 (0)