Ash's helpful answer is the best solution for machines running Windows 8 or above / Windows Server 2012 R2 or above.


If you still need to run remotely on a Windows 7 / Windows Server 2012 machine:

(Get-ItemProperty 'HKCU:\Control Panel\Desktop' PreferredUILanguages).PreferredUILanguages[0]

Background information:

In local execution, the simplest solution is to use $PSUICulture (returns a string with the language name, such as en-US) or Get-UICulture (returns a [cultureinfo] object), as shown in this answer.

However, this doesn't work when you use PowerShell remoting (which is why the above solution / Ash's solution is necessary):

# Does NOT return the target user's display language.
# Seemingly always returns the OS installation language.
Invoke-Command -ComputerName $someComputer { $PSUICulture }

I'm unclear on the exact reasons, but it may be related to the fact that remotely executed PowerShell code runs in an invisible window station that is distinct from the interactive desktop.

Answer from mklement0 on Stack Overflow
🌐
Microsoft Learn
learn.microsoft.com › en-us › powershell › module › international › get-winuserlanguagelist
Get-WinUserLanguageList (International) | Microsoft Learn
This command returns the language list for the current user account, BCP-47 tags, and the corresponding display name.
Top answer
1 of 2
4

Ash's helpful answer is the best solution for machines running Windows 8 or above / Windows Server 2012 R2 or above.


If you still need to run remotely on a Windows 7 / Windows Server 2012 machine:

(Get-ItemProperty 'HKCU:\Control Panel\Desktop' PreferredUILanguages).PreferredUILanguages[0]

Background information:

In local execution, the simplest solution is to use $PSUICulture (returns a string with the language name, such as en-US) or Get-UICulture (returns a [cultureinfo] object), as shown in this answer.

However, this doesn't work when you use PowerShell remoting (which is why the above solution / Ash's solution is necessary):

# Does NOT return the target user's display language.
# Seemingly always returns the OS installation language.
Invoke-Command -ComputerName $someComputer { $PSUICulture }

I'm unclear on the exact reasons, but it may be related to the fact that remotely executed PowerShell code runs in an invisible window station that is distinct from the interactive desktop.

2 of 2
3

The language you see there is the first one in the list from Get-WinUserLanguageList.

PS C:\> (Get-WinUserLanguageList).LocalizedName
Russian
English (United States)

When I change the order of the list, and set English first, it reverses the order in PowerShell.

PS C:\> Set-WinUserLanguageList -LanguageList en-US,ru

Confirm
Continue with this operation?
[Y] Yes  [N] No  [S] Suspend  [?] Help (default is "Y"): Y
PS C:\> (Get-WinUserLanguageList).LocalizedName
English (United States)
Russian

So to get the current language, you merely have to call the first object in that list.

(Get-WinUserLanguageList)[0].LocalizedName
🌐
PDQ
pdq.com › powershell › set-winuserlanguagelist
Set-WinUserLanguageList - PowerShell Command | PDQ
The enabled input methods are listed in the format Language ID: Keyboard layout ID. --Handwriting recognition input mode (READ/WRITE). This value is either 0 (freehand) or 1 (write each character separately). ... PS C:\> $OldList = Get-WinUserLanguageList PS C:\> $OldList.Add("fr-FR") PS C:\> Set-WinUserLanguageList $OldList This command adds the language French (France) to the user's language list.
🌐
Microsoft Learn
learn.microsoft.com › en-us › powershell › module › international › set-winuilanguageoverride
Set-WinUILanguageOverride (International) | Microsoft Learn
Sets the Windows UI language override setting for the current user account. Set-WinUILanguageOverride [[-Language] <CultureInfo>] [<CommonParameters>] The Set-WinUILanguageOverride cmdlet sets a user-preferred display language to be used for the Windows user interface (UI). If no override setting is used, the display language is dynamically determined from the language list of the user. Log off and loging back on is required for changes to take place. For more information, see the Get-WinUserLanguageList and Set-WinUserLanguageList cmdlets.
🌐
Microsoft Learn
learn.microsoft.com › en-us › powershell › module › international › set-winuserlanguagelist
Set-WinUserLanguageList (International) | Microsoft Learn
January 11, 2023 - The Set-WinUserLanguageList cmdlet sets the current user language settings. These settings include input method, spelling setting, text prediction setting, and handwriting input mode.
🌐
PowerShell Forums
forums.powershell.org › powershell help
Language settings - PowerShell Help - PowerShell Forums
May 25, 2024 - i want to improve my code to actually copy language settings to all profiles and not change only current user profile If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] “Administrator”)) { $arguments = “& '” + $myinvocation.mycommand.definition + “'” Start-Process powershell -Verb runAs -ArgumentList $arguments Break } Clear-Host Function to set language and region settings function Set-Langu...
Find elsewhere
Top answer
1 of 2
1

In a comment you note that the problem was that Set-WinUserLanguageList complained about an invalid language passed as part of the array of languages to -LanguageList and, indeed, ua-UA should have been uk-UA (Ukrainian).[1]

