Search code examples
windowspowershelllocale

How to change "OsMuiLanguages" in windows-11?


Background:
In an attempt to change language settings for a Windows-11 Home edition, from ES to US. I managed to get most changes done, but still there are several other items* returning Spanish items, or aliases.

The only place left that is still showing es-ES (Spanish) shows up as OsMuiLanguages:

# Get-computerinfo | FL OsLanguage,OSMUIlanguages, OsLocale

OsLanguage     : en-US
OsMuiLanguages : {en-US, es-ES}
OsLocale       : en-US

Example of another item returning Spanish:

# Get-LocalGroup

Name                                 Description
----                                 -----------
Administradores                      Los administradores tienen acceso completo y sin
Device Owners                        Los miembros de este grupo pueden cambiar la …
Hyper-V Administrators               Members of this group have complete and unrestricted …
IIS_IUSRS                            Grupo integrado usado por Internet Information Services.
Invitados                            De forma predeterminada, los invitados tienen el mismo… 
...

# net localgroup

Aliases for \\LAPTOP-xxxx

-------------------------------------------------------------------------------
*Administradores
*Device Owners
*Hyper-V Administrators
*IIS_IUSRS
*Invitados
*Lectores del registro de eventos
*System Managed Accounts Group
*Usuarios
*Usuarios COM distribuidos
*Usuarios de administración remota
*Usuarios del monitor de sistema
*Usuarios del registro de rendimiento

The command completed successfully.

UPDATE: 2023-11-28

Adding some additional output:

# dism /online /get-intl

Deployment Image Servicing and Management tool
Version: 10.0.22621.1

Image Version: 10.0.22621.2715

Reporting online international settings.

Default system UI language : en-US
System locale : en-US
Default time zone : Romance Standard Time
Active keyboard(s) : 0409:00000409, 0c0a:0000040a
Keyboard layered driver : Not installed.

Installed language(s): en-US
  Type : Fully localized language.
Installed language(s): es-ES
  Type : Partially localized language, MUI type.
  Fallback Languages en-US

The operation completed successfully.

#--------------------------------------
# whoami /groups /FO TABLE

Group Name                                                    Type             SID          Attributes
============================================================= ================ ============ ===============================================================
Everyone                                                      Well-known group S-1-1-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account and member of Administrators group Well-known group S-1-5-114    Mandatory group, Enabled by default, Enabled group
BUILTIN\Administradores                                       Alias            S-1-5-32-544 Mandatory group, Enabled by default, Enabled group, Group owner
BUILTIN\Usuarios                                              Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\INTERACTIVE                                      Well-known group S-1-5-4      Mandatory group, Enabled by default, Enabled group
CONSOLE LOGON                                                 Well-known group S-1-2-1      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users                              Well-known group S-1-5-11     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\This Organization                                Well-known group S-1-5-15     Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Local account                                    Well-known group S-1-5-113    Mandatory group, Enabled by default, Enabled group
LOCAL                                                         Well-known group S-1-2-0      Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\NTLM Authentication                              Well-known group S-1-5-64-10  Mandatory group, Enabled by default, Enabled group
Mandatory Label\High Mandatory Level                          Label            S-1-16-12288

Note that there are different Types shown here, such as Alias and Label, for which I cannot find any info.


Q: Where is OsMuiLanguages set, and how can I remove it?

Bonus Question:
Would it remove the ES language from other items above?


Solution

  • Combining the - terse - Microsoft.PowerShell.Commands.ComputerInfo documentation (the return type of the Get-ComputerInfo cmdlet) with observed behavior:

    • OsMuiLanguages is the list of locally installed language packs (Multilingual User Interface (MUI) Packs, though some may actually of type LIP (Language Interface Pack)), including the one that the OS shipped with, the so-called install language; the order in which the languages are listed does not indicate which language is the active Windows display language (see below); instead, it seems that the install language is listed first, followed by the languages installed later in alphabetical order.

      • You can manage and download additional languages via the Settings app (downloadable languages are now called LXPs, Local eXperience Packs, and their ultimate source is Microsoft Store); you can directly launch the relevant page as follows:

        Start-Process ms-settings:regionformatting
        
    • OsLanguage is the so-called install language, i.e. the language that the OS shipped with.

    • OsLocale is the legacy system locale aka language for non-Unicode programs, which determines the culture-specific OEM and ANSI code pages used by non-Unicode applications. Notably, the OEM code page is still invariably used in consoles.

    I assume that it is only possible to remove language packs that were installed later (i.e. that you cannot remove the install language) and only if they're not used as the current system UI language (the language used by the Welcome screen and system accounts, as well as by default for future users), namely via Remove-AppxPackage in combination with Set-WinUserLanguageList, in order to remove the language from the list of preferred languages too; e.g., for es-ES:

    # The language's tag, as reported in the .OSMuiLanguages property.
    $langTag = 'es-ES'
    
    # Remove -WhatIf to perform actual removal.
    Get-AppxPackage Microsoft.LanguageExperiencePack$langTag |
      Remove-AppxPackage -WhatIf
    
    # Prompts for confirmation; add -Force to skip the prompt.
    Set-WinUserLanguageList (
      (Get-WinUserLanguageList) | Where-Object LanguageTag -ne $langTag
    )
    

    Note:

    • These operations affect the current user only.

    • If you start an elevated session and add -AllUsers to both Get-AppxPackage and Remove-AppxPackage, you can remove packages even for other users, but note that the Set-WinUserLanguageList call (or its interactive equivalent of removing the uninstalled language from the list of user languages in the Settings app) must be made from each user account, though with additional effort you could perform this centrally as well, by programmatically loading the registry hives of all users and performing the following in each, if present:

      • Remove the tag of the language to remove (e.g, es-ES) from the REG_MULTI_SZ value named Languages from key Control Panel\International\User Profile

      • Remove a subkey named for the language tag, if present.


    However, perhaps all you're looking for is to change the active Windows display language for the current user:

    To get the active display language:

    if ($result = Get-WinUILanguageOverride) { $result } else { (Get-WinUserLanguageList)[0] }
    

    To set it, there are two options:

    • Re-order the list of user languages, to make sure that the desired language comes first; e.g., if you haven't removed the es-ES language pack, you can put it last in the list of languages:

      $langTag = 'es-ES'
      
      # Prompts for confirmation; add -Force to skip the prompt.
      Set-WinUserLanguageList (
        @((Get-WinUserLanguageList) | Where-Object LanguageTag -ne $langTag) + $langTag
      )
      
      • This list of language tags is stored in a REG_MULTI_SZ registry value named Languages in key HKEY_CURRENT_USER\Control Panel\International\User Profile.
    • Put an override in place; this leaves the list of languages as-is (whose ordering implies language preference for applications downloaded from Microsoft Store):

      Set-WinUILanguageOverride en-US
      
      • This setting is stored in a REG_SZ registry value named WindowsOverride in key HKEY_CURRENT_USER\Control Panel\International\User Profile.
    • Log off and back on or reboot for the change to take effect.

    The above:

    • makes GUI elements appear in that language (if available)

    • makes cmd.exe and certain standard utilities (e.g. net.exe and whoami.exe) print messages in that language

    • sets the UI culture in .NET / PowerShell to that language, as reflected in [cultureinfo]::CurrentUICulture and Get-UICulture.

      • Windows PowerShell then uses that language in its messages and error messages.

      • By contrast, PowerShell (Core) 7+ does not, because it hasn't been internationalized - see GitHub issue #666.

    Note:

    • It seems that certain language-specific information is created statically based on the original display language, which is therefore retained even after switching to a different display language later.

    • Notably, as you've discovered and show in this related question, this applies to the names and descriptions of built-in user and group accounts such as Administrators; this answer shows a programmatic way to rename them after the fact.

    Additional considerations:

    • Changing the display language may not also set the regional settings (number, time, ... formats) as reflected in [cultureinfo]::CurrentCulture] and Get-Culture / $PSCulture: Only if the Regional format setting in the Settings app shows Recommended (which corresponds to the UserLocaleFromLanguageProfileOptOut REG_SZ registry value in key HKEY_CURRENT_USER\Control Panel\International\User Profile either not existing or having a value of 0) are the regional settings automatically changed in tandem with the display language.

      • If needed, as an alternative to changing the setting interactively via the Settings app (Start-Process ms-settings:regionformatting), you can use Set-Culture (note that there is no Set-UICulture), but the latter only allows you to specify a new regional settings statically, whereas the former allows you to return the setting to Recommended, which keeps the regional setting synced with future changes to the display language.
    • To change the system locale (code pages for non-Unicode programs and consoles), run intl.cpl to open the relevant Control Panel applet, switch to the Administrative tab and click on Change system locale... (requires elevation and a reboot). As the name suggests, this is a system-wide setting and therefore affects all users.

      • Note: Windows 10 introduced the option to set both the ANSI and OEM legacy code pages to UTF-8 (65001), which potentially enables full Unicode support even for legacy and console applications; however, as of Windows 11 22H2, the feature is still labeled beta and it has far-reaching consequences - see this answer for details.
    • By default, the keyboard language is determined by the first language shown in the list of preferred languages in the relevant Settings app page (Start-Process ms-settings:regionformatting), also reflected in the first one output by Get-WinUserLanguageList.

      • You can alternatively pick a fixed keyboard language via the advanced keyboard settings: Run Start-Process ms-settings:typing and click on Advanced keyboard settings.
    • You may also want to change the display language for the Welcome (logon) screen and future user accounts.

      • Run intl.cpl to open the relevant Control Panel applet, switch to the Administrative tab and click on Copy settings... (requires elevation).

    See also: