(a) For external programs such as netstat.exe
, there is unfortunately no way (that I know of) to change the UI language in-session:
On Windows Server 2012 / Windows 8 and above, the Set-WinUILanguageOverride
cmdlet allows you to (persistently) change the system-wide UI language for the current user, but that only takes effect in future logon sessions - that is, logging off and back on or a reboot are required.
As an aside: On Windows Server 2012 / Windows 8 and above, there is also the Set-Culture
cmdlet, but its purpose is not to change the UI culture (display language), but only culture-specific settings such as date, number, and currency formats. It too changes the setting persistently for the current user, but only requires a new session (process) for the change to take effect.
(b) For PowerShell commands and .NET types, there is an in-session (non-persistent) solution - assuming the commands are culture-aware and come with localized strings - see important caveats further below:
Set [cultureinfo]::CurrentUICulture
(temporarily) to the desired culture name (use [cultureinfo]::GetCultures('SpecificCultures')
to see all predefined ones) ; e.g., [cultureinfo]::CurrentUICulture = 'en-US'
- Complementarily, you may want to set
[cultureinfo]::CurrentCulture
(note the missing UI
part) as well, which determines the culture-specific number, date, ... formatting.
- In older versions of PowerShell / .NET, you'll have to set these properties on
[System.Threading.Thread]::CurrentThread
instead; e.g.,
[System.Threading.Thread]::CurrentThread.CurrentUICulture = 'en-US'
See the bottom section for helper function Use-Culture
that wraps this functionality for execution of code with a different culture temporarily in effect; here's an example call
with the culture-sensitive Get-LocalGroupMember
cmdlet:
# Try with values other than "en-US", e.g. "fr-FR" to see localized
# values in the "ObjectClass" output column.
Use-Culture en-US { Get-LocalGroupMember Administrators }
An ad hoc example, if you don't want to define a helper function (only the UI culture is changed here):
& {
$prev=[cultureinfo]::CurrentUICulture
[cultureinfo]::CurrentUICulture='en-US'
Get-LocalGroupMember Administrators
[cultureinfo]::CurrentUICulture=$prev
}
Caveats:
Fundamentally, the above only works with UI cultures corresponding to Windows languages actually installed for the current user, as reflected in the output from Get-WinUserLanguageList
PowerShell (Core) 7+ itself is not localized yet, as of v7.4.x; progress is being tracked in GitHub issue #666; however, the solution above does work with third-party modules that ship with localized messages and help content, as well as select Windows-specific modules that talk to platform APIs, such as the Microsoft.PowerShell.LocalAccounts
module, whose Get-LocalGroupMember
cmdlet was used in the example above.
.NET (Core), the cross-platform successor to the legacy, Windows-only .NET Framework seemingly does NOT offer localized exception messages for its built-in class library - though third-party libraries may offer them, if explicitly implemented.
While built-in .NET Framework APIs do respect an in-process UI culture change, that seemingly doesn't extend to system error messages surfaced via .NET exceptions, i.e. the error messages associated with the error codes returned from WinAPI functions - they remain in the persistently configured language for the current user.
Due to a bug in Windows PowerShell (PowerShell [Core] v6+ is not affected), in-session changes to [cultureinfo]::CurrentUICulture
and [cultureinfo]::CurrentCulture
are automatically reset at the command prompt, whenever a command finishes executing; however, for a given script the changes remain in effect for the entire script and its callees - see this answer.
Taking a step back:
I wrote some software that uses the output of system (powershell) commands, but did not foresee that the output would be different for languages other than English.
This is precisely why it's generally worth looking for PowerShell-native solutions as opposed to calling external programs:
Instead of having to parse - possibly localized - text, as with netstat.exe
, for instance, PowerShell commands return objects whose properties you can robustly access in a culture-independent fashion.
Specifically, Mathias R. Jessen suggests looking at Get-NetTCPConnection
as a PowerShell alternative to netstat.exe
(available on Windows Server 2012 / Windows 8 and above).
Function Use-Culture
's source code:
Note: The code was gratefully adapted from this venerable blog post; it is designed
# Runs a script block in the context of the specified culture, without changing
# the session's culture persistently.
# Handy for quickly testing the behavior of a command in the context of a different culture.
# Example:
# Use-Culture fr-FR { Get-Date }
function Use-Culture
{
param(
[Parameter(Mandatory)] [cultureinfo] $Culture,
[Parameter(Mandatory)] [scriptblock] $ScriptBlock
)
# Note: In Windows 10, a culture-info object can be created from *any* string.
# However, an identifier that does't refer to a *predefined* culture is
# reflected in .LCID containing 4096 (0x1000)
if ($Culture.LCID -eq 4096) { Throw "Unrecognized culture: $($Culture.DisplayName)" }
# Save the current culture / UI culture values.
$PrevCultures = [Threading.Thread]::CurrentThread.CurrentCulture, [Threading.Thread]::CurrentThread.CurrentUICulture
try {
# (Temporarily) set the culture and UI culture for the current thread.
[Threading.Thread]::CurrentThread.CurrentCulture = [Threading.Thread]::CurrentThread.CurrentUICulture = $Culture
# Now invoke the given code.
& $ScriptBlock
}
finally {
# Restore the previous culture / UI culture values.
[Threading.Thread]::CurrentThread.CurrentCulture = $PrevCultures[0]
[Threading.Thread]::CurrentThread.CurrentUICulture = $PrevCultures[1]
}
}
netstat
is not a powershell cmdlet - it's an executable. Why not useGet-NetTCPConnection
in a powershell script instead? – Turpitude