Blog Post

Core Infrastructure and Security Blog
14 MIN READ

Windows 10 Multilanguage Deployment with MEMCM

Christian Wunderlich's avatar
Apr 30, 2020

 

Hello Everyone! My name is Christian Wunderlich, Premier Field Engineer (PFE) at Microsoft Germany for Microsoft Endpoint Manager. This blog post will provide you a better understanding on how to manage multilanguage windows 10 deployments. It will focus on how to deal with LXP files and language specific add-ons like Features on Demand! Once you have reached the end of this post, you can combine all those puzzle pieces to build your own multilanguage deployment!

Let´s get started with some basics ....

 

  1. Features on Demand
  2. Windows Language Packs
  3. Automation with MEMCM

 

Features on Demand

 

What are Features on Demand? 

Features on Demand (FODs) are windows feature packages that can be installed at any time. Common Features are .NetFx3 or additional language features for a language pack like Handwriting, Text-To-Speech, speech recognition, ...

  

Starting with Windows 10, version 1809 and Windows Server 2019, Windows has two different types of FODs available.  

  

FODs without satellite packages 

Those FODs include all language resources packaged into just one file. Those FODs are distributed as a single cab file. 

 

 

FODs with satellite packages

FODs with satellite packages are language neutral features which have languages and/or architecture resources in separate packages, so called satellites. If you would point your installation to a source containing those language and/or architecture files, only the files which apply to the windows image are installed which reduces the disk footprint. 

 

 

FODs with satellites require a well-formed repository of cab files and metadata for an offline installation. You can´t just copy a few files from the source iso and expect that the installation is successful. Those satellite packages require metadata used during the installation.  

 

Installation 

 

There are a couple of methods allowing you to install Features on Demand. FODs can be installed either online via windows update or offline using cab files. The later one requires a few preparation steps.  

 

Preparation 

 

Preparation of the offline repository 

There are a few options you have in order to prepare a repository of FOD files. Either you use the whole ISO files which can be up to 10GB or you extract only the files which are needed for a specific client and store them in a separate repository. If it comes to installations on just a few machines, the best way would be surely to just mount the iso and point the installation to this source. Another option would be to use a file share which contains the whole stack of FODs which you can also use in the source parameter. In case you want to deploy specific files during a Task Sequence with MEMCM, you might need to create a dedicated repository to use this as the package source. 

  

FODs without satellite packages 

All FODs without a satellite package just need the package.cab file in a folder. Once the file is in that folder, you can just point the installation to this source so it can be installed without further considerations. 

 

 

FODs with satellite packages 

FODs with satellite packages require more preparation in case you want use them offline. Beside from finding the necessary files and including them into a package, you also require the metadata folder as well as the FoDMetaData_Client.cab file! 

If you want to install a specific feature, you need to take the installed languages on the client into consideration. You must provide the language neutral file(s) as well as all language related files for this feature. In addition, you also must take care about the architecture amd64 and/or wow64. 

In this example, my client is a windows 10 1909 which has an en-us base installation with the German and French language pack on top. To install the DHCP RSAT Tool, you must provide the following files. 

 

 
Preparation FODs online 

If you are planning to retrieve the content via the Internet (Windows Update) you just need to enable a GPO called "Specify settings for optional component installation and component repair" and select the option "Download repair content and optional features directly from Windows Update instead of Windows Server Update Services (WSUS). 

If you don´t do this, you might run into the Error code 0x800f0954 

 

Installation methods 

You do have several methods and commands available to install FODs. Either via DISM or via add-windowscapability. In both cases, please use the parameter /add-capability instead add-package as the parameter /add-capability work with both satellites and non-satellite packages. 

  

There are other parameters available which can be found here.

 

Online installation 

 

  • add-WindowsCapability -Online -Name Rsat.DHCP.Tools~~~~0.0.1.0 

 

Offline installation 

When installing FODs offline, you might have several commands to do so. As an example, I have listed a dism as well as a more recent PowerShell-cmdlet! 

  

  • DISM.exe /Online /add-capability /CapabilityName:"Rsat.DHCP.Tools~~~~0.0.1.0" /limitaccess /source:"C:\temp\DHCP" 
  • Add-WindowsCapability -Online -Name "Rsat.DHCP.Tools~~~~0.0.1.0" -Source "C:\temp\DHCP" -LimitAccess 

 

Windows Language Packs

  

Microsoft offers a variety of options to change the Windows Language to your demands. At the first glance this might seem to very confusing as there are cab , lxp, lip, appx, FODs and a lot more expressions used in those discussions about language packs. First, let´s bring in some clarity into this. 

  

Language component explanation 

There are different language components used which need to be explained. Beside from the below mentioned main components, there are other components available which are not part of this guide. 

  

  • Language Packs (LP): Fully-localized Windows UI text for the dialog boxes, menu items, and help files that you see in Windows. Those files are delivered as .cab files 

  

  • Language Interface Packs (LIP): partially-localized languages. LIPs require a base language pack. LIPs only translate the most common dialog boxes, menu items and help files. UI language is not changed, therefore it requires the base language pack. In previous windows edition, those files have also been delivered as .cab files, since Windows 1803 those files are delivered as .appx packages, now called LXP files! 

  

  • Local Experience Packs (LXP): Since Windows 1803, Microsoft introduced Local Experience Packs which are modern language packs delivered through the Microsoft Store or Microsoft Store for Business. LXPs are the successor of the legacy LIPs which will be replaced!  

  

  • Features on Demand (FODS): Features on Demand include language specific additional features like spell checking, handwriting, text-to-speech and so on. Features on Demand include beside those language files a lot more features which can extend your windows environment like NetFx3. Those Features can be added at any time. 

 

Installation notes 

All kind of the above listed components can be installed during the provisioning process or afterwards as an additional language. According to Microsoft´s documentation, it is recommended to install language FODs (handwriting, text-to-speech, …) after you have applied a LP. To minimize the disk footprint, only install languages on the device what you think your users will require at the users location.

 

Installation 

As already mentioned above, you have the option to apply / install language packs while the OS runs or you have the option to inject them into the image itself.  

  

Add languages to a running Operating System 

 

DISM 

LP or LIPs can be installed while the OS is being executed with the dism tool. You just need to copy the LP.cab file to the desired location and execute the following installation command. 

 

  

  • dism /online /add-package /packagepath:"C:\temp\es-es\Microsoft-Windows-Client-Language-Pack_x64_es-es.cab" 

Beside installing a single lp, you can specify further files(LIP, FOD) into this location and execute the following: 

  • dism /online /add-package /packagepath:"C:\temp\es-es\" 
 
LXP 

LXPs are the successor of the traditional deprecated LIP files. Additional to the list of the previous LIPs, you now also have LXP files for all those languages for which you have had only a full language pack available. But be aware, this doesn´t mean you can deploy an LXP for a language like German, Spanish or French and expect that the whole OS got translated. LXP files, even for languages where a full language pack exist, will just translate the mostly used parts of the Operating System! 

 

Local experience packages can be applied with the following command: 

 

  • Add-appxpackage –Path C:\temp\de-de\LanguageExperiencePack.de-DE.Neutral.appx 

 

  

By using add-appxpackage you are just registering the Application for the current logged-on user.  You can take a look for which user the app is actually registered by running this command. 

 

  • Get-AppxPackage -AllUsers | ? Name -Like *LanguageExperiencePack* | Format-List Name, PackageUserInformation 

Even after the language has been installed, it is not yet in the list of available display languages. How to add the language is covered in a later section.

 

There is another way to install a Local Experience Pack.  This time, we are applying the LXP files with the PowerShell command add-appxprovisionedpackage. This cmdlet does not only install the LP for the current user, it does install it for all newly created users automatically.

 

  • Add-AppxProvisionedPackage -Online -PackagePath C:\temp\de-de\LanguageExperiencePack.de-DE.Neutral.appx -LicensePath C:\temp\de-de\License.xml 

 

After installing the LXP and the creation of a new user account, we can check the installation status by using the previously used command:

 

  • Get-AppxPackage -AllUsers | ? Name -Like *LanguageExperiencePack* | Format-List Name, PackageUserInformation
 

 

So far, the process went quite smooth, but unfortunately the newly installed LXP does not yet appear in the list of available windows display languages. It must be added afterwards, a more detailed guide is covered in a later section.

 

Manually add the recent installed LXP to the list of available windows display language

Once you have installed the LP, LIP or LXP, you must make it available to the user. Unfortunately, this is not yet automated, so even after installing the language, it is not yet automatically available in the list of windows display languages.

 

 

Now either the user adds the installed language to his preferred list of languages OR you have to do this manually via PowerShell.

 

 

$OSLanguages = (Get-WmiObject -Class Win32_OperatingSystem -Namespace root\CIMV2).MUILanguages

$userlanguagelist = Get-WinUserLanguageList

foreach ($OSLanguage in $OSLanguages) {

    $userlanguagelist.add($OSLanguage)

}

Set-WinUserLanguageList $userlanguagelist -force

 

 

 

How to automate this process with MEMCM?

As Microsoft Endpoint Configuration Manager is widely used by a lot of enterprises, I wanted to take this into consideration and provide some guidance on how to actually deploy those LPs and LXPs in an automated way.

 

As so often, there is no general recipe which covers every use case, so there are a few things to consider before deciding which solution you want to implement!

 

First of all, there is the decision to make if you would like to install this LXP or LP as part of the Operating System Deployment or as an additional language you will offer via the Software Center. In both cases, there are a few things to take care of, which I will cover in the following sections!

 

Deployment of additional Languages with MEMCM

The Deployment of additional LXP files with MEMCM might be a bit tricky as the language does not automatically register itself as an available display language you can select. Therefore we might need to tweak the installation here a bit :smile:

 

First of all, I just would like to highlight the different deployment options you have with MEMCM. The LXP installation can be done via

  • built-in application wizard (deployment of appx packages)
  • via the store as an (connected to Store 4 Business)
    • online application
    • offline application

In all deployment situations you will have to manually adjust the language settings afterwards as the installed language does not appear in the list of available languages in the dropdown menu. To bypass this problem, we have to execute a script, so windows automatically registers this LXP language as a selectable language.

 

I have built an application which executes a script as the user account, not system (to set default language and make it available in the language selection screen) which has a dependency of the application to install the LXP. So MEMCM downloads both applications but first installs the LXP and executes secondly the script to make this language selectable in the list and sets it as default :smile: so easy!

 

Remember - Of course you can also install the LXP without the script, but it will just change the language for the current user. If another user will logon to windows, it will use the default language of your image.

 

The later section will cover what scripts and configuration is needed to build the application(s).

 

Deployment of Languages as part of the OSD

I will not tackle the LP installation with MEMCM that much, as there are hundreds of other blogs describing this more detailed. Furthermore the approach even with the latest .cab files is still the same as in good old days.

 

This article is more about the deployment of the newer local experience packs with MEMCM. You might face the challenge, that you would like to use those LXP files, as this is the future, but still would like to apply them as you would have done with the traditional lp.cab files.

 

In order to do this, you have to use add-appxprovisionedpackage as this command installs but does not register the appx package during the task sequence. This is required as no user is logged-on yet! Furthermore, the System Account is not allowed to run the add-appxpackage command!

 

 

  • powershell.exe -executionpolicy bypass -command “Add-AppxProvisionedPackage -Path %OSDTargetSystemDrive%\ -PackagePath .\LanguageExperiencePack.de-DE.Neutral.appx

 

This command does pre-provision the appx package to the user, nevertheless this LXP still needs to get registered. To be able to do this, you have to add an additional step (run command line) in the task sequence to add a registry key.

 

  •  cmd.exe /c reg add "HKLM\SOFTWARE\Policies\Microsoft\Windows\Appx" /t REG_DWORD /v AllowDeploymentInSpecialProfiles /d 1 /f

 

This regkey allows deployment operations (adding, registering, staging, updating or removing) of Windows Store apps when using a special profile. If this regkey does not exist or is disabled, the next step will be blocked!

 

Before finally register the LXP, we must add a (service)user to the local administrator group. Because the add-appxpackage command, which we run next, need to be executed with elevated rights but not from the system account.

 

 

  • cmd.exe /c net localgroup “Administrators” “serviceaccount” /add

 

The next step is to register the LXP for a user. To achieve this, we would need to add another step (run PowerShell script) and run this step as a user (f.e. service account). You will find all necessary scripts in the section [Deployment Tools & Configurations].

 

 

 

$pathxml = (Get-AppxPackage -AllUsers | ? Name -Like *LanguageExperiencePackde-DE*).InstallLocation

Add-AppxPackage -Register -Path “$pathxml\AppxManifest.xml” -DisableDevelopmentMode

 

Before moving on, let´s remove the (service)user again from the administrators group. Add another run command line step with the following content:

 

  • cmd.exe /c net localgroup “Administrators” “serviceaccount” /delete

 

Now, as the app is registered and not anymore in staging status, we can use again f.e. our custom xml file to make this LXP Language as the default language for the current and all new users!

You will find all necessary scripts in the section [Deployment Tools & Configurations]

 

 

  • Powershell.exe -ExecutionPolicy ByPass -File SCCM_SetLangPack.ps1

 

Another computer restart at the end will finish off the project to use LXP files and treat them like as regular lp files! You will now have the default language set to your desired one! If you consider to work with task sequence variables, you can do this for a lot more languages!

 

Just to provide you an overview about my task sequence setup:

 

 

Deployment Tools & Configurations

This section should outline the tools and configurations to automate the deployment of multi languages.

 

Custom XML file to set default language

You still can define custom "international settings" by using the intl.cpl tool in conjunction with a custom XML file. Those settings include default language, local, keyboard values and other language related configurations. Please be aware, that with Windows 10 the intl.cpl command line tool does not support newer settings available in the Region and Language section of the control panel. Furthermore you should use the new PowerShell cmdlet settings to automate customizing international settings. Nevertheless, I have used this particular solution to not only set the default language but also some other language settings for the current and for new users!

 

XML to specify Language Settings

 

 

<gs:GlobalizationServices xmlns:gs="urn:longhornGlobalizationUnattend">

<!--User List-->

<gs:UserList>

    <gs:User UserID="Current" CopySettingsToDefaultUserAcct="true" CopySettingsToSystemAcct="true"/>

</gs:UserList>

<!-- user locale -->

<gs:UserLocale>

    <gs:Locale Name="de-DE" SetAsCurrent="true"/>

</gs:UserLocale>

<!-- system locale -->

<gs:SystemLocale Name="de-DE"/>

<!-- GeoID -->

<gs:LocationPreferences>

    <gs:GeoID Value="94"/>

</gs:LocationPreferences>

<gs:MUILanguagePreferences>

<gs:MUILanguage Value="de-DE"/>

<gs:MUIFallback Value="en-US"/>

</gs:MUILanguagePreferences>

<!-- input preferences -->

<gs:InputPreferences>

    <!--de-DE-->

    <gs:InputLanguageID Action="add" ID="0407:00000407" Default="true"/>

    <!--en-US-->

    <gs:InputLanguageID Action="remove" ID="0409:00000409"/>

</gs:InputPreferences>

</gs:GlobalizationServices>

 

 

PowerShell Script to call this XML file (intl.cpl)

With this tiny script you can just call the intl.cpl command line tool and provide the custom XML file to change the language. I have built a memcm application (install as user) to just execute this script. As already outlined above, if you create another application for installing the LXP, you can use this as a dependency to install and set a new language automatically!

 

Powershell Script to apply language settings using intl.cpl

 

 

start-sleep -seconds 20



$LogFileLocation = $env:TEMP+"\importlanguage.log"

Start-Transcript -path $LogFileLocation -Force



function prepare-scriptname

{

if ($hostinvocation -ne $null){$hostinvocation.MyCommand.Path}

else{$script:MyInvocation.MyCommand.Path}

}



[string]$ScriptName = prepare-scriptname

[string]$ScriptDirectory = Split-Path $ScriptName



Write-Output "Create Path"



$dedeXML = $ScriptDirectory + "\de-DE.xml"



Write-Output "import language settings from XML"



& $env:SystemRoot\System32\control.exe "intl.cpl,,/f:`"$dedeXML`""



Stop-Transcript

 

This is the content you would need to deploy this.

 

 

References (Windows Features on Demand):

Add or Remove FODS

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/features-on-demand-v2--capabilities#adding-or-removing-features-on-demand 

 Overview Features on Demand

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/features-on-demand-v2--capabilities#overview

List of available Features on Demand

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/features-on-demand-non-language-fod

 

References (Windows Language Pack):

Localize Windows

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/localize-windows

LXP Explanation

https://techcommunity.microsoft.com/t5/windows-it-pro-blog/local-experience-packs-what-are-they-and-when-should-you-use/ba-p/286841 

CMDLET (add-appxprovisionedpackage)

https://docs.microsoft.com/en-us/powershell/module/dism/add-appxprovisionedpackage?view=win10-ps

CMDLET (add-appxpackage)

https://docs.microsoft.com/en-ca/powershell/module/appx/Add-AppxPackage?view=winserver2012r2-ps

Configure International Settings in Windows

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/configure-international-settings-in-windows

 

Christian Wunderlich

PFE

 

Disclaimer
The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.

 

 

Updated May 04, 2020
Version 2.0