You could have avoided the problem if you hadn't hardcoded the array passed to -LanguageList and instead retrieved the list of installed user language programmatically:

# Get the current list of installed user languages (as an array).
$userLangs = (Get-WinUserLanguageList).LanguageTag

You could then simply swap the array's first two entries for your successive Set-WinUserLanguageList calls, and use a single call to powershell.exe, the Windows PowerShell CLI.

Here's the PowerShell code in isolation, spread across multiple lines for readability, with comments (note that the Set-WinUserLanguageList calls emit warnings, which you can suppress with -WarningAction Ignore; the Start-Sleep 1 call (1-second sleep) shouldn't be necessary, but, sadly, is):

# Get the list (array) of user languages.
$userLangs = (Get-WinUserLanguageList).LanguageTag
# Create a copy that has the 1st and 2nd elements swapped.
$userLangsModified = $userLangs[1, 0] + $(if ($userLangs.Count -ge 3) { $userLangs[2..($userLangs.Count-1)] })
# Apply the workaround:
# Set the modified list.
Set-WinUserLanguageList -Force -LanguageList $userLangsModified
# Sleep a little. !! As you've found out, this is necessary
# for the 2nd call to take effect.
Start-Sleep 1
# Switch back to the original list.
Set-WinUserLanguageList -Force -LanguageList $userLangs

And here's the (of necessity) single-line form for your batch file:

@echo off

powershell -c "$userLangs = (Get-WinUserLanguageList).LanguageTag; $userLangsModified = $userLangs[1, 0] + $(if ($userLangs.Count -ge 3) { $userLangs[2..($userLangs.Count-1)] }); Set-WinUserLanguageList -Force -LanguageList $userLangsModified; Start-Sleep 1; Set-WinUserLanguageList -Force -LanguageList $userLangs"

Optional reading: How to test the validity of a culture name / language tag (whether it refers to a predefined culture / language):

It is not obvious how to test this, given that you can call a [cultureinfo] constructor with any name that is formally correct ([a-z][a-z] or [a-z][a-z]-[A-Z][A-Z], although case doesn't matter and there are variations with additional/longer tokens) without causing an error; similarly, the .GetCultureInfo() method doesn't report an error by default.

  • Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1) / .NET Framework solution:

    $cultureNameToTest = 'ua-UA'
    $isValid = 
      try { ([cultureinfo] $cultureNameToTest).EnglishName -notmatch 'Unknown Locale' } 
      catch { $false }
    
    • Note: Interactively, you can just do something like [cultureinfo] 'ua-UA' and see if the DisplayName column contains substring Unknown Locale or an error is reported.
  • PowerShell (Core) 7 (the modern, cross-platform, install-on-demand edition) / .NET solution:

    # Using the Get-Culture cmdlet
    $cultureNameToTest = 'ua-UA'
    $isValid = 
      try { [bool] (Get-Culture $cultureNametoTest) } 
      catch { $false }
    
    # Alternatively, using [cultureinfo]::GetCultureInfo() with the
    # overload with the `predefinedOnly` parameter
    $cultureNameToTest = 'ua-UA'
    $isValid = 
      try { [cultureinfo]::GetCultureInfo($cultureNameToTest, $true) } 
      catch { $false }
    
    • Note: Interactively, you can just do something like Get-Culture ua-UA and see if an error is reported.

[1] While the call still succeeds for those languages that are valid (you only get a warning stating The list you attempted to set contained invalid languages which were ignored), the original uk-UA (Ukrainian) entry will in effect disappear from the list (since you mistakenly tried to reference it as ua-UA, which was ignored).

2 of 2
-1

If you are executing a PowerShell command in a batch like that you might have problems in 3 places:

  • The command being executed. Try including the -NoExit parameter to the powershell.exe call so you can catch any script errors. You'll need to remove it later.
  • The powershell.exe process. If you have syntax problems in the command, or the execution policy is restrictive PowerShell will not execute. Try adding the parameter -ExecutionPolicy Bypass to the powershell.exe call (requires administrator). Also try to execute the raw command in a PowerShell host to see if it gives the expected result.
  • Syntax or execution problems in the batch file. Instead of executing the batch try calling it from a command prompt, this way when it finishes executing the window will still be open and you can see any errors that it might write to STDERR. Combine this with the -NoExit parameter and you will end up with two windows.

Let me know if it worked for you.

🌐
Winaero
winaero.com › home › windows 10 › find current system locale in windows 10
Find Current System Locale in Windows 10
May 13, 2019 - Open PowerShell as Administrator.Tip: You can add "Open PowerShell As Administrator" context menu. Type or copy-paste the following command: Get-WinSystemLocale. You can also use the classic command prompt to see the current system locale.
🌐
YouTube
youtube.com › watch
PowerShell: Get-WinUserLanguageList, Set-WinUserLanguageList - YouTube
In this video, I will be using Get-WinUserLanguageList, Set-WinUserLanguageList to configure Windows 11 keyboard list for current user and then I will also u...
Published   May 12, 2024
🌐
4sysops
4sysops.com › home › blog › articles › adding and removing keyboard languages with powershell
Adding and removing keyboard languages with PowerShell – 4sysops
July 28, 2023 - Outcome of PowerShell code to remove language in Windows10 ... Hi, you need to fill the contents of your LanguageList object first. You do it with this line: $LanguageList = Get-WinUserLanguageList · Then you can remove or add as many languages to that object, and after you're done, you can replace your current object with the one you created, like this:
🌐
Windows 10 Forums
tenforums.com › tutorials › 30656-see-system-default-ui-language-windows-10-a.html
See System Default UI Language of Windows 10 - Windows 10 Help Forums
June 16, 2021 - Windows uses this language if the current user (ex: new user) has not made specific language settings or if no active account is signed in like on the Welcome, Sign In, Sign Out, Shutdown, and Restart screens. The system UI language can be changed only if more than one user interface language (aka: display language) is installed on the computer. This tutorial will show you how to see the system default UI language for the installed language of Windows 10. ... 1 Open PowerShell...
Top answer
1 of 11
15

Don't know if this still works on Windows 7 but it does in Windows XP

reg query "hklm\system\controlset001\control\nls\language" /v Installlanguage

Then you can parse the ouput. e.g.

0409 --> English
0407 --> German
2 of 11
12

You can't use InstallLanguage under HKLM\SYSTEM\CurrentControlSet\Control\nls\language
because that's just what it says it is: Install Language
Although you can directly install localized version of Windows, this is not always done, as it wasn't on my PC. Instead a language pack is applied, which is fine, but then Display Language is not the same as Install Language.
Also if a user change his display language, InstallLanguage will not reflect the change. And there could be more users with different display languages.

  • Current User Display Language

HKCU\Control Panel\Desktop
PreferredUILanguages

FOR /F "tokens=3" %%a IN ('reg query "HKCU\Control Panel\Desktop" /v PreferredUILanguages ^| find "PreferredUILanguages"') DO set UILanguage=%%a
echo User Display Language: %UILanguage%


There is difference between Local Machine language, System language and User language. There is also separate settings for BCD language, used for recovery and boot manager

  • Local Machine

Install language is set upon installation and is never changed
also a Default value for "HKLM\SYSTEM\CurrentControlSet\Control\nls\language" key is set to the same value. This value is wrongly read by some InstallShield setup programs, resulting in English interface on localized Windows.
If you change Display language, new value is stored in

HKLM\SYSTEM\CurrentControlSet\Control\MUI\Settings
PreferredUiLanguages

this will override InstallLanguage value under HKLM\SYSTEM\CurrentControlSet\Control\nls\language
There is a mix-up in value types, while InstallLanguage is LCID, PreferredUiLanguages is LCID string. This language is then reported as Local Machine Language. It isn't User Display Language

  • System Language

This is the language for System user.
Before a user is logged on, this language is used.
That means it is a language for Welcome screen, and for the OOBE.

HKEY_USERS\S-1-5-18\Control Panel\Desktop\MuiCached
MachinePreferredUILanguages



There is also a WMI way to get OS language, but I didn't test which of these languages you'll get

wmic os get locale, oslanguage, codeset

FOR /F "tokens=2 delims==" %%a IN ('wmic os get OSLanguage /Value') DO set OSLanguage=%%a
echo OS Language: %OSLanguage%
🌐
Winaero
winaero.com › home › windows 10 › find default system language in windows 10
Find Default System Language in Windows 10
May 25, 2017 - Open a new PowerShell instance and type or copy-paste the following command: ... In the output, see the columns "Name" and "DisplayName". Method three. Using Registry · The same information can be found in the Registry. Here is how it can be done. Open Registry Editor (see how). ... Tip: How to jump to the desired registry key with one click. On the right, see the value data of the string value InstallLanguage. Its value is the code of the language used during the setup of Windows 10.
🌐
Eleven Forum
elevenforum.com › windows support forums › tutorials
Change Display Language in Windows 11 | Windows 11 Forum
January 17, 2022 - 1 Open Windows Terminal, and select Windows PowerShell. 2 Copy and paste the Get-WinUserLanguageList command into PowerShell, and press Enter to see a list of all languages currently installed for your account.
🌐
Eleven Forum
elevenforum.com › windows support forums › installation, updates and activation
New user/default user language VS. Service/System account language | Windows 11 Forum
March 13, 2025 - # Adapted from https://inthecloud247.com/install-an-additional-language-pack-on-windows-11-during-autopilot-enrollment/ # https://learn.microsoft.com/en-us/windows/win32/intl/table-of-geographical-locations $NewUserInputLocale = 'de-DE' $GeoId = 94 # Make a backup of SYSTEM user's current profile $SystemInputLocale = Get-SystemPreferredUILanguage $SystemList = Get-WinUserLanguageList # Temporarily change defaults on current user profile Set-SystemPreferredUILanguage $NewUserInputLocale Set-WinUILanguageOverride -Language $NewUserInputLocale $NewUserLanguageList = New-WinUserLanguageList -Langu