mirror of
https://github.com/Raphire/Win11Debloat.git
synced 2026-10-07 22:16:43 +00:00
Add localization for app names and descriptions (#769)
* Translate app names and descriptions in Config/Apps.json * Document Apps section and first-ID translation key for multi-ID apps * Fix app list breaking when "Only show installed" runs translation in an isolated runspace
This commit is contained in:
@@ -196,7 +196,7 @@ Avoid these common mistakes when contributing:
|
|||||||
|
|
||||||
8. **Hardcoded Paths**: When writing PowerShell logic, use `$PSScriptRoot` and script variables instead of hardcoded paths. This ensures the script works regardless of where it's installed.
|
8. **Hardcoded Paths**: When writing PowerShell logic, use `$PSScriptRoot` and script variables instead of hardcoded paths. This ensures the script works regardless of where it's installed.
|
||||||
|
|
||||||
9. **Missing Translation Entry**: A new Feature, Category, or UI Group needs a matching entry in `Config/Languages/en-US/` (see [Localizing UI Text](#localizing-ui-text)). Without one, the GUI silently falls back to displaying the raw `FeatureId`/`CategoryId`/`GroupId` instead of your `Label`/`ToolTip` text.
|
9. **Missing Translation Entry**: A new Feature, Category, UI Group, or App needs a matching entry in `Config/Languages/en-US/` (see [Localizing UI Text](#localizing-ui-text)). Without one, the GUI silently falls back to displaying the raw `FeatureId`/`CategoryId`/`GroupId`/`AppId` instead of your `Label`/`ToolTip`/`FriendlyName`/`Description` text.
|
||||||
|
|
||||||
## Implementing New Features
|
## Implementing New Features
|
||||||
|
|
||||||
@@ -233,7 +233,8 @@ To add a new app that can be removed via Win11Debloat:
|
|||||||
- `FriendlyName`: Display name shown in the GUI.
|
- `FriendlyName`: Display name shown in the GUI.
|
||||||
- `AppId`: The package name from `Get-AppxPackage` or the `Id` from
|
- `AppId`: The package name from `Get-AppxPackage` or the `Id` from
|
||||||
`winget list`, depending on removal method. Use an array when one app
|
`winget list`, depending on removal method. Use an array when one app
|
||||||
requires multiple identifiers.
|
requires multiple identifiers. The GUI looks up the translation entry by
|
||||||
|
the first ID in the array, key `Apps.json` by that one.
|
||||||
- `Description`: Brief description of the app shown in the GUI.
|
- `Description`: Brief description of the app shown in the GUI.
|
||||||
- `SelectedByDefault`: Set to `true` only for apps that are largely considered bloatware, otherwise set to `false`.
|
- `SelectedByDefault`: Set to `true` only for apps that are largely considered bloatware, otherwise set to `false`.
|
||||||
- `Recommendation`: Indicates how strongly the app is recommended for removal. One of:
|
- `Recommendation`: Indicates how strongly the app is recommended for removal. One of:
|
||||||
@@ -244,7 +245,9 @@ To add a new app that can be removed via Win11Debloat:
|
|||||||
- `Appx` — remove as a standard Appx package via `Remove-AppxPackage` (most apps)
|
- `Appx` — remove as a standard Appx package via `Remove-AppxPackage` (most apps)
|
||||||
- `WinGet` — remove via WinGet (`winget uninstall`). Use for non-Appx apps such as Microsoft Copilot.
|
- `WinGet` — remove via WinGet (`winget uninstall`). Use for non-Appx apps such as Microsoft Copilot.
|
||||||
|
|
||||||
3. **Follow the Guidelines**:
|
3. **Add the English Translation Entry**: Add a matching entry for your `AppId` to `Config/Languages/en-US/Apps.json` (see [Localizing UI Text](#localizing-ui-text)) with `FriendlyName` and `Description` matching what you set above, so the GUI shows them instead of the raw `AppId`.
|
||||||
|
|
||||||
|
4. **Follow the Guidelines**:
|
||||||
|
|
||||||
- Use clear, user-friendly names for `FriendlyName`
|
- Use clear, user-friendly names for `FriendlyName`
|
||||||
- Provide a concise description explaining what the app does
|
- Provide a concise description explaining what the app does
|
||||||
@@ -451,11 +454,12 @@ Add a matching entry for your `GroupId` to `Config/Languages/en-US/Features.json
|
|||||||
|
|
||||||
### Localizing UI Text
|
### Localizing UI Text
|
||||||
|
|
||||||
GUI text lives in `Config/Languages/en-US/`, not hardcoded in `Schemas/*.xaml` or `Scripts/GUI/*.ps1`. Adding or changing a Feature, Category, or UI Group means updating the matching English entry, or the GUI falls back to showing the raw ID.
|
GUI text lives in `Config/Languages/en-US/`, not hardcoded in `Schemas/*.xaml` or `Scripts/GUI/*.ps1`. Adding or changing a Feature, Category, UI Group, or App means updating the matching English entry, or the GUI falls back to showing the raw ID.
|
||||||
|
|
||||||
- `Config/Languages/en-US/Features.json`, under `"Features"`, keyed by `FeatureId`. Add `Label`, `ToolTip`, `ApplyText`, `UndoLabel`, and `ApplyUndoText` to match whatever fields you set in `Config/Features.json`.
|
- `Config/Languages/en-US/Features.json`, under `"Features"`, keyed by `FeatureId`. Add `Label`, `ToolTip`, `ApplyText`, `UndoLabel`, and `ApplyUndoText` to match whatever fields you set in `Config/Features.json`.
|
||||||
- `Config/Languages/en-US/Features.json`, under `"UiGroups"`, keyed by `GroupId`. Add `Label`, `ToolTip`, and a `Values` map of `FeatureId: "Option label"` matching the group's `Values` array.
|
- `Config/Languages/en-US/Features.json`, under `"UiGroups"`, keyed by `GroupId`. Add `Label`, `ToolTip`, and a `Values` map of `FeatureId: "Option label"` matching the group's `Values` array.
|
||||||
- `Config/Languages/en-US/Categories.json`, keyed by `CategoryId`. Add a `Label` for every new category.
|
- `Config/Languages/en-US/Categories.json`, keyed by `CategoryId`. Add a `Label` for every new category.
|
||||||
|
- `Config/Languages/en-US/Apps.json`, keyed by `AppId`. Add `FriendlyName` and `Description` for every new app.
|
||||||
- `Config/Languages/en-US/Chrome.json`, a flat key/value map for static GUI chrome: buttons, dialog titles, tooltips not tied to a specific Feature/Category/UiGroup. Add a key here only for new static text, and reference it from XAML with a `%LANG:YourKey%` marker or from PowerShell with `Get-Translation -Key 'YourKey'`.
|
- `Config/Languages/en-US/Chrome.json`, a flat key/value map for static GUI chrome: buttons, dialog titles, tooltips not tied to a specific Feature/Category/UiGroup. Add a key here only for new static text, and reference it from XAML with a `%LANG:YourKey%` marker or from PowerShell with `Get-Translation -Key 'YourKey'`.
|
||||||
|
|
||||||
Check for an existing `Chrome.json` key with the same English text before adding a new one. Two keys holding identical strings is duplication waiting to drift.
|
Check for an existing `Chrome.json` key with the same English text before adding a new one. Two keys holding identical strings is duplication waiting to drift.
|
||||||
@@ -468,7 +472,7 @@ A new language is its own pull request, not something bundled with unrelated cha
|
|||||||
|
|
||||||
1. **Create the language folder**: copy `Config/Languages/en-US/` to `Config/Languages/<culture-code>/`, using the .NET culture code the GUI should match (`nl-NL`, `es-ES`). This is also the folder matched against the user's Windows display language: exact match first, then a language-only prefix match (`nl-BE` falls back to `nl-NL` if that's the only Dutch folder present), then `en-US` if nothing matches.
|
1. **Create the language folder**: copy `Config/Languages/en-US/` to `Config/Languages/<culture-code>/`, using the .NET culture code the GUI should match (`nl-NL`, `es-ES`). This is also the folder matched against the user's Windows display language: exact match first, then a language-only prefix match (`nl-BE` falls back to `nl-NL` if that's the only Dutch folder present), then `en-US` if nothing matches.
|
||||||
|
|
||||||
2. **Translate the three files** (`Chrome.json`, `Features.json`, `Categories.json`), keeping every key name exactly as it is in `en-US`. Only the values change. Leave a key untranslated and the GUI shows the `en-US` text for it instead of a blank or a crash, so a translation can land incrementally.
|
2. **Translate the four files** (`Chrome.json`, `Features.json`, `Categories.json`, `Apps.json`), keeping every key name exactly as it is in `en-US`. Only the values change. Leave a key untranslated and the GUI shows the `en-US` text for it instead of a blank or a crash, so a translation can land incrementally.
|
||||||
|
|
||||||
3. **Add the language's plural rule**. Strings using the `_one`/`_other` suffix convention (see `AppsSelectedCount_one` in `en-US/Chrome.json`) need a matching `case` in `Get-PluralCategory` (`Scripts/FileIO/Import-LanguageFile.ps1`), keyed by language prefix (`'nl'`). Several languages share English's rule, singular at exactly 1, plural otherwise, and can reuse it as-is. Others need more categories: CLDR defines `zero`/`one`/`two`/`few`/`many`/`other`. Match your key suffixes to whatever categories your language's rule actually uses.
|
3. **Add the language's plural rule**. Strings using the `_one`/`_other` suffix convention (see `AppsSelectedCount_one` in `en-US/Chrome.json`) need a matching `case` in `Get-PluralCategory` (`Scripts/FileIO/Import-LanguageFile.ps1`), keyed by language prefix (`'nl'`). Several languages share English's rule, singular at exactly 1, plural otherwise, and can reuse it as-is. Others need more categories: CLDR defines `zero`/`one`/`two`/`few`/`many`/`other`. Match your key suffixes to whatever categories your language's rule actually uses.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,566 @@
|
|||||||
|
{
|
||||||
|
"Clipchamp.Clipchamp": {
|
||||||
|
"FriendlyName": "Clipchamp",
|
||||||
|
"Description": "Video editor from Microsoft"
|
||||||
|
},
|
||||||
|
"Microsoft.3DBuilder": {
|
||||||
|
"FriendlyName": "3D Builder",
|
||||||
|
"Description": "Basic 3D modeling software"
|
||||||
|
},
|
||||||
|
"Microsoft.549981C3F5F10": {
|
||||||
|
"FriendlyName": "Cortana",
|
||||||
|
"Description": "Microsoft Cortana voice assistant (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingFinance": {
|
||||||
|
"FriendlyName": "Bing Finance",
|
||||||
|
"Description": "Finance news and tracking via Bing (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingFoodAndDrink": {
|
||||||
|
"FriendlyName": "Bing Food And Drink",
|
||||||
|
"Description": "Recipes and food news via Bing (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingHealthAndFitness": {
|
||||||
|
"FriendlyName": "Bing Health And Fitness",
|
||||||
|
"Description": "Health and fitness tracking/news via Bing (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingNews": {
|
||||||
|
"FriendlyName": "Bing News",
|
||||||
|
"Description": "News aggregator via Bing (Replaced by Microsoft News/Start)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingSports": {
|
||||||
|
"FriendlyName": "Bing Sports",
|
||||||
|
"Description": "Sports news and scores via Bing (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingTranslator": {
|
||||||
|
"FriendlyName": "Bing Translator",
|
||||||
|
"Description": "Translation service via Bing"
|
||||||
|
},
|
||||||
|
"Microsoft.BingTravel": {
|
||||||
|
"FriendlyName": "Bing Travel",
|
||||||
|
"Description": "Travel planning and news via Bing (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingWeather": {
|
||||||
|
"FriendlyName": "Bing Weather",
|
||||||
|
"Description": "Weather forecast via Bing"
|
||||||
|
},
|
||||||
|
"XP9CXNGPPJ97XX": {
|
||||||
|
"FriendlyName": "Microsoft Copilot",
|
||||||
|
"Description": "AI assistant integrated into Windows"
|
||||||
|
},
|
||||||
|
"Microsoft.Windows.AIHub": {
|
||||||
|
"FriendlyName": "Copilot+ AI Hub",
|
||||||
|
"Description": "Copilot+ AI Hub app (Windows 11 24H2+)"
|
||||||
|
},
|
||||||
|
"Microsoft.PCManager": {
|
||||||
|
"FriendlyName": "Microsoft PC Manager",
|
||||||
|
"Description": "Microsoft PC Manager system cleanup and optimization tool (often preinstalled)"
|
||||||
|
},
|
||||||
|
"Microsoft.Getstarted": {
|
||||||
|
"FriendlyName": "Get Started",
|
||||||
|
"Description": "Tips and introductory guide for Windows (Cannot be uninstalled in Windows 11)"
|
||||||
|
},
|
||||||
|
"Microsoft.Messaging": {
|
||||||
|
"FriendlyName": "Messaging",
|
||||||
|
"Description": "Messaging app, often integrates with Skype (Largely discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.Microsoft3DViewer": {
|
||||||
|
"FriendlyName": "3D Viewer",
|
||||||
|
"Description": "Viewer for 3D models"
|
||||||
|
},
|
||||||
|
"Microsoft.MicrosoftJournal": {
|
||||||
|
"FriendlyName": "Microsoft Journal",
|
||||||
|
"Description": "Digital note-taking app optimized for pen input"
|
||||||
|
},
|
||||||
|
"Microsoft.MicrosoftOfficeHub": {
|
||||||
|
"FriendlyName": "Office Hub",
|
||||||
|
"Description": "Hub to access Microsoft Office apps and documents (Precursor to Microsoft 365 app)"
|
||||||
|
},
|
||||||
|
"Microsoft.MicrosoftPowerBIForWindows": {
|
||||||
|
"FriendlyName": "Power BI",
|
||||||
|
"Description": "Business analytics service client"
|
||||||
|
},
|
||||||
|
"Microsoft.MicrosoftSolitaireCollection": {
|
||||||
|
"FriendlyName": "Solitaire Collection",
|
||||||
|
"Description": "Collection of solitaire card games"
|
||||||
|
},
|
||||||
|
"Microsoft.MicrosoftStickyNotes": {
|
||||||
|
"FriendlyName": "Sticky Notes",
|
||||||
|
"Description": "Digital sticky notes app (Discontinued & replaced by OneNote)"
|
||||||
|
},
|
||||||
|
"Microsoft.MixedReality.Portal": {
|
||||||
|
"FriendlyName": "Mixed Reality Portal",
|
||||||
|
"Description": "Portal for Windows Mixed Reality headsets"
|
||||||
|
},
|
||||||
|
"Microsoft.NetworkSpeedTest": {
|
||||||
|
"FriendlyName": "Network Speed Test",
|
||||||
|
"Description": "Internet connection speed test utility"
|
||||||
|
},
|
||||||
|
"Microsoft.News": {
|
||||||
|
"FriendlyName": "Microsoft News",
|
||||||
|
"Description": "News aggregator (Replaced Bing News, now part of Microsoft Start)"
|
||||||
|
},
|
||||||
|
"Microsoft.Office.OneNote": {
|
||||||
|
"FriendlyName": "OneNote",
|
||||||
|
"Description": "Digital note-taking app (Universal Windows Platform version)"
|
||||||
|
},
|
||||||
|
"Microsoft.Office.Sway": {
|
||||||
|
"FriendlyName": "Sway",
|
||||||
|
"Description": "Presentation and storytelling app"
|
||||||
|
},
|
||||||
|
"Microsoft.OneConnect": {
|
||||||
|
"FriendlyName": "One Connect",
|
||||||
|
"Description": "Mobile Operator management app (Replaced by Mobile Plans)"
|
||||||
|
},
|
||||||
|
"Microsoft.Print3D": {
|
||||||
|
"FriendlyName": "Print 3D",
|
||||||
|
"Description": "3D printing preparation software"
|
||||||
|
},
|
||||||
|
"Microsoft.PowerAutomateDesktop": {
|
||||||
|
"FriendlyName": "Power Automate",
|
||||||
|
"Description": "Desktop automation tool (RPA)"
|
||||||
|
},
|
||||||
|
"Microsoft.SkypeApp": {
|
||||||
|
"FriendlyName": "Skype (UWP)",
|
||||||
|
"Description": "Skype communication app, Universal Windows Platform version (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.Todos": {
|
||||||
|
"FriendlyName": "Microsoft To Do",
|
||||||
|
"Description": "To-do list and task management app"
|
||||||
|
},
|
||||||
|
"Microsoft.Windows.DevHome": {
|
||||||
|
"FriendlyName": "Dev Home",
|
||||||
|
"Description": "Developer dashboard and tool configuration utility (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsAlarms": {
|
||||||
|
"FriendlyName": "Alarms & Clock",
|
||||||
|
"Description": "Alarms & Clock app"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsFeedbackHub": {
|
||||||
|
"FriendlyName": "Feedback Hub",
|
||||||
|
"Description": "App for providing feedback to Microsoft on Windows"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsMaps": {
|
||||||
|
"FriendlyName": "Windows Maps",
|
||||||
|
"Description": "Mapping and navigation app"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsSoundRecorder": {
|
||||||
|
"FriendlyName": "Sound Recorder",
|
||||||
|
"Description": "Basic audio recording app"
|
||||||
|
},
|
||||||
|
"Microsoft.XboxApp": {
|
||||||
|
"FriendlyName": "Xbox Console Companion",
|
||||||
|
"Description": "Old Xbox Console Companion App (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.ZuneVideo": {
|
||||||
|
"FriendlyName": "Movies & TV",
|
||||||
|
"Description": "Movies & TV app for renting/buying/playing video content (Rebranded as \"Films & TV\")"
|
||||||
|
},
|
||||||
|
"MicrosoftCorporationII.MicrosoftFamily": {
|
||||||
|
"FriendlyName": "Family Safety",
|
||||||
|
"Description": "Family Safety App for managing family accounts and settings"
|
||||||
|
},
|
||||||
|
"MicrosoftCorporationII.QuickAssist": {
|
||||||
|
"FriendlyName": "Quick Assist",
|
||||||
|
"Description": "Remote assistance tool"
|
||||||
|
},
|
||||||
|
"MicrosoftTeams": {
|
||||||
|
"FriendlyName": "Microsoft Teams (Old)",
|
||||||
|
"Description": "Old Microsoft Teams personal (MS Store version)"
|
||||||
|
},
|
||||||
|
"MSTeams": {
|
||||||
|
"FriendlyName": "Microsoft Teams (New)",
|
||||||
|
"Description": "New Microsoft Teams app (Work/School or Personal)"
|
||||||
|
},
|
||||||
|
"ACGMediaPlayer": {
|
||||||
|
"FriendlyName": "ACG Media Player",
|
||||||
|
"Description": "Media player app"
|
||||||
|
},
|
||||||
|
"ActiproSoftwareLLC": {
|
||||||
|
"FriendlyName": "Actipro Software",
|
||||||
|
"Description": "Potentially UI controls or software components, often bundled by OEMs"
|
||||||
|
},
|
||||||
|
"AdobeSystemsIncorporated.AdobePhotoshopExpress": {
|
||||||
|
"FriendlyName": "Adobe Photoshop Express",
|
||||||
|
"Description": "Basic photo editing app from Adobe"
|
||||||
|
},
|
||||||
|
"Amazon.com.Amazon": {
|
||||||
|
"FriendlyName": "Amazon",
|
||||||
|
"Description": "Amazon shopping app"
|
||||||
|
},
|
||||||
|
"AmazonVideo.PrimeVideo": {
|
||||||
|
"FriendlyName": "Prime Video",
|
||||||
|
"Description": "Amazon Prime Video streaming service app"
|
||||||
|
},
|
||||||
|
"Asphalt8Airborne": {
|
||||||
|
"FriendlyName": "Asphalt 8",
|
||||||
|
"Description": "Racing game"
|
||||||
|
},
|
||||||
|
"AutodeskSketchBook": {
|
||||||
|
"FriendlyName": "Autodesk SketchBook",
|
||||||
|
"Description": "Digital drawing and sketching app"
|
||||||
|
},
|
||||||
|
"CaesarsSlotsFreeCasino": {
|
||||||
|
"FriendlyName": "Caesars Slots",
|
||||||
|
"Description": "Casino slot machine game"
|
||||||
|
},
|
||||||
|
"COOKINGFEVER": {
|
||||||
|
"FriendlyName": "Cooking Fever",
|
||||||
|
"Description": "Restaurant simulation game"
|
||||||
|
},
|
||||||
|
"CyberLinkMediaSuiteEssentials": {
|
||||||
|
"FriendlyName": "CyberLink Media Suite",
|
||||||
|
"Description": "Multimedia software suite (often preinstalled by OEMs)"
|
||||||
|
},
|
||||||
|
"DisneyMagicKingdoms": {
|
||||||
|
"FriendlyName": "Disney Magic Kingdoms",
|
||||||
|
"Description": "Disney theme park building game"
|
||||||
|
},
|
||||||
|
"Disney.37853FC22B2CE": {
|
||||||
|
"FriendlyName": "Disney+",
|
||||||
|
"Description": "Disney+ streaming service app"
|
||||||
|
},
|
||||||
|
"DrawboardPDF": {
|
||||||
|
"FriendlyName": "Drawboard PDF",
|
||||||
|
"Description": "PDF viewing and annotation app, often focused on pen input"
|
||||||
|
},
|
||||||
|
"Duolingo-LearnLanguagesforFree": {
|
||||||
|
"FriendlyName": "Duolingo",
|
||||||
|
"Description": "Language learning app"
|
||||||
|
},
|
||||||
|
"EclipseManager": {
|
||||||
|
"FriendlyName": "Eclipse Manager",
|
||||||
|
"Description": "Often related to specific OEM software or utilities (e.g. for managing screen settings)"
|
||||||
|
},
|
||||||
|
"FACEBOOK.FACEBOOK": {
|
||||||
|
"FriendlyName": "Facebook",
|
||||||
|
"Description": "Facebook social media app"
|
||||||
|
},
|
||||||
|
"FarmVille2CountryEscape": {
|
||||||
|
"FriendlyName": "FarmVille 2",
|
||||||
|
"Description": "Farming simulation game"
|
||||||
|
},
|
||||||
|
"Flipboard": {
|
||||||
|
"FriendlyName": "Flipboard",
|
||||||
|
"Description": "News and social network aggregator styled as a magazine"
|
||||||
|
},
|
||||||
|
"HiddenCity": {
|
||||||
|
"FriendlyName": "Hidden City",
|
||||||
|
"Description": "Hidden object puzzle adventure game"
|
||||||
|
},
|
||||||
|
"HULULLC.HULUPLUS": {
|
||||||
|
"FriendlyName": "Hulu",
|
||||||
|
"Description": "Hulu streaming service app"
|
||||||
|
},
|
||||||
|
"iHeartRadio": {
|
||||||
|
"FriendlyName": "iHeartRadio",
|
||||||
|
"Description": "Internet radio streaming app"
|
||||||
|
},
|
||||||
|
"Facebook.Instagram": {
|
||||||
|
"FriendlyName": "Instagram",
|
||||||
|
"Description": "Instagram social media app"
|
||||||
|
},
|
||||||
|
"king.com.BubbleWitch3Saga": {
|
||||||
|
"FriendlyName": "Bubble Witch 3",
|
||||||
|
"Description": "Puzzle game from King"
|
||||||
|
},
|
||||||
|
"king.com.CandyCrushSaga": {
|
||||||
|
"FriendlyName": "Candy Crush Saga",
|
||||||
|
"Description": "Puzzle game from King"
|
||||||
|
},
|
||||||
|
"king.com.CandyCrushSodaSaga": {
|
||||||
|
"FriendlyName": "Candy Crush Soda",
|
||||||
|
"Description": "Puzzle game from King"
|
||||||
|
},
|
||||||
|
"LinkedInforWindows": {
|
||||||
|
"FriendlyName": "LinkedIn",
|
||||||
|
"Description": "LinkedIn professional networking app"
|
||||||
|
},
|
||||||
|
"MarchofEmpires": {
|
||||||
|
"FriendlyName": "March of Empires",
|
||||||
|
"Description": "Strategy game"
|
||||||
|
},
|
||||||
|
"4DF9E0F8.Netflix": {
|
||||||
|
"FriendlyName": "Netflix",
|
||||||
|
"Description": "Netflix streaming service app"
|
||||||
|
},
|
||||||
|
"NYTCrossword": {
|
||||||
|
"FriendlyName": "NYT Crossword",
|
||||||
|
"Description": "New York Times crossword puzzle app"
|
||||||
|
},
|
||||||
|
"OneCalendar": {
|
||||||
|
"FriendlyName": "One Calendar",
|
||||||
|
"Description": "Calendar aggregation app"
|
||||||
|
},
|
||||||
|
"PandoraMediaInc": {
|
||||||
|
"FriendlyName": "Pandora",
|
||||||
|
"Description": "Pandora music streaming app"
|
||||||
|
},
|
||||||
|
"PhototasticCollage": {
|
||||||
|
"FriendlyName": "Phototastic Collage",
|
||||||
|
"Description": "Photo collage creation app"
|
||||||
|
},
|
||||||
|
"PicsArt-PhotoStudio": {
|
||||||
|
"FriendlyName": "PicsArt",
|
||||||
|
"Description": "Photo editing and creative app"
|
||||||
|
},
|
||||||
|
"PolarrPhotoEditorAcademicEdition": {
|
||||||
|
"FriendlyName": "Polarr Photo Editor",
|
||||||
|
"Description": "Photo editing app (Academic Edition)"
|
||||||
|
},
|
||||||
|
"flaregamesGmbH.RoyalRevolt": {
|
||||||
|
"FriendlyName": "Royal Revolt",
|
||||||
|
"Description": "Tower defense / strategy game"
|
||||||
|
},
|
||||||
|
"Sidia.LiveWallpaper": {
|
||||||
|
"FriendlyName": "Live Wallpaper",
|
||||||
|
"Description": "Live wallpaper app"
|
||||||
|
},
|
||||||
|
"SlingTV": {
|
||||||
|
"FriendlyName": "Sling TV",
|
||||||
|
"Description": "Live TV streaming service app"
|
||||||
|
},
|
||||||
|
"SpotifyAB.SpotifyMusic": {
|
||||||
|
"FriendlyName": "Spotify",
|
||||||
|
"Description": "Spotify music streaming app"
|
||||||
|
},
|
||||||
|
"BytedancePte.Ltd.TikTok": {
|
||||||
|
"FriendlyName": "TikTok",
|
||||||
|
"Description": "TikTok short-form video app"
|
||||||
|
},
|
||||||
|
"TuneInRadio": {
|
||||||
|
"FriendlyName": "TuneIn Radio",
|
||||||
|
"Description": "Internet radio streaming app"
|
||||||
|
},
|
||||||
|
"WinZipUniversal": {
|
||||||
|
"FriendlyName": "WinZip",
|
||||||
|
"Description": "File compression and extraction utility (Universal Windows Platform version)"
|
||||||
|
},
|
||||||
|
"Microsoft.BingSearch": {
|
||||||
|
"FriendlyName": "Bing Search",
|
||||||
|
"Description": "Web Search from Microsoft Bing (Integrates into Windows Search)"
|
||||||
|
},
|
||||||
|
"Microsoft.Edge": {
|
||||||
|
"FriendlyName": "Microsoft Edge",
|
||||||
|
"Description": "Windows' default browser, WARNING: Removing this app also removes the only browser from Windows Sandbox and could affect other apps"
|
||||||
|
},
|
||||||
|
"Microsoft.GamingApp": {
|
||||||
|
"FriendlyName": "Xbox Gaming App",
|
||||||
|
"Description": "Modern Xbox Gaming App, required for installing some PC games"
|
||||||
|
},
|
||||||
|
"Microsoft.GetHelp": {
|
||||||
|
"FriendlyName": "Get Help",
|
||||||
|
"Description": "Required for some Windows 11 Troubleshooters and support interactions"
|
||||||
|
},
|
||||||
|
"Microsoft.M365Companions": {
|
||||||
|
"FriendlyName": "Microsoft 365 Companions",
|
||||||
|
"Description": "Microsoft 365 (Business) Calendar, Files and People mini-apps, these apps may be reinstalled if enabled by your Microsoft 365 admin"
|
||||||
|
},
|
||||||
|
"Microsoft.MSPaint": {
|
||||||
|
"FriendlyName": "Paint 3D",
|
||||||
|
"Description": "Paint 3D (Modern paint application with 3D features)"
|
||||||
|
},
|
||||||
|
"Microsoft.OneDrive": {
|
||||||
|
"FriendlyName": "OneDrive",
|
||||||
|
"Description": "OneDrive consumer cloud storage client"
|
||||||
|
},
|
||||||
|
"Microsoft.OutlookForWindows": {
|
||||||
|
"FriendlyName": "Outlook for Windows",
|
||||||
|
"Description": "New Outlook for Windows mail client"
|
||||||
|
},
|
||||||
|
"Microsoft.Paint": {
|
||||||
|
"FriendlyName": "Paint",
|
||||||
|
"Description": "Classic Paint (Traditional 2D paint application)"
|
||||||
|
},
|
||||||
|
"Microsoft.People": {
|
||||||
|
"FriendlyName": "People",
|
||||||
|
"Description": "Required for & included with Mail & Calendar (discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.RemoteDesktop": {
|
||||||
|
"FriendlyName": "Remote Desktop",
|
||||||
|
"Description": "Remote Desktop client app"
|
||||||
|
},
|
||||||
|
"Microsoft.ScreenSketch": {
|
||||||
|
"FriendlyName": "Snipping Tool",
|
||||||
|
"Description": "Snipping Tool (Screenshot and annotation tool)"
|
||||||
|
},
|
||||||
|
"Microsoft.StartExperiencesApp": {
|
||||||
|
"FriendlyName": "Widgets Experience",
|
||||||
|
"Description": "This app powers Windows Widgets My Feed"
|
||||||
|
},
|
||||||
|
"Microsoft.Whiteboard": {
|
||||||
|
"FriendlyName": "Whiteboard",
|
||||||
|
"Description": "Digital collaborative whiteboard app"
|
||||||
|
},
|
||||||
|
"Microsoft.Windows.Photos": {
|
||||||
|
"FriendlyName": "Photos",
|
||||||
|
"Description": "Default photo viewing and basic editing app"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsCalculator": {
|
||||||
|
"FriendlyName": "Calculator",
|
||||||
|
"Description": "Calculator app"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsCamera": {
|
||||||
|
"FriendlyName": "Camera",
|
||||||
|
"Description": "Camera app for using built-in or connected cameras"
|
||||||
|
},
|
||||||
|
"Microsoft.windowscommunicationsapps": {
|
||||||
|
"FriendlyName": "Mail & Calendar",
|
||||||
|
"Description": "Mail & Calendar app suite (Discontinued)"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsNotepad": {
|
||||||
|
"FriendlyName": "Notepad",
|
||||||
|
"Description": "Notepad text editor app"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsStore": {
|
||||||
|
"FriendlyName": "Microsoft Store",
|
||||||
|
"Description": "Microsoft Store, WARNING: This app cannot be reinstalled easily if removed!"
|
||||||
|
},
|
||||||
|
"Microsoft.WindowsTerminal": {
|
||||||
|
"FriendlyName": "Windows Terminal",
|
||||||
|
"Description": "Default terminal app in windows 11 (Command Prompt, PowerShell, WSL), WARNING: Do not remove if you launched Win11Debloat from Windows Terminal, as this will cause the script to fail."
|
||||||
|
},
|
||||||
|
"Microsoft.Xbox.TCUI": {
|
||||||
|
"FriendlyName": "Xbox TCUI Framework",
|
||||||
|
"Description": "UI framework, seems to be required for Microsoft Store, photos and certain games"
|
||||||
|
},
|
||||||
|
"Microsoft.XboxGameOverlay": {
|
||||||
|
"FriendlyName": "Xbox Game Overlay",
|
||||||
|
"Description": "Game overlay, required/useful for some games (Part of Xbox Game Bar)"
|
||||||
|
},
|
||||||
|
"Microsoft.XboxGamingOverlay": {
|
||||||
|
"FriendlyName": "Xbox Gaming Overlay",
|
||||||
|
"Description": "Game overlay, required/useful for some games (Part of Xbox Game Bar)"
|
||||||
|
},
|
||||||
|
"Microsoft.XboxIdentityProvider": {
|
||||||
|
"FriendlyName": "Xbox Identity Provider",
|
||||||
|
"Description": "Xbox sign-in framework, required for some games and Xbox services"
|
||||||
|
},
|
||||||
|
"Microsoft.XboxSpeechToTextOverlay": {
|
||||||
|
"FriendlyName": "Xbox Speech To Text",
|
||||||
|
"Description": "Accessibility feature required for some games, WARNING: This app cannot be reinstalled easily!"
|
||||||
|
},
|
||||||
|
"Microsoft.YourPhone": {
|
||||||
|
"FriendlyName": "Phone Link",
|
||||||
|
"Description": "Phone link (Connects Android/iOS phone to PC)"
|
||||||
|
},
|
||||||
|
"Microsoft.ZuneMusic": {
|
||||||
|
"FriendlyName": "Media Player",
|
||||||
|
"Description": "Modern Media Player (Replaced Groove Music, plays local audio/video)"
|
||||||
|
},
|
||||||
|
"MicrosoftWindows.CrossDevice": {
|
||||||
|
"FriendlyName": "Cross Device Experience",
|
||||||
|
"Description": "Phone integration within File Explorer, Camera and more (Part of Phone Link features)"
|
||||||
|
},
|
||||||
|
"MicrosoftWindows.Client.WebExperience": {
|
||||||
|
"FriendlyName": "Windows Web Experience Pack",
|
||||||
|
"Description": "Helps deliver and update certain features, like Widgets, through the Microsoft Store"
|
||||||
|
},
|
||||||
|
"Microsoft.WidgetsPlatformRuntime": {
|
||||||
|
"FriendlyName": "Widgets Platform Runtime",
|
||||||
|
"Description": "Runtime required for Windows Widgets to function"
|
||||||
|
},
|
||||||
|
"LGElectronics.LGMonitorApp": {
|
||||||
|
"FriendlyName": "LG Monitor App",
|
||||||
|
"Description": "LG OEM software for controlling your LG monitor, Windows Update may silently reinstall this app if you have an LG monitor connected"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPAIExperienceCenter": {
|
||||||
|
"FriendlyName": "HP AI Experience Center",
|
||||||
|
"Description": "HP OEM software, AI-enhanced features and support"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPConnectedMusic": {
|
||||||
|
"FriendlyName": "HP Connected Music",
|
||||||
|
"Description": "HP OEM software for music (Potentially discontinued)"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPConnectedPhotopoweredbySnapfish": {
|
||||||
|
"FriendlyName": "HP Connected Photo",
|
||||||
|
"Description": "HP OEM software for photos, integrated with Snapfish (Potentially discontinued)"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPDesktopSupportUtilities": {
|
||||||
|
"FriendlyName": "HP Desktop Support Utilities",
|
||||||
|
"Description": "HP OEM software providing desktop support tools"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPEasyClean": {
|
||||||
|
"FriendlyName": "HP Easy Clean",
|
||||||
|
"Description": "HP OEM software for system cleaning or optimization"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPFileViewer": {
|
||||||
|
"FriendlyName": "HP File Viewer",
|
||||||
|
"Description": "HP OEM software for viewing specific file types"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPJumpStarts": {
|
||||||
|
"FriendlyName": "HP JumpStarts",
|
||||||
|
"Description": "HP OEM software for tutorials, app discovery, or quick access to HP features"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPPCHardwareDiagnosticsWindows": {
|
||||||
|
"FriendlyName": "HP PC Hardware Diagnostics",
|
||||||
|
"Description": "HP OEM software for PC hardware diagnostics"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPPowerManager": {
|
||||||
|
"FriendlyName": "HP Power Manager",
|
||||||
|
"Description": "HP OEM software for managing power settings and battery"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPPrinterControl": {
|
||||||
|
"FriendlyName": "HP Printer Control",
|
||||||
|
"Description": "HP OEM software for managing HP printers"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPPrivacySettings": {
|
||||||
|
"FriendlyName": "HP Privacy Settings",
|
||||||
|
"Description": "HP OEM software for managing privacy settings"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPQuickDrop": {
|
||||||
|
"FriendlyName": "HP QuickDrop",
|
||||||
|
"Description": "HP OEM software for quick file transfer between devices"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPQuickTouch": {
|
||||||
|
"FriendlyName": "HP QuickTouch",
|
||||||
|
"Description": "HP OEM software, possibly for touch-specific shortcuts or controls"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPRegistration": {
|
||||||
|
"FriendlyName": "HP Registration",
|
||||||
|
"Description": "HP OEM software for product registration"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPSupportAssistant": {
|
||||||
|
"FriendlyName": "HP Support Assistant",
|
||||||
|
"Description": "HP OEM software for support, updates, and troubleshooting"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPSureShieldAI": {
|
||||||
|
"FriendlyName": "HP Sure Shield AI",
|
||||||
|
"Description": "HP OEM security software, likely AI-based threat protection"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPSystemInformation": {
|
||||||
|
"FriendlyName": "HP System Information",
|
||||||
|
"Description": "HP OEM software for displaying system information"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPWelcome": {
|
||||||
|
"FriendlyName": "HP Welcome",
|
||||||
|
"Description": "HP OEM software providing a welcome experience or initial setup help"
|
||||||
|
},
|
||||||
|
"AD2F1837.HPWorkWell": {
|
||||||
|
"FriendlyName": "HP WorkWell",
|
||||||
|
"Description": "HP OEM software focused on well-being, possibly with break reminders or ergonomic tips"
|
||||||
|
},
|
||||||
|
"AD2F1837.myHP": {
|
||||||
|
"FriendlyName": "myHP",
|
||||||
|
"Description": "HP OEM central hub app for device info, support, and services"
|
||||||
|
},
|
||||||
|
"E046963F.LenovoCompanion": {
|
||||||
|
"FriendlyName": "Lenovo Vantage",
|
||||||
|
"Description": "Lenovo OEM hub app for device settings, updates, and support"
|
||||||
|
},
|
||||||
|
"LenovoCompanyLimited.LenovoVantageService": {
|
||||||
|
"FriendlyName": "Lenovo Vantage Service",
|
||||||
|
"Description": "Background service component for Lenovo Vantage"
|
||||||
|
},
|
||||||
|
"DellInc.DellSupportAssistforPCs": {
|
||||||
|
"FriendlyName": "Dell SupportAssist",
|
||||||
|
"Description": "Dell OEM support, diagnostic, and update tool"
|
||||||
|
},
|
||||||
|
"DellInc.DellDigitalDelivery": {
|
||||||
|
"FriendlyName": "Dell Digital Delivery Services",
|
||||||
|
"Description": "Dell OEM software for delivering pre-purchased software"
|
||||||
|
},
|
||||||
|
"DellInc.DellMobileConnect": {
|
||||||
|
"FriendlyName": "Dell Mobile Connect",
|
||||||
|
"Description": "Dell OEM app for linking Android/iOS phone to PC (superseded by Phone Link)"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,8 +70,8 @@ function Import-AppDetailsFromJson {
|
|||||||
# Use first AppId for fallback names, join all for display
|
# Use first AppId for fallback names, join all for display
|
||||||
$primaryAppId = $appIdArray[0]
|
$primaryAppId = $appIdArray[0]
|
||||||
$appIdDisplay = $appIdArray -join ', '
|
$appIdDisplay = $appIdArray -join ', '
|
||||||
$friendlyName = if ($appData.FriendlyName) { $appData.FriendlyName } else { $primaryAppId }
|
$friendlyName = Get-Translation -Key $primaryAppId -Field 'FriendlyName' -Section 'Apps'
|
||||||
$displayName = if ($appData.FriendlyName) { "$($appData.FriendlyName) ($appIdDisplay)" } else { $appIdDisplay }
|
$displayName = "$friendlyName ($appIdDisplay)"
|
||||||
$isChecked = if ($InitialCheckedFromJson) { $appData.SelectedByDefault } else { $false }
|
$isChecked = if ($InitialCheckedFromJson) { $appData.SelectedByDefault } else { $false }
|
||||||
|
|
||||||
$apps += [PSCustomObject]@{
|
$apps += [PSCustomObject]@{
|
||||||
@@ -80,7 +80,7 @@ function Import-AppDetailsFromJson {
|
|||||||
FriendlyName = $friendlyName
|
FriendlyName = $friendlyName
|
||||||
DisplayName = $displayName
|
DisplayName = $displayName
|
||||||
IsChecked = $isChecked
|
IsChecked = $isChecked
|
||||||
Description = $appData.Description
|
Description = Get-Translation -Key $primaryAppId -Field 'Description' -Section 'Apps'
|
||||||
SelectedByDefault = $appData.SelectedByDefault
|
SelectedByDefault = $appData.SelectedByDefault
|
||||||
Recommendation = $appData.Recommendation
|
Recommendation = $appData.Recommendation
|
||||||
RemovalMethod = if ($appData.RemovalMethod -and $appData.RemovalMethod -eq 'WinGet') { 'WinGet' } else { 'Appx' }
|
RemovalMethod = if ($appData.RemovalMethod -and $appData.RemovalMethod -eq 'WinGet') { 'WinGet' } else { 'Appx' }
|
||||||
@@ -89,3 +89,51 @@ function Import-AppDetailsFromJson {
|
|||||||
|
|
||||||
return $apps
|
return $apps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Runs Import-AppDetailsFromJson in a background runspace via Invoke-NonBlocking.
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
The runspace inherits neither dot-sourced functions nor script-scoped variables, so
|
||||||
|
this dot-sources the app loader, its winget helper, and the language loader inside the
|
||||||
|
scriptblock, and passes $Lang through to be reassigned to $script:Lang there.
|
||||||
|
|
||||||
|
.PARAMETER OnlyInstalled
|
||||||
|
Filters the results to applications detected through Appx or the supplied
|
||||||
|
winget installation list.
|
||||||
|
|
||||||
|
.PARAMETER InstalledList
|
||||||
|
A pre-fetched winget installation list used when filtering installed apps.
|
||||||
|
|
||||||
|
.PARAMETER InitialCheckedFromJson
|
||||||
|
Sets each returned app's IsChecked value from its SelectedByDefault setting.
|
||||||
|
|
||||||
|
.PARAMETER Lang
|
||||||
|
The loaded language object ($script:Lang) to make available inside the runspace.
|
||||||
|
#>
|
||||||
|
function Invoke-AppDetailsFromJsonAsync {
|
||||||
|
param (
|
||||||
|
[string]$LoaderScriptPath = $script:LoadAppsDetailsScriptPath,
|
||||||
|
[string]$HelperScriptPath = $script:TestAppInWingetListScriptPath,
|
||||||
|
[string]$LanguageFileScriptPath = $script:ImportLanguageFileScriptPath,
|
||||||
|
[string]$AppsFilePath = $script:AppsListFilePath,
|
||||||
|
[object[]]$InstalledList = $null,
|
||||||
|
[switch]$OnlyInstalled,
|
||||||
|
[switch]$InitialCheckedFromJson,
|
||||||
|
[object]$Lang = $script:Lang
|
||||||
|
)
|
||||||
|
|
||||||
|
$onlyInstalledValue = [bool]$OnlyInstalled
|
||||||
|
$initialCheckedFromJsonValue = [bool]$InitialCheckedFromJson
|
||||||
|
|
||||||
|
return Invoke-NonBlocking -ScriptBlock {
|
||||||
|
param($loaderScript, $helperScript, $languageFileScript, $appsListFilePath, $installedList, $onlyInstalled, $initialCheckedFromJson, $Lang)
|
||||||
|
$script:AppsListFilePath = $appsListFilePath
|
||||||
|
$script:Lang = $Lang
|
||||||
|
. $helperScript
|
||||||
|
. $languageFileScript
|
||||||
|
. $loaderScript
|
||||||
|
Import-AppDetailsFromJson -OnlyInstalled:$onlyInstalled -InstalledList $installedList -InitialCheckedFromJson:$initialCheckedFromJson
|
||||||
|
} -ArgumentList $LoaderScriptPath, $HelperScriptPath, $LanguageFileScriptPath, $AppsFilePath, $InstalledList, $onlyInstalledValue, $initialCheckedFromJsonValue, $Lang
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ function Resolve-LanguageFolder {
|
|||||||
|
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Loads Chrome/Features/Categories JSON for a language folder, or returns $null on failure.
|
Loads Chrome/Features/Categories/Apps JSON for a language folder, or returns $null on failure.
|
||||||
#>
|
#>
|
||||||
function Import-LanguageContent {
|
function Import-LanguageContent {
|
||||||
param(
|
param(
|
||||||
@@ -38,8 +38,9 @@ function Import-LanguageContent {
|
|||||||
$chrome = Import-JsonFile -filePath (Join-Path $folderPath 'Chrome.json')
|
$chrome = Import-JsonFile -filePath (Join-Path $folderPath 'Chrome.json')
|
||||||
$features = Import-JsonFile -filePath (Join-Path $folderPath 'Features.json')
|
$features = Import-JsonFile -filePath (Join-Path $folderPath 'Features.json')
|
||||||
$categories = Import-JsonFile -filePath (Join-Path $folderPath 'Categories.json')
|
$categories = Import-JsonFile -filePath (Join-Path $folderPath 'Categories.json')
|
||||||
|
$apps = Import-JsonFile -filePath (Join-Path $folderPath 'Apps.json')
|
||||||
|
|
||||||
if (-not $chrome -or -not $features -or -not $categories) {
|
if (-not $chrome -or -not $features -or -not $categories -or -not $apps) {
|
||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ function Import-LanguageContent {
|
|||||||
Features = $features.Features
|
Features = $features.Features
|
||||||
UiGroups = $features.UiGroups
|
UiGroups = $features.UiGroups
|
||||||
Categories = $categories
|
Categories = $categories
|
||||||
|
Apps = $apps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +130,7 @@ function Get-LanguageFallbackChain {
|
|||||||
|
|
||||||
<#
|
<#
|
||||||
.SYNOPSIS
|
.SYNOPSIS
|
||||||
Finds the named section object (Chrome, Features, UiGroups, or Categories) that owns a key.
|
Finds the named section object (Chrome, Features, UiGroups, Categories, or Apps) that owns a key.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
A FeatureId, GroupId, and CategoryId aren't guaranteed to be disjoint (Config/Features.json
|
A FeatureId, GroupId, and CategoryId aren't guaranteed to be disjoint (Config/Features.json
|
||||||
@@ -142,7 +144,7 @@ function Find-TranslationSection {
|
|||||||
[object]$Lang,
|
[object]$Lang,
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
[string]$Key,
|
[string]$Key,
|
||||||
[ValidateSet('', 'Chrome', 'Features', 'UiGroups', 'Categories')]
|
[ValidateSet('', 'Chrome', 'Features', 'UiGroups', 'Categories', 'Apps')]
|
||||||
[string]$Section = ''
|
[string]$Section = ''
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -154,7 +156,7 @@ function Find-TranslationSection {
|
|||||||
return $null
|
return $null
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($sectionName in 'Chrome', 'Features', 'UiGroups', 'Categories') {
|
foreach ($sectionName in 'Chrome', 'Features', 'UiGroups', 'Categories', 'Apps') {
|
||||||
$sectionObject = $Lang.$sectionName
|
$sectionObject = $Lang.$sectionName
|
||||||
if ($sectionObject -and $sectionObject.PSObject.Properties[$Key]) {
|
if ($sectionObject -and $sectionObject.PSObject.Properties[$Key]) {
|
||||||
return $sectionObject
|
return $sectionObject
|
||||||
@@ -169,14 +171,15 @@ function Find-TranslationSection {
|
|||||||
Looks up a translated value from the active language, falling back to en-US, then to the key itself.
|
Looks up a translated value from the active language, falling back to en-US, then to the key itself.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Chrome.json keys are flat strings, so -Field is omitted for those. Features/UiGroups/Categories
|
Chrome.json keys are flat strings, so -Field is omitted for those. Features/UiGroups/Categories/Apps
|
||||||
keys (FeatureId/GroupId/CategoryId) resolve to an object, so -Field picks the property on it
|
keys (FeatureId/GroupId/CategoryId/AppId) resolve to an object, so -Field picks the property on it
|
||||||
(Label, ToolTip, ApplyText, UndoLabel, ApplyUndoText). One generic lookup covers every section
|
(Label, ToolTip, ApplyText, UndoLabel, ApplyUndoText for Features/UiGroups/Categories;
|
||||||
instead of a separate function per section.
|
FriendlyName, Description for Apps). One generic lookup covers every section instead of a
|
||||||
|
separate function per section.
|
||||||
|
|
||||||
A FeatureId and a GroupId aren't guaranteed to be distinct strings, so pass -Section
|
A FeatureId and a GroupId aren't guaranteed to be distinct strings, so pass -Section
|
||||||
('Features', 'UiGroups', or 'Categories') whenever the caller knows which one it means,
|
('Features', 'UiGroups', 'Categories', or 'Apps') whenever the caller knows which one it
|
||||||
rather than relying on Find-TranslationSection's search order to guess correctly.
|
means, rather than relying on Find-TranslationSection's search order to guess correctly.
|
||||||
|
|
||||||
When -Count is supplied, tries the plural-suffixed key ("$Key`_$category") before the bare key,
|
When -Count is supplied, tries the plural-suffixed key ("$Key`_$category") before the bare key,
|
||||||
so callers don't need to add a plural variant for every string, only the ones that need one.
|
so callers don't need to add a plural variant for every string, only the ones that need one.
|
||||||
@@ -191,7 +194,7 @@ function Get-Translation {
|
|||||||
[object]$Lang = $script:Lang,
|
[object]$Lang = $script:Lang,
|
||||||
[Nullable[int]]$Count = $null,
|
[Nullable[int]]$Count = $null,
|
||||||
[object[]]$FormatArgs = $null,
|
[object[]]$FormatArgs = $null,
|
||||||
[ValidateSet('', 'Chrome', 'Features', 'UiGroups', 'Categories')]
|
[ValidateSet('', 'Chrome', 'Features', 'UiGroups', 'Categories', 'Apps')]
|
||||||
[string]$Section = ''
|
[string]$Section = ''
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -282,7 +285,7 @@ function Get-GroupValueTranslation {
|
|||||||
Flattens a loaded language object into a sorted set of dotted key paths.
|
Flattens a loaded language object into a sorted set of dotted key paths.
|
||||||
|
|
||||||
.DESCRIPTION
|
.DESCRIPTION
|
||||||
Chrome.json keys are already flat and are used as-is. Features/UiGroups/Categories
|
Chrome.json keys are already flat and are used as-is. Features/UiGroups/Categories/Apps
|
||||||
keys are one level deeper (EntryId -> {Field: value}), so each field becomes its own
|
keys are one level deeper (EntryId -> {Field: value}), so each field becomes its own
|
||||||
"Section.EntryId.Field" path (e.g. "Features.DisableTelemetry.Label"). UiGroups' nested
|
"Section.EntryId.Field" path (e.g. "Features.DisableTelemetry.Label"). UiGroups' nested
|
||||||
Values map becomes "UiGroups.GroupId.Values.FeatureId". Used by Test-LanguageKeyCoverage
|
Values map becomes "UiGroups.GroupId.Values.FeatureId". Used by Test-LanguageKeyCoverage
|
||||||
@@ -301,7 +304,7 @@ function Get-LanguageKeyPaths {
|
|||||||
$paths.Add($chromeKey)
|
$paths.Add($chromeKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($sectionName in 'Features', 'Categories') {
|
foreach ($sectionName in 'Features', 'Categories', 'Apps') {
|
||||||
$section = $Lang.$sectionName
|
$section = $Lang.$sectionName
|
||||||
if (-not $section) { continue }
|
if (-not $section) { continue }
|
||||||
|
|
||||||
|
|||||||
@@ -391,27 +391,15 @@ function Add-AppsToMainWindow {
|
|||||||
|
|
||||||
$script:MainWindowLastSelectedCheckbox = $null
|
$script:MainWindowLastSelectedCheckbox = $null
|
||||||
|
|
||||||
$loaderScriptPath = $script:LoadAppsDetailsScriptPath
|
|
||||||
$helperScriptPath = $script:TestAppInWingetListScriptPath
|
|
||||||
$appsFilePath = $script:AppsListFilePath
|
|
||||||
$onlyInstalled = [bool]$OnlyInstalledAppsBox.IsChecked
|
$onlyInstalled = [bool]$OnlyInstalledAppsBox.IsChecked
|
||||||
|
|
||||||
# Use preloaded data if available; otherwise load in background job
|
# Use preloaded data if available; otherwise load in a background job to keep the UI responsive.
|
||||||
if (-not $onlyInstalled -and $script:PreloadedAppData) {
|
if (-not $onlyInstalled -and $script:PreloadedAppData) {
|
||||||
$rawAppData = $script:PreloadedAppData
|
$rawAppData = $script:PreloadedAppData
|
||||||
$script:PreloadedAppData = $null
|
$script:PreloadedAppData = $null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
# Load apps details in a background job to keep the UI responsive.
|
$rawAppData = Invoke-AppDetailsFromJsonAsync -OnlyInstalled:$onlyInstalled -InstalledList $ListOfApps
|
||||||
# The helper is dot-sourced inside the job because the runspace
|
|
||||||
# does not inherit the parent scope's dot-sourced functions.
|
|
||||||
$rawAppData = Invoke-NonBlocking -ScriptBlock {
|
|
||||||
param($loaderScript, $helperScript, $appsListFilePath, $installedList, $onlyInstalled)
|
|
||||||
$script:AppsListFilePath = $appsListFilePath
|
|
||||||
. $helperScript
|
|
||||||
. $loaderScript
|
|
||||||
Import-AppDetailsFromJson -OnlyInstalled:$onlyInstalled -InstalledList $installedList -InitialCheckedFromJson:$false
|
|
||||||
} -ArgumentList $loaderScriptPath, $helperScriptPath, $appsFilePath, $ListOfApps, $onlyInstalled
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$appsToAdd = @($rawAppData | Where-Object { $_ -and ($_.AppId -or $_.FriendlyName) } | Sort-Object -Property FriendlyName)
|
$appsToAdd = @($rawAppData | Where-Object { $_ -and ($_.AppId -or $_.FriendlyName) } | Sort-Object -Property FriendlyName)
|
||||||
|
|||||||
@@ -16,13 +16,14 @@ Describe 'Resolve-LanguageFolder' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Describe 'Import-LanguageFile' {
|
Describe 'Import-LanguageFile' {
|
||||||
It 'loads all three JSON files for the resolved language' {
|
It 'loads all four JSON files for the resolved language' {
|
||||||
$lang = Import-LanguageFile -LanguageCode 'en-US'
|
$lang = Import-LanguageFile -LanguageCode 'en-US'
|
||||||
|
|
||||||
$lang.LanguageCode | Should -Be 'en-US'
|
$lang.LanguageCode | Should -Be 'en-US'
|
||||||
$lang.Chrome.TitleBarClose | Should -Be 'Close'
|
$lang.Chrome.TitleBarClose | Should -Be 'Close'
|
||||||
$lang.Features.DisableTelemetry.Label | Should -Be 'Disable telemetry'
|
$lang.Features.DisableTelemetry.Label | Should -Be 'Disable telemetry'
|
||||||
$lang.Categories.PrivacySuggestedContent.Label | Should -Be 'Privacy & Suggested Content'
|
$lang.Categories.PrivacySuggestedContent.Label | Should -Be 'Privacy & Suggested Content'
|
||||||
|
$lang.Apps.'TestApp.One'.FriendlyName | Should -Be 'Test App'
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'attaches an en-US Fallback when a non-en-US language is loaded' {
|
It 'attaches an en-US Fallback when a non-en-US language is loaded' {
|
||||||
@@ -124,6 +125,11 @@ Describe 'Get-Translation' {
|
|||||||
Get-Translation -Key 'PrivacySuggestedContent' -Field 'Label' -Lang $script:EnLang | Should -Be 'Privacy & Suggested Content'
|
Get-Translation -Key 'PrivacySuggestedContent' -Field 'Label' -Lang $script:EnLang | Should -Be 'Privacy & Suggested Content'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It 'looks up a Field on an Apps entry' {
|
||||||
|
Get-Translation -Key 'TestApp.One' -Field 'FriendlyName' -Section 'Apps' -Lang $script:EnLang | Should -Be 'Test App'
|
||||||
|
Get-Translation -Key 'TestApp.One' -Field 'Description' -Section 'Apps' -Lang $script:EnLang | Should -Be 'A test app.'
|
||||||
|
}
|
||||||
|
|
||||||
It 'looks up a Field on a UiGroups entry' {
|
It 'looks up a Field on a UiGroups entry' {
|
||||||
Get-Translation -Key 'SearchIcon' -Field 'Label' -Lang $script:EnLang | Should -Be 'Taskbar search style'
|
Get-Translation -Key 'SearchIcon' -Field 'Label' -Lang $script:EnLang | Should -Be 'Taskbar search style'
|
||||||
}
|
}
|
||||||
@@ -199,6 +205,8 @@ Describe 'Test-LanguageKeyCoverage' {
|
|||||||
$coverage.MissingKeys | Should -Contain 'Features.DisableTelemetry.ToolTip'
|
$coverage.MissingKeys | Should -Contain 'Features.DisableTelemetry.ToolTip'
|
||||||
$coverage.MissingKeys | Should -Contain 'UiGroups.SearchIcon.Label'
|
$coverage.MissingKeys | Should -Contain 'UiGroups.SearchIcon.Label'
|
||||||
$coverage.MissingKeys | Should -Contain 'Categories.PrivacySuggestedContent.Label'
|
$coverage.MissingKeys | Should -Contain 'Categories.PrivacySuggestedContent.Label'
|
||||||
|
$coverage.MissingKeys | Should -Contain 'Apps.TestApp.One.FriendlyName'
|
||||||
|
$coverage.MissingKeys | Should -Contain 'Apps.TestApp.One.Description'
|
||||||
$coverage.ExtraKeys | Should -BeNullOrEmpty
|
$coverage.ExtraKeys | Should -BeNullOrEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
Add-Type -AssemblyName PresentationFramework
|
Add-Type -AssemblyName PresentationFramework
|
||||||
|
function Invoke-DoEvents {}
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-JsonFile.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-JsonFile.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-LanguageFile.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-LanguageFile.ps1')
|
||||||
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-AppDetailsFromJson.ps1')
|
||||||
|
. (Join-Path $PSScriptRoot '..\Scripts\Threading\Invoke-NonBlocking.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-AppSelection.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-AppSelection.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-Deployment.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-Deployment.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-Navigation.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\GUI\MainWindow-Navigation.ps1')
|
||||||
@@ -9,6 +12,10 @@ BeforeAll {
|
|||||||
. (Join-Path $PSScriptRoot '..\Scripts\GUI\Set-WindowThemeResources.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\GUI\Set-WindowThemeResources.ps1')
|
||||||
$script:LanguagesPath = Join-Path $PSScriptRoot '..\Config\Languages'
|
$script:LanguagesPath = Join-Path $PSScriptRoot '..\Config\Languages'
|
||||||
$script:Lang = Import-LanguageFile -LanguageCode 'en-US'
|
$script:Lang = Import-LanguageFile -LanguageCode 'en-US'
|
||||||
|
$script:LoadAppsDetailsScriptPath = Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-AppDetailsFromJson.ps1'
|
||||||
|
$script:TestAppInWingetListScriptPath = Join-Path $PSScriptRoot '..\Scripts\AppRemoval\Test-AppInWingetList.ps1'
|
||||||
|
$script:ImportLanguageFileScriptPath = Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-LanguageFile.ps1'
|
||||||
|
$script:AppsListFilePath = Join-Path $PSScriptRoot '..\Config\Apps.json'
|
||||||
|
|
||||||
function New-TestWindow {
|
function New-TestWindow {
|
||||||
$window = New-Object System.Windows.Window
|
$window = New-Object System.Windows.Window
|
||||||
@@ -19,6 +26,25 @@ BeforeAll {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Describe 'Invoke-AppDetailsFromJsonAsync' {
|
||||||
|
BeforeEach { $script:GuiWindow = [PSCustomObject]@{} }
|
||||||
|
|
||||||
|
It 'resolves translated FriendlyName and Description inside the background runspace' {
|
||||||
|
$result = @(Invoke-AppDetailsFromJsonAsync -OnlyInstalled:$false)
|
||||||
|
|
||||||
|
$result.Count | Should -Be 141
|
||||||
|
$clipchamp = $result | Where-Object { $_.AppId -contains 'Clipchamp.Clipchamp' }
|
||||||
|
$clipchamp.FriendlyName | Should -Be 'Clipchamp'
|
||||||
|
$clipchamp.Description | Should -Be 'Video editor from Microsoft'
|
||||||
|
}
|
||||||
|
|
||||||
|
It 'does not return null entries when OnlyInstalled filters the runspace results' {
|
||||||
|
$result = @(Invoke-AppDetailsFromJsonAsync -OnlyInstalled:$true -InstalledList @())
|
||||||
|
|
||||||
|
@($result | Where-Object { -not $_ }).Count | Should -Be 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Describe 'ConvertTo-NormalizedCheckboxState' {
|
Describe 'ConvertTo-NormalizedCheckboxState' {
|
||||||
It 'normalizes indeterminate tri-state checkboxes to checked' {
|
It 'normalizes indeterminate tri-state checkboxes to checked' {
|
||||||
$checkBox = New-Object System.Windows.Controls.CheckBox
|
$checkBox = New-Object System.Windows.Controls.CheckBox
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ BeforeAll {
|
|||||||
function Test-AppInWingetList { param($appId, $InstalledList) $false }
|
function Test-AppInWingetList { param($appId, $InstalledList) $false }
|
||||||
|
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-JsonFile.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-JsonFile.ps1')
|
||||||
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-LanguageFile.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Add-Parameter.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\Helpers\Add-Parameter.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Save-ToFile.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Save-ToFile.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-Settings.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-Settings.ps1')
|
||||||
@@ -12,6 +13,8 @@ BeforeAll {
|
|||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-AppPresetsFromJson.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Import-AppPresetsFromJson.ps1')
|
||||||
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Get-ValidatedAppList.ps1')
|
. (Join-Path $PSScriptRoot '..\Scripts\FileIO\Get-ValidatedAppList.ps1')
|
||||||
$script:JsonFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading'
|
$script:JsonFixturePath = Join-Path $PSScriptRoot 'TestData\JsonFileLoading'
|
||||||
|
$script:LanguagesPath = Join-Path $PSScriptRoot '..\Config\Languages'
|
||||||
|
$script:Lang = Import-LanguageFile -LanguageCode 'en-US'
|
||||||
}
|
}
|
||||||
|
|
||||||
Describe 'Save-ToFile' {
|
Describe 'Save-ToFile' {
|
||||||
@@ -150,7 +153,8 @@ Describe 'Import-AppDetailsFromJson' {
|
|||||||
$apps = @(Import-AppDetailsFromJson -InitialCheckedFromJson)
|
$apps = @(Import-AppDetailsFromJson -InitialCheckedFromJson)
|
||||||
|
|
||||||
$apps | Should -HaveCount 2
|
$apps | Should -HaveCount 2
|
||||||
$apps[0].DisplayName | Should -Be 'One (One.App, Alias.App)'
|
# 'One.App' has no en-US Apps.json entry, so Get-Translation falls back to the raw key.
|
||||||
|
$apps[0].DisplayName | Should -Be 'One.App (One.App, Alias.App)'
|
||||||
$apps[0].IsChecked | Should -BeTrue
|
$apps[0].IsChecked | Should -BeTrue
|
||||||
$apps[0].RemovalMethod | Should -Be 'WinGet'
|
$apps[0].RemovalMethod | Should -Be 'WinGet'
|
||||||
$apps[1].FriendlyName | Should -Be 'Two.App'
|
$apps[1].FriendlyName | Should -Be 'Two.App'
|
||||||
@@ -159,6 +163,18 @@ Describe 'Import-AppDetailsFromJson' {
|
|||||||
@($apps[1].AppId) | Should -HaveCount 1
|
@($apps[1].AppId) | Should -HaveCount 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
It 'resolves FriendlyName and Description from Config/Languages/en-US/Apps.json for a real AppId' {
|
||||||
|
'{"Apps":[{"AppId":"Clipchamp.Clipchamp","FriendlyName":"stale JSON name, should not appear","Description":"stale JSON description, should not appear"}]}' |
|
||||||
|
Set-Content -LiteralPath $script:AppsListFilePath -Encoding UTF8
|
||||||
|
|
||||||
|
$apps = @(Import-AppDetailsFromJson)
|
||||||
|
|
||||||
|
$apps | Should -HaveCount 1
|
||||||
|
$apps[0].FriendlyName | Should -Be 'Clipchamp'
|
||||||
|
$apps[0].Description | Should -Be 'Video editor from Microsoft'
|
||||||
|
$apps[0].DisplayName | Should -Be 'Clipchamp (Clipchamp.Clipchamp)'
|
||||||
|
}
|
||||||
|
|
||||||
It 'skips missing, blank, and non-string app IDs without failing the complete catalog' {
|
It 'skips missing, blank, and non-string app IDs without failing the complete catalog' {
|
||||||
'{"Apps":[{"AppId":null},{"FriendlyName":"Missing"},{"AppId":42},{"AppId":[" Valid.App ",null,{},""]}]}' |
|
'{"Apps":[{"AppId":null},{"FriendlyName":"Missing"},{"AppId":42},{"AppId":[" Valid.App ",null,{},""]}]}' |
|
||||||
Set-Content -LiteralPath $script:AppsListFilePath -Encoding UTF8
|
Set-Content -LiteralPath $script:AppsListFilePath -Encoding UTF8
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"TestApp.One": {
|
||||||
|
"FriendlyName": "Test App",
|
||||||
|
"Description": "A test app."
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -200,6 +200,7 @@ $script:ImportExportConfigSchema = Join-Path $schemasPath 'ImportExportConfigWin
|
|||||||
$script:RestoreBackupWindowSchema = Join-Path $schemasPath 'RestoreBackupWindow.xaml'
|
$script:RestoreBackupWindowSchema = Join-Path $schemasPath 'RestoreBackupWindow.xaml'
|
||||||
$script:LoadAppsDetailsScriptPath = Join-Path (Join-Path $scriptsPath 'FileIO') 'Import-AppDetailsFromJson.ps1'
|
$script:LoadAppsDetailsScriptPath = Join-Path (Join-Path $scriptsPath 'FileIO') 'Import-AppDetailsFromJson.ps1'
|
||||||
$script:TestAppInWingetListScriptPath = Join-Path (Join-Path $scriptsPath 'AppRemoval') 'Test-AppInWingetList.ps1'
|
$script:TestAppInWingetListScriptPath = Join-Path (Join-Path $scriptsPath 'AppRemoval') 'Test-AppInWingetList.ps1'
|
||||||
|
$script:ImportLanguageFileScriptPath = Join-Path (Join-Path $scriptsPath 'FileIO') 'Import-LanguageFile.ps1'
|
||||||
|
|
||||||
$script:ControlParams = 'WhatIf', 'Confirm', 'Verbose', 'Debug', 'LogPath', 'Language', 'Silent', 'Sysprep', 'User', 'SkipExplorerRestart', 'SkipRegistryBackup', 'RunDefaults', 'RunDefaultsLite', 'RunSavedSettings', 'Config', 'CLI', 'AppRemovalTarget'
|
$script:ControlParams = 'WhatIf', 'Confirm', 'Verbose', 'Debug', 'LogPath', 'Language', 'Silent', 'Sysprep', 'User', 'SkipExplorerRestart', 'SkipRegistryBackup', 'RunDefaults', 'RunDefaultsLite', 'RunSavedSettings', 'Config', 'CLI', 'AppRemovalTarget'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user