#Requires -RunAsAdministrator <# Sets Windows language on Windows 10/11. Menu: 1 = English (en-US) 2 = Svenska (sv-SE) 3 = Norsk Bokmal (nb-NO) Modes: - Quick = Current user display language, language list, keyboard, culture, and home location - All = Quick settings plus system preferred UI language, system locale, and defaults for system/new users Notes: - Requires Administrator. - Requires internet access to Windows Update, or a configured FoD/WSUS source. - Restart or sign out/sign in is required before the Windows shell fully changes language. - If this is run as SYSTEM, HKCU means the SYSTEM profile, not the signed-in user. - Avoids collection method calls so it can run more reliably under Constrained Language Mode. #> param( [string]$Choice, [string]$Mode ) $ErrorActionPreference = "Stop" function Write-Section { param( [string]$Title ) Write-Host "" Write-Host "== $Title ==" } function Write-Step { param( [string]$Message ) Write-Host (" - {0}" -f $Message) } function Write-WarningStep { param( [string]$Message ) Write-Host (" ! {0}" -f $Message) } function Get-FirstLanguageTag { param( $LanguageList ) foreach ($language in $LanguageList) { return $language.LanguageTag } return $null } function Test-CommandExists { param( [string]$Name ) $command = Get-Command -Name $Name -ErrorAction SilentlyContinue if ($null -eq $command) { return $false } return $true } function Install-LanguageWithLanguagePackManagement { param( [string]$Tag, [string]$SelectedMode ) if (-not (Test-CommandExists -Name "Install-Language")) { return $false } Write-Step "Using LanguagePackManagement Install-Language for $Tag" if ($SelectedMode -eq "All") { Install-Language -Language $Tag -CopyToSettings | Out-Null } else { Install-Language -Language $Tag | Out-Null } return $true } function Install-LanguageWithWindowsCapability { param( [string]$Tag, [string]$SelectedMode ) if (-not (Test-CommandExists -Name "Get-WindowsCapability")) { throw "Neither Install-Language nor Get-WindowsCapability is available on this system." } if ($SelectedMode -eq "Quick") { $capabilityPrefixes = @( "Language.Basic" ) } else { $capabilityPrefixes = @( "Language.Basic", "Language.OCR", "Language.Speech", "Language.TextToSpeech", "Language.Handwriting" ) } Write-Step "Using Windows capabilities fallback for $Tag" $allCaps = Get-WindowsCapability -Online foreach ($prefix in $capabilityPrefixes) { $caps = $allCaps | Where-Object { $_.Name -like "$prefix*~~~$Tag~*" } if (-not $caps) { Write-Step "${prefix}: not available for $Tag on this system, skipping" continue } foreach ($cap in $caps) { if ($cap.State -eq "Installed") { Write-Step "$($cap.Name): already installed" } else { Write-Step "Installing $($cap.Name)" Add-WindowsCapability -Online -Name $cap.Name | Out-Null } } } } function Set-CurrentUserLanguage { param( [string]$Tag, [string]$InputTip, [int]$GeoId ) $currentList = Get-WinUserLanguageList $newList = New-WinUserLanguageList -Language $Tag foreach ($item in $currentList) { if ($item.LanguageTag -ne $Tag) { $newList += $item } } Set-WinUserLanguageList -LanguageList $newList -Force | Out-Null Set-WinUILanguageOverride -Language $Tag Set-Culture -CultureInfo $Tag Set-WinHomeLocation -GeoId $GeoId Set-WinCultureFromLanguageListOptOut -OptOut $False Set-WinAcceptLanguageFromLanguageListOptOut -OptOut $False if ($InputTip) { Set-WinDefaultInputMethodOverride -InputTip $InputTip } } function Set-ComputerWideLanguage { param( [string]$Tag ) Set-WinSystemLocale -SystemLocale $Tag if (Test-CommandExists -Name "Set-SystemPreferredUILanguage") { Set-SystemPreferredUILanguage -Language $Tag } else { Write-WarningStep "Set-SystemPreferredUILanguage is not available; system preferred UI language was not changed" } Copy-UserInternationalSettingsToSystem -WelcomeScreen $True -NewUser $True } function Test-LanguageResult { param( [string]$Tag, [string]$SelectedMode ) $problems = 0 Write-Section "Verification before restart" $verifyList = Get-WinUserLanguageList $primaryLanguage = Get-FirstLanguageTag -LanguageList $verifyList if ($primaryLanguage -eq $Tag) { Write-Step "Primary user language is $Tag" } else { Write-WarningStep "Primary user language is $primaryLanguage, expected $Tag" $problems = $problems + 1 } $uiOverride = Get-WinUILanguageOverride if ($null -ne $uiOverride -and $uiOverride.Name -eq $Tag) { Write-Step "User UI language override is $Tag" } else { Write-WarningStep "User UI language override is not $Tag" $problems = $problems + 1 } $culture = Get-Culture if ($culture.Name -eq $Tag) { Write-Step "User culture is $Tag" } else { Write-WarningStep "User culture is $($culture.Name), expected $Tag" $problems = $problems + 1 } if ($SelectedMode -eq "All") { $systemLocale = Get-WinSystemLocale if ($systemLocale.Name -eq $Tag) { Write-Step "System locale is $Tag" } else { Write-WarningStep "System locale is $($systemLocale.Name), expected $Tag" $problems = $problems + 1 } if (Test-CommandExists -Name "Get-SystemPreferredUILanguage") { $systemPreferred = Get-SystemPreferredUILanguage if ($systemPreferred -eq $Tag) { Write-Step "System preferred UI language is $Tag" } else { Write-WarningStep "System preferred UI language is $systemPreferred, expected $Tag" $problems = $problems + 1 } } } return $problems } if (-not $Choice) { Write-Host "" Write-Host "Choose language:" Write-Host "1 = English" Write-Host "2 = Svenska" Write-Host "3 = Norsk Bokmal" Write-Host "" $Choice = Read-Host "Enter 1, 2, or 3" } switch ($Choice) { '1' { $LanguageTag = 'en-US' $LanguageName = 'English (United States)' $InputTip = '0409:00000409' $GeoId = 244 } '2' { $LanguageTag = 'sv-SE' $LanguageName = 'Svenska (Sverige)' $InputTip = '041D:0000041D' $GeoId = 221 } '3' { $LanguageTag = 'nb-NO' $LanguageName = 'Norsk Bokmal (Norge)' $InputTip = '0414:00000414' $GeoId = 177 } default { Write-Host "Invalid choice: $Choice" Write-Host "Use 1, 2, or 3." exit 1 } } if (-not $Mode) { Write-Host "" Write-Host "Choose mode:" Write-Host "1 = Quick (current user language/display settings)" Write-Host "2 = All (current user + system-wide settings)" Write-Host "" $modeChoice = Read-Host "Enter 1 or 2" switch ($modeChoice) { '1' { $Mode = "Quick" } '2' { $Mode = "All" } default { Write-Host "Invalid mode: $modeChoice" Write-Host "Use 1 or 2." exit 1 } } } else { switch ($Mode) { 'Quick' { $Mode = "Quick" } 'All' { $Mode = "All" } 'quick' { $Mode = "Quick" } 'all' { $Mode = "All" } default { Write-Host "Invalid mode: $Mode" Write-Host "Use Quick or All." exit 1 } } } Write-Host "" Write-Host "Selected language: $LanguageName [$LanguageTag]" Write-Host "Selected mode: $Mode" Write-Section "Execution context" $currentIdentity = whoami.exe Write-Step "User: $currentIdentity" Write-Step "PowerShell language mode: $($ExecutionContext.SessionState.LanguageMode)" if ($currentIdentity -eq "nt authority\system") { Write-WarningStep "Running as SYSTEM. Current-user settings will apply to SYSTEM, not the signed-in user's HKCU profile." } Write-Section "Installing language" $installedWithLanguagePackManagement = $false try { $installedWithLanguagePackManagement = Install-LanguageWithLanguagePackManagement -Tag $LanguageTag -SelectedMode $Mode } catch { Write-WarningStep "Install-Language failed: $($_.Exception.Message)" Write-WarningStep "Trying Windows capability fallback" } if (-not $installedWithLanguagePackManagement) { Install-LanguageWithWindowsCapability -Tag $LanguageTag -SelectedMode $Mode } Write-Section "Configuring current user" Set-CurrentUserLanguage -Tag $LanguageTag -InputTip $InputTip -GeoId $GeoId Write-Step "User language list, UI override, culture, home location, and default keyboard set" if ($Mode -eq "All") { Write-Section "Configuring computer-wide settings" Set-ComputerWideLanguage -Tag $LanguageTag Write-Step "System locale, system preferred UI language, and default account settings applied where supported" } else { Write-Section "Skipping computer-wide settings in Quick mode" Write-Step "System locale not changed" Write-Step "System preferred UI language not changed" Write-Step "Welcome screen and new user defaults not changed" } $problemCount = Test-LanguageResult -Tag $LanguageTag -SelectedMode $Mode Write-Host "" if ($problemCount -gt 0) { Write-Host "Completed with $problemCount verification warning(s)." Write-Host "If these warnings show the old language immediately after running, a policy, missing language pack, or wrong execution account is preventing the change." exit 2 } Write-Host "Done." if ($Mode -eq "All") { Write-Host "Language set to $LanguageName [$LanguageTag] for the current user and computer-wide defaults." } else { Write-Host "Language set to $LanguageName [$LanguageTag] for the current user." } Write-Host "Restart the computer, or sign out and back in, to fully apply the Windows UI language."