Temporarily change powershell language to English?

  • (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:

    • 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:

  • PowerShell [Core] itself is not localized yet, as of v7.2.x; progress is being tracked in GitHub issue #666; however, the solution below 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.

  • 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]
  }
}

Original author of this code is @Scepticalist.

Run this from powershell console. It will change the culture to en-US for current session.

function Set-CultureWin([System.Globalization.CultureInfo] $culture) { [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture ; [System.Threading.Thread]::CurrentThread.CurrentCulture = $culture } ; Set-CultureWin en-US ; [system.threading.thread]::currentthread.currentculture

Then you have to use the command Get-NetTCPConnection Instead of netstat. For its usage see https://docs.microsoft.com/en-us/powershell/module/nettcpip/get-nettcpconnection?view=win10-ps

Tags:

Powershell