Skip to content

feat: Add dynamic multi-language support for the GUI#643

Open
jmolinap2 wants to merge 2 commits into
Raphire:masterfrom
jmolinap2:feat/language-support
Open

feat: Add dynamic multi-language support for the GUI#643
jmolinap2 wants to merge 2 commits into
Raphire:masterfrom
jmolinap2:feat/language-support

Conversation

@jmolinap2

@jmolinap2 jmolinap2 commented Jun 21, 2026

Copy link
Copy Markdown

Summary

This PR adds a dynamic localization system to the Win11Debloat GUI, allowing the interface to display in the user's system language automatically.

Changes

  • Scripts/FileIO/LoadLanguage.ps1 — new language loader: detects system UI culture, loads the matching JSON file from Config/Languages/, falls back to en-US. Provides helper functions: L, Get-LangCategory, Get-LangFeature, Get-LangGroupLabel, Get-LangGroupValue, Get-LangFeatureTooltip, Get-LangGroupTooltip
  • Config/Languages/en-US.json — full English strings for all UI labels, tooltips, categories, messages and feature descriptions
  • Config/Languages/es-ES.json — complete Spanish (Castilian) translation
  • Schemas/MainWindow.xaml — all hardcoded strings replaced with %LANG:key% markers
  • Scripts/GUI/ — all GUI scripts updated to use L 'key' calls and lang helper functions for dynamically-built controls (tweaks, app list, tooltips)
  • Win11Debloat.ps1 — loads language on startup via $script:Lang = LoadLanguage

How it works

On startup, the script reads [System.Globalization.CultureInfo]::CurrentUICulture. It tries an exact match (es-ES.json), then a prefix match (es-*.json), then falls back to en-US.json. New languages can be added by dropping a JSON file in Config/Languages/.

Adding a new language

Create Config/Languages/<culture-code>.json following the structure of en-US.json. The loader will pick it up automatically.

Multi-Language Localization System Implementation

This PR introduces a comprehensive dynamic localization framework to the Win11Debloat GUI, enabling the interface to automatically display in the user's system language with a fallback to English.

Core Infrastructure

Scripts/FileIO/LoadLanguage.ps1 — New module providing language detection and localization helpers:

  • LoadLanguage function: Detects the system UI culture (e.g., es-ES, en-US) and loads the corresponding JSON language file from Config/Languages/. Uses an "exact match → prefix glob → en-US fallback" strategy
  • ConvertTo-LocalizedXaml function: Substitutes %LANG:Key% markers in XAML with translated values, XML-escaping results for safe XAML attribute usage
  • Helper functions for retrieving localized strings: L (generic key lookup), Get-LangCategory, Get-LangFeature, Get-LangGroupLabel, Get-LangGroupValue, Get-LangFeatureTooltip, Get-LangGroupTooltip

Language Resources

Config/Languages/en-US.json and Config/Languages/es-ES.json — Complete localization files (~371 lines each) containing:

  • Language metadata (version, name, language code)
  • UI navigation and menu action labels
  • Home screen prompts and placeholders
  • App removal and tweak selection interface text (labels, tooltips, presets, search)
  • Deployment settings and configuration options
  • Feature descriptions, category mappings, and grouped feature configurations
  • Status messages, error text, and button labels

UI Integration

Schemas/MainWindow.xaml — Updated to replace 79 hardcoded English strings with %LANG:key% markers across:

  • Title bar and context menu
  • Home, App Removal, Tweaks, and Deployment Settings tabs
  • Navigation buttons and progress indicators
  • Tooltips and automation properties

GUI Scripts — Modified to use localization functions:

  • MainWindow-AppSelection.ps1: App status and scope descriptions now use localized strings
  • MainWindow-Deployment.ps1: Overview and deployment messages use localized resources
  • MainWindow-TweaksBuilder.ps1: Category headers, feature labels, group options, and tooltips are localized
  • Show-MainWindow.ps1: XAML is processed through ConvertTo-LocalizedXaml on load; error messages and UI text use localized resources
  • Show-MessageBox.ps1: Button labels (OK, Cancel, Yes, No) use localized resources

Win11Debloat.ps1 — Loads the language module and initializes the system language on startup:

  • Defines $script:LanguagesPath pointing to Config/Languages
  • Dot-sources Scripts/FileIO/LoadLanguage.ps1
  • Sets $script:Lang via LoadLanguage with automatic system language detection and en-US fallback

Language Extension

Adding support for additional languages requires creating a new JSON file in Config/Languages/<culture-code>.json following the structure of the en-US.json template. The loader automatically detects and uses the file based on the system UI culture.

- Introduced LoadLanguage.ps1 to detect system UI language and load corresponding language files.
- Implemented ConvertTo-LocalizedXaml function to replace %LANG:Key% markers in XAML with localized strings.
- Updated various GUI scripts to utilize localization functions for displaying messages and labels.
- Replaced hardcoded strings with localized versions in MainWindow-AppSelection.ps1, MainWindow-Deployment.ps1, Show-MainWindow.ps1, and Show-MessageBox.ps1.
- Added language file loading in Win11Debloat.ps1 and set default language to system UI language with a fallback to en-US.
- Updated es-ES.json with extensive translations for tweaks, features, and tooltips.
- Enhanced LoadLanguage.ps1 to support new translation functions for categories, features, and tooltips.
- Modified MainWindow-AppSelection.ps1 to utilize translated recommendations for app removal.
- Updated MainWindow-TweaksBuilder.ps1 to display translated category names, feature labels, and tooltips in the UI.
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end localization support to Win11Debloat. A new LoadLanguage.ps1 module resolves and loads a language JSON at startup, substitutes %LANG:Key% placeholders in the XAML schema via ConvertTo-LocalizedXaml, and exposes translation helpers (L, Get-LangFeature, etc.) used throughout the GUI scripts. All hardcoded English strings in GUI scripts and the XAML template are replaced with localized lookups. English (en-US) and Spanish (es-ES) JSON files are added.

Changes

Localization Pipeline

Layer / File(s) Summary
Language data contracts
Config/Languages/en-US.json, Config/Languages/es-ES.json
Adds complete English and Spanish JSON files covering language metadata, all UI string keys (navigation, home, app removal, tweaks, deployment, buttons, messages, tooltips), FeaturesCategories/FeaturesLabels maps, FeaturesToolTips/GroupsToolTips blocks, and structured FeaturesGroups schemas with Label and Values entries.
Language loading module and script wiring
Scripts/FileIO/LoadLanguage.ps1, Win11Debloat.ps1
Adds LoadLanguage (exact/prefix/en-US fallback file resolution and UTF-8 JSON parse), ConvertTo-LocalizedXaml (placeholder substitution with XML escaping), and shorthand helpers L, Get-LangCategory, Get-LangFeature, Get-LangGroupLabel, Get-LangFeatureTooltip, Get-LangGroupTooltip, Get-LangGroupValue. Win11Debloat.ps1 adds $script:LanguagesPath, dot-sources the module, and initializes $script:Lang at startup.
XAML template placeholder substitution
Schemas/MainWindow.xaml, Scripts/GUI/Show-MainWindow.ps1 (load path)
Replaces all hardcoded English strings in MainWindow.xaml with %LANG:Key% placeholders across every tab, button, column header, and accessibility property. Show-MainWindow.ps1 passes raw XAML through ConvertTo-LocalizedXaml before parsing so placeholders resolve at window load time.
Runtime localization of GUI script strings
Scripts/GUI/Show-MainWindow.ps1, Scripts/GUI/MainWindow-AppSelection.ps1, Scripts/GUI/MainWindow-Deployment.ps1, Scripts/GUI/MainWindow-TweaksBuilder.ps1, Scripts/GUI/Show-MessageBox.ps1
All message boxes, bubble text, status labels, combo descriptions, tooltip content, button labels, and scope-selection logic are updated to use L/Get-Lang* helpers; scope selection switches from matching SelectedItem.Content strings to SelectedIndex integers.

Sequence Diagram(s)

sequenceDiagram
  participant Win11Debloat.ps1
  participant LoadLanguage.ps1
  participant LanguagesPath
  participant Show-MainWindow.ps1
  participant GUI Scripts

  Win11Debloat.ps1->>LoadLanguage.ps1: LoadLanguage (system culture or parameter)
  LoadLanguage.ps1->>LanguagesPath: exact match → prefix glob → en-US fallback
  LanguagesPath-->>LoadLanguage.ps1: JSON file bytes
  LoadLanguage.ps1-->>Win11Debloat.ps1: $script:Lang object

  Win11Debloat.ps1->>Show-MainWindow.ps1: invoke Show-MainWindow
  Show-MainWindow.ps1->>LoadLanguage.ps1: ConvertTo-LocalizedXaml(rawXaml, $script:Lang)
  LoadLanguage.ps1-->>Show-MainWindow.ps1: XAML with %LANG:Key% replaced
  Show-MainWindow.ps1->>Show-MainWindow.ps1: parse and display localized XAML

  GUI Scripts->>LoadLanguage.ps1: L / Get-LangFeature / Get-LangCategory / ...
  LoadLanguage.ps1-->>GUI Scripts: translated string or fallback
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main purpose of the PR—adding dynamic multi-language support to the GUI.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Scripts/FileIO/LoadLanguage.ps1 (1)

58-58: ⚡ Quick win

Consider adding nested object keys to the skip list for defensive coding.

The skipKeys list currently excludes only metadata keys, but the JSON schema also contains nested objects (FeaturesToolTips, FeaturesCategories, FeaturesLabels, FeaturesGroups, GroupsToolTips per PR objectives and context snippets). If someone later mistakenly adds a placeholder like %LANG:FeaturesToolTips% to the XAML, line 63 would stringify the object as "System.Management.Automation.PSCustomObject" and substitute that garbage into the markup.

While no current XAML placeholder uses these keys, extending the skip list prevents future bugs:

-$skipKeys = @('Version', 'LanguageName', 'NativeName', 'LanguageCode')
+$skipKeys = @('Version', 'LanguageName', 'NativeName', 'LanguageCode', 'FeaturesToolTips', 'FeaturesCategories', 'FeaturesLabels', 'FeaturesGroups', 'GroupsToolTips')

Alternatively, guard by type:

if ($prop.Value -is [PSCustomObject] -or $prop.Value -is [Array]) { continue }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Scripts/FileIO/LoadLanguage.ps1` at line 58, The skipKeys array needs to be
extended to include nested object keys (FeaturesToolTips, FeaturesCategories,
FeaturesLabels, FeaturesGroups, GroupsToolTips) to prevent them from being
stringified and inserted into XAML if someone accidentally adds a placeholder
for them. Add these nested object keys to the skipKeys list alongside the
existing metadata keys like Version and LanguageName. Alternatively, add a type
guard in the property iteration logic around line 63 to check if the property
value is a PSCustomObject or Array type and skip it, which provides defensive
coverage without hardcoding specific key names.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Scripts/FileIO/LoadLanguage.ps1`:
- Line 58: The skipKeys array needs to be extended to include nested object keys
(FeaturesToolTips, FeaturesCategories, FeaturesLabels, FeaturesGroups,
GroupsToolTips) to prevent them from being stringified and inserted into XAML if
someone accidentally adds a placeholder for them. Add these nested object keys
to the skipKeys list alongside the existing metadata keys like Version and
LanguageName. Alternatively, add a type guard in the property iteration logic
around line 63 to check if the property value is a PSCustomObject or Array type
and skip it, which provides defensive coverage without hardcoding specific key
names.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9710bc0e-d713-48e7-b8b6-e3f8ddaa3d41

📥 Commits

Reviewing files that changed from the base of the PR and between 908274a and 95c2c72.

📒 Files selected for processing (10)
  • Config/Languages/en-US.json
  • Config/Languages/es-ES.json
  • Schemas/MainWindow.xaml
  • Scripts/FileIO/LoadLanguage.ps1
  • Scripts/GUI/MainWindow-AppSelection.ps1
  • Scripts/GUI/MainWindow-Deployment.ps1
  • Scripts/GUI/MainWindow-TweaksBuilder.ps1
  • Scripts/GUI/Show-MainWindow.ps1
  • Scripts/GUI/Show-MessageBox.ps1
  • Win11Debloat.ps1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant