A lot of us, who administer Azure Virtual Desktop and engineer new images for our clients, have often the request to inject new Language Packs into the images, so that the new hosts can be setup in a different language.
While there is good article on the topic from Microsoft: Install language packs on Windows 10 VMs in Azure Virtual Desktop – Azure | Microsoft Learn
when I personally read it, it was confusing at first till I was able to implement it, so I decided to create this blog post and try to explain it in a simple way.
In the following article we’ll see how to create a PowerShell script, where we just prepare the sources one time and then we can run this script and reuse it in new environments
Step 1: Prepare the Files (1st time only)
From the Microsoft article, we need to download (Assuming that you’re using Windows 10 21H1 or later) the following 3 ISO’s:
- Language ISO:
- FOD Disk 1 ISO:
- Inbox Apps ISO:
The 3 files are pretty big, so make sure you have at least 20 GB on the drive:

Actually, the “Inbox Apps ISO” is the Windows Apps, which few people want to use in other languages, so in most cases, I only use the previous two ISO’s – Language and Features On Demand (FOD)
From the Language Pack ISO, copy the Language-Pack CAB file for the language you need:
Once you mount the ISO you’ll see the following folder:

For 64 bit OS, from the x64 Folder -> langpacks,
copy the Client Language Pack for the language you need

From the Local Experience Folder copy the following 2 Files from the subfolder with the language you need:

Now, let’s go to the other ISO. with the FOD:
Once you mount it, you’ll see a bunch of FOD language packs, for the different Windows Features, like Language Features Basic, Language Features Fonts and so on.
You can copy all you want, but make sure that you select the right language and system architecture, as some of them are for for other system architectures, like arm.

At the end you should be left with a folder, like this one (in the example for German)

Step 2: Upload the files to a cloud storage
Now, here you can use whatever cloud storage you want, but I used an Azure Storage Account, so my script will be optimized for that.
Zip your files and upload them one per language in the cloud storage

Then create a read-only SAS Link:

You should create one Zip file per Language Pack
Congratulatons – you’re done with the repository of files. This you need to do only once and make sure to prepare all language packs you need or may need
Step 3: Import the Language Packs in the AVD golden Image with PowerShell
Now for each new AVD Environment, you just need to run the script below, again, as explained in the Microsoft article: Install language packs on Windows 10 VMs in Azure Virtual Desktop – Azure | Microsoft Learn
Just make sure that you add a group, like the ones below for DE and NL, for each language you want to install in the image
########################################################
## Add Languages to running Windows Image for Capture ##
########################################################
[CmdletBinding()]
param(
[Parameter(Mandatory = $false,
HelpMessage = "specify which language you want to install. At the moment allowed values are DE, NL")]
[ValidateSet("DE","NL")]
[string]$LanguagePack="NL"
)
##Disable Language Pack Cleanup##
Disable-ScheduledTask -TaskPath "\Microsoft\Windows\AppxDeploymentClient\" -TaskName "Pre-staged app cleanup"
#connect to the storage account
Install-PackageProvider -Name "Nuget" -Force
install-module az.storage -Force
$context=New-AzStorageContext -ConnectionString "YOUR CONNECTION STRING HERE"
switch($LanguagePack)
{
"DE" {
#Download the Language Packs"
Get-AzStorageContainer -Context $context appsources | Get-AzStorageBlobContent -Blob "AVD Language Packs/DE/DE.zip" -Destination $env:TEMP
Expand-Archive -Path "$env:temp\AVD Language Packs\DE\DE.zip" -DestinationPath "$env:TEMP\AVD Language Packs\Content" -Force
$contentpath="$env:TEMP\AVD Language Packs\Content\DE"
##German##
Add-AppProvisionedPackage -Online -PackagePath $contentpath\LanguageExperiencePack.de-de.Neutral.appx -LicensePath $contentpath\License.xml
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Client-Language-Pack_x64_de-de.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-Basic-de-de-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-Handwriting-de-de-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-OCR-de-de-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-Speech-de-de-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-TextToSpeech-de-de-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-MSPaint-FoD-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Notepad-FoD-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-PowerShell-ISE-FOD-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Printing-WFS-FoD-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-StepsRecorder-Package~31bf3856ad364e35~amd64~de-de~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-WordPad-FoD-Package~31bf3856ad364e35~amd64~de-de~.cab
$LanguageList = Get-WinUserLanguageList
$LanguageList.Add("de-de")
Set-WinUserLanguageList $LanguageList -force
}
"NL" {
#Download the Language Packs"
Get-AzStorageContainer -Context $context appsources | Get-AzStorageBlobContent -Blob "AVD Language Packs/NL/NL.zip" -Destination $env:TEMP
Expand-Archive -Path "$env:temp\AVD Language Packs\NL\NL.zip" -DestinationPath "$env:TEMP\AVD Language Packs\Content" -Force
$contentpath="$env:TEMP\AVD Language Packs\Content\NL"
##German##
Add-AppProvisionedPackage -Online -PackagePath $contentpath\LanguageExperiencePack.nl-nl.Neutral.appx -LicensePath $contentpath\License.xml
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Client-Language-Pack_x64_nl-nl.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-Basic-nl-nl-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-Handwriting-nl-nl-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-OCR-nl-nl-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-TextToSpeech-nl-be-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-LanguageFeatures-TextToSpeech-nl-nl-Package~31bf3856ad364e35~amd64~~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-NetFx3-OnDemand-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-InternetExplorer-Optional-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-MSPaint-FoD-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Notepad-FoD-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-PowerShell-ISE-FOD-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-Printing-WFS-FoD-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-StepsRecorder-Package~31bf3856ad364e35~amd64~nl-NL~.cab
Add-WindowsPackage -Online -PackagePath $contentpath\Microsoft-Windows-WordPad-FoD-Package~31bf3856ad364e35~amd64~nl-NL~.cab
$LanguageList = Get-WinUserLanguageList
$LanguageList.Add("nl-nl")
$LanguageList.Add("nl-be")
Set-WinUserLanguageList -LanguageList $LanguageList -force
}
}
remove-item -Path "$env:TEMP:\AVD Language Packs\" -Force -ErrorAction SilentlyContinue
After you’re done, make sure you run the following on the host pool:
Create a scheduled task to run with User Credentials on logon (again, you’d need to change it to the languages you need):
$LanguageList = Get-WinUserLanguageList
$LanguageList.Add("de-de")
$LanguageList.Add("nl-nl")
Set-WinUserLanguageList $LanguageList -force
That’s it, I do hope you’d be able to easily administer your AVD environments now 🙂
Copy files from FOD ISO in Powershell:
# All de-DE packages
# Target is Drive Z:\Langpack\
copy *~de-DE~* Z:\Langpack\