powershellculturecurrentuicultureuiculture

Fully change language (including Culture) for the current PowerShell session


My Win 10 system has Spanish language. I mean to fully operate a PowerShell session in English. Across everything I tried (see below), I managed to change the UICulture to en-US for the current session, but not the Culture.

Is there any way I can permanently change the Culture for the current PowerShell session?


Changing the Culture (with no success):

    > $( Get-Culture ; Get-UICulture ; [System.Threading.Thread]::CurrentThread.CurrentCulture ; [System.Threading.Thread]::CurrentThread.CurrentUICulture ; [CultureInfo]::CurrentCulture ; [CultureInfo]::CurrentUICulture ; ) | Format-Table -Property LCID,Name,DisplayName,IsNeutralCulture,UseUserOverride,IsReadOnly
     LCID Name  DisplayName             IsNeutralCulture UseUserOverride IsReadOnly
     ---- ----  -----------             ---------------- --------------- ----------
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False 
    > Set-Culture 'en-US'
    > [Threading.Thread]::CurrentThread.CurrentCulture='en-US'
    > $( Get-Culture ; Get-UICulture ; [System.Threading.Thread]::CurrentThread.CurrentCulture ; [System.Threading.Thread]::CurrentThread.CurrentUICulture ; [CultureInfo]::CurrentCulture ; [CultureInfo]::CurrentUICulture ; ) | Format-Table -Property LCID,Name,DisplayName,IsNeutralCulture,UseUserOverride,IsReadOnly
     LCID Name  DisplayName             IsNeutralCulture UseUserOverride IsReadOnly
     ---- ----  -----------             ---------------- --------------- ----------
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False
    11274 es-AR Spanish (Argentina)                False            True      False
     1033 en-US English (United States)            False            True      False

Note: I inferred System.Threading.Thread and Threading.Thread are the same.


Other things I tried:

Answers here and here. Since they are SO posts, I guess not posting them here reduces the clutter. But I could add them if deemed convenient.

I found a few other posts, all repeating the same commands.


EDIT:

Methods for setting Culture:

S1. Win Settings -> Time and Language -> Region -> Regional Format

S2. Set-Culture <culture>

S3. [CultureInfo]::CurrentCulture=<culture>

S4. [Threading.Thread]::CurrentThread.CurrentCulture=<culture>

Methods for getting Culture:

G1. Same as S1.

G2. Get-Culture

G3. [CultureInfo]::CurrentCulture

G4. [Threading.Thread]::CurrentThread.CurrentCulture

What I found:

  1. S3/G3 and S4/G4 seem to involve the same session setting / environment variable / registry key, etc. (?), and to be completely equivalent.
  2. Method S1 affects (G2, G3, G4) in a new session.
  3. Method S2 affects G1 immediately, and (G3, G4) in a new session.
  4. Methods (S3, S4) affect (G3, G4) immediately (trivial) but only in the current thread, not session, and (1, 2) not at all.
  5. The options available in method S1 are richer than those for method S2. I can change in S1 to "Spanish (Argentina)", "English (US)", etc., and it will get reflected in PS. But if I change in S1 to "Spansh (Brazil)", then PS will show en-US, as if it were a fallback Culture.

Solution

  • The following function will change both Culture and UICulture for the current PowerShell session in PowerShell 5.1:

    function Set-PowerShellLanguage {
        
        Param (
            [Parameter(Mandatory)] 
            [System.Globalization.CultureInfo] $CultureInfo
        )
    
        if ($CultureInfo -notin (Get-WinUserLanguageList | % {$_.LanguageTag})) {
            Write-Error "Language pack for $CultureInfo is not installed."
            return
        }
        [System.Reflection.Assembly]::Load('System.Management.Automation').GetType('Microsoft.PowerShell.NativeCultureResolver').GetField('m_Culture', 'NonPublic, Static').SetValue($null, $CultureInfo)
        [System.Reflection.Assembly]::Load('System.Management.Automation').GetType('Microsoft.PowerShell.NativeCultureResolver').GetField('m_uiCulture', 'NonPublic, Static').SetValue($null, $CultureInfo)
    }
    

    It is actually a merge of the already linked answer and mkelement0's comment.

    Example usage:

    PS C:\> Get-Culture
    
    LCID             Name             DisplayName
    ----             ----             -----------
    1033             en-US            English (United States)
    
    
    PS C:\> Get-UICulture
    
    LCID             Name             DisplayName
    ----             ----             -----------
    1033             en-US            English (United States)
    
    
    PS C:\> Set-PowerShellLanguage 'es-AR'
    PS C:\> Get-Culture
    
    LCID             Name             DisplayName
    ----             ----             -----------
    11274            es-AR            Spanish (Argentina)
    
    
    PS C:\> Get-UICulture
    
    LCID             Name             DisplayName
    ----             ----             -----------
    11274            es-AR            Spanish (Argentina)
    
    
    PS C:\>