My customer has Spanish, French, English, Dutch, Romanian and Russian speaking employees and needs the Windows User Interface in this language. As of Windows 1809 and higher, Microsoft changed things with the language pack installation. They call this a Local Experience Pack (LXP in short).
Prior to Windows 10 1809 an installation of a Language Interface Pack (LIP in short) was easy. Just download the lp.cab of the language pack and install it with DISM or lpksetup.exe. Example old commands:
- dism.exe /online /add-package /packagepath:D:\langpacks\de-de\lp.cab
- lpksetup /i es-ES /r /s /p D:\langpacks\es-es\lp.cab
The User Experience changed when using LXP in Windows 10 >=1809. With LXP, things are more user focused from the modern settings panel. And more user input is needed, which is difficult for automation. If an end-user wants to select their “Windows Display Language”. The user needs to add a preferred language first (even if the LXP is already installed on the machine level). After that, he’s able to select the Windows Display Language of choice (which is a subset of the user defined preferred language).
If you want to automate this process in a pooled VDI or Windows Virtual Desktop environment all the workers need to have the LXP installed upfront or your users need admin rights. If you want to automate the installation of LXP to a golden master or persistent images, the process is as follows:
- Download the “Windows 10 Language Pack” ISO for your Windows build from the Windows Volume Licensing or MSDN website. (i.e. “Windows 10 Language Pack, version 1903”)
- Install the required Language Pack cab language files to the system. (i.e. “Microsoft-Windows-Client-Language-Pack_x64_es-es.cab”)
- Install the corresponding LXP APPX file to the system. (i.e. “LanguageExperiencePack.es-ES.Neutral.appx”)
- Add the language to the “preferred language” per user!
I’ve created a powershell script, which automates the steps 2 to 4. The script can be downloaded here: https://vandenbornit-my.sharepoint.com/:u:/g/personal/patrick_vandenborn_it/EdzXPl6eDB5Fj-uDxgRZsf4BkyMyGjRDZ050r62PoVs3eA?e=7yMJIK or copy paste the code at the bottom of this blog.
Use the powershell script as follows:
1. Create a folder of choice and create two subfolders (LangPacks and LXP)
2. Copy the cab files from the ISO (x86 or x64 folder) to the LangPacks directory
3. Copy the corresponding LXP folders form the ISO (LocalExperiencePacks) to the LXP directory
4. Edit the Install_Win10_LXP.ps1 script and change the global settings:
5. Add the Install_Win10_LXP.ps1 to your automation software or run as admin from PowerShell
6. The scripts detect missing files
7. When the script finishes, a powershell command is generated. Use this as a RunOnce login script for each user in your WVD or VDI environment:
8. Run the powershell script in user context
###########################################
#
PowerShell Script for users or login script
###########################################
$prefered_list =
Get-WinUserLanguageList
$prefered_list.Add("es-es")
$prefered_list.Add("fr-fr")
$prefered_list.Add("nl-nl")
Set-WinUserLanguageList($prefered_list)
-Force
|
9. This adds the installed languages to the “preferred language list” automatically:
The powershell script:
#############################
#
Install Language pack Win10 1809 and higher
#
#
Created by Patrick van den Born (vandenborn.it)
#
#
MS Switched from lp.cab to APPX also called Local Experience Packs
#
More info: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/add-language-packs-to-windows
#
#
This tool installs the needed CAB and APPX packages
#
#
You can download the Language Pack from your volume licensing channel website
#
#
In my case: "Windows 10 Language Pack, version 1903"
#
#
Create a folder structure like this
#
#
\LangPacks i.e.
D:\Win10-1903\LangPacks --> Root folder for LangPacks
#
\LXP i.e.
D:\Win10-1903\LXP --> Root folder for Local Experience Pack
#
#
Then copy required cab from ISO x64 or x86 folder, for example
#
\LangPacks\Microsoft-Windows-Client-Language-Pack_x64_es-es.cab
#
\LangPacks\Microsoft-Windows-Client-Language-Pack_x64_fr-fr.cab
#
\LangPacks\Microsoft-Windows-Client-Language-Pack_x64_nl-nl.cab
#
#
Then copy corresponding Local Experience Pack folders from ISO
LocalExperiencePack folder, for example
#
\LXP\es-es\LanguageExperiencePack.es-ES.Neutral.appx
#
\LXP\es-es\License.xml
#
\LXP\fr-fr\LanguageExperiencePack.fr-FR.Neutral.appx
#
\LXP\fr-fr\License.xml
#
\LXP\nl-nl\LanguageExperiencePack.nl-NL.Neutral.appx
#
\LXP\nl-nl\License.xml
#
#
The cab and appx files needs to be installed as Admin
#
#
To activate the languages, this should be started as user and is marked at
the end of this script
#
###############################################
#####################
#
Global script vars
#####################
$lp_root_folder =
"D:\Win10-1903" #Root folder where the copied sourcefiles are
$architecture =
"x64" #Architecture
of cab files
$systemlocale =
"nl-NL" #System
local when script finishes
#####################
#
Start installation of language pack on Win10 1809 and higher
#####################
$installed_lp =
New-Object System.Collections.ArrayList
foreach ($language
in Get-ChildItem
-Path "$lp_root_folder\LXP")
{
#check if
files exist
$appxfile
= $lp_root_folder
+ "\LXP\"
+ $language.Name + "\LanguageExperiencePack." + $language.Name + ".Neutral.appx"
$licensefile
= $lp_root_folder
+ "\LXP\"
+ $language.Name + "\License.xml"
$cabfile
= $lp_root_folder
+ "\LangPacks\Microsoft-Windows-Client-Language-Pack_"
+ $architecture
+ "_"
+ $language.Name + ".cab"
if (!(Test-Path $appxfile)) {
Write-Host
$language.Name
" - File missing: $appxfile"
-ForegroundColor Red
Write-Host
"Skipping installation of " + $language.Name
} elseif
(!(Test-Path
$licensefile)) {
Write-Host
$language.Name
" - File missing: $licensefile"
-ForegroundColor Red
Write-Host
"Skipping installation of " + $language.Name
} elseif
(!(Test-Path
$cabfile)) {
Write-Host
$language.Name
" - File missing: $cabfile"
-ForegroundColor Red
Write-Host
"Skipping installation of " + $language.Name
} else
{
Write-Host
$language.Name
" - Installing $cabfile"
-ForegroundColor Green
Start-Process
-FilePath "dism.exe"
-WorkingDirectory "C:\Windows\System32"
-ArgumentList "/online
/Add-Package /PackagePath=$cabfile /NoRestart" -Wait
Write-Host
$language.Name
" - Installing $appxfile"
-ForegroundColor Green
Start-Process
-FilePath "dism.exe"
-WorkingDirectory "C:\Windows\System32"
-ArgumentList "/online
/Add-ProvisionedAppxPackage /PackagePath=$appxfile /LicensePath=$licensefile /NoRestart" -Wait
Write-Host
$language.Name
" - CURRENT USER - Add language to preffered
languages (User level)" -ForegroundColor
Green
$prefered_list
= Get-WinUserLanguageList
$prefered_list.Add($language.Name)
Set-WinUserLanguageList($prefered_list) -Force
$installed_lp.Add($language.Name)
}
}
Write-Host "$systemlocale -
Setting the system locale" -ForegroundColor
Green
Set-WinSystemLocale -SystemLocale
$systemlocale
#Generating
output for script
Write-Host "
"
Write-Host "###########################################"
-ForegroundColor Blue
Write-Host "PowerShell
Script for users or login script" -ForegroundColor
Blue
Write-Host "###########################################"
-ForegroundColor Blue
Write-Host '$prefered_list
= Get-WinUserLanguageList' -ForegroundColor
Blue
For ($i
= 0; $i -ne $installed_lp.Count;
$i++) {
Write-Host
'$prefered_list.Add(' $installed_lp[$i] ')' -ForegroundColor
Blue
}
Write-Host 'Set-WinUserLanguageList($prefered_list)
-Force' -ForegroundColor Blue
|