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

1

3

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.
Valorize answered 13/7, 2020 at 9:10 Comment(0)
D
3

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:\>
Daytoday answered 27/7, 2020 at 12:59 Comment(3)
Great! Is there an equivalent to Get-WinUserLanguageList for UICultures? The corresponding list of available culture may (perhaps) be different... I'm just guessing, I don't know.Valorize
@sancho.sReinstateMonicaCellio I think there is a misunderstanding. Get-WinUserLanguageList returns the installed language packs aka CultureInfo. There is no distinction between Culture and UICulture. It's more like you use one CultureInfo for both, Culture and UICulture, in the function above. I refactored some names to reduce ambiguities.Daytoday
Just a note that this doesn't work on PowerShell v1. I'll try to find a workaround for downlevel versions. Also, the following works for PowerShell Core 6.0 and newer: [System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture; [System.Threading.Thread]::CurrentThread.CurrentCulture = $cultureGig

© 2022 - 2024 — McMap. All rights reserved.