Setting the default language during Autopilot
Unless you live in the United States, you probably want to deploy Windows using your local language and regional settings. Having dates display properly is always a big help to users 😉
In days of olde, you could configure the Windows language using the unattend XML to deploy the correct settings. Unfortunately in an Autopilot deployment where the device you deploy may never actually be touched until it arrives in the users hands (assuming a vanilla Windows install, and not imaged at the factory), we don't have this option.
Install
I have written a Powershell script that can be deployed as a Win32 app to install the language you choose (during device setup - before account setup), and set it as default.
One quirk of InTune I found is that the installer session runs in the 32bit space - but the Install-Language command is provided by a 64bit module!
To get around this, the first part of the script detects the "bittyness" of the running Powershell session and starts the 64bit version if needed.
Set the $LanguageSetting variable to the language you wish to install. In this case, I'm installing Australian English.
Set the $GeoId value to the target country to set the regional settings. A table of GeoId's can be found here: https://learn.microsoft.com/en-au/windows/win32/intl/table-of-geographical-locations?redirectedfrom=MSDN
When executed, the script will download the language from the Microsoft Store. Note that this may take some time.
Write-Host "Is 64bit PowerShell: $([Environment]::Is64BitProcess)"
Write-Host "Is 64bit OS: $([Environment]::Is64BitOperatingSystem)"
if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
$TranscriptPath = [IO.Path]::Combine($env:ProgramData, "Scripts", "LanguageSetup", "InstallLog (x86).txt")
Start-Transcript -Path $TranscriptPath -Force -IncludeInvocationHeader
write-warning "Running in 32-bit Powershell, starting 64-bit..."
if ($myInvocation.Line) {
&"$env:WINDIR\sysnative\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
}else{
&"$env:WINDIR\sysnative\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args
}
Stop-Transcript
exit $lastexitcode
}
$TranscriptPath = [IO.Path]::Combine($env:ProgramData, "Scripts", "LanguageSetup", "InstallLog.txt")
Start-Transcript -Path $TranscriptPath -Force -IncludeInvocationHeader
$LanguageSetting = "en-AU"
$GeoId = 12
$RebootRequired = $false
Import-Module International
Import-Module LanguagePackManagement
$Languages = Get-InstalledLanguage
$LanguagePresent = $false
foreach ($Language in $Languages) {
if ($Language.Language -eq $LanguageSetting) {
$LanguagePresent = $true
}
}
if ($LanguagePresent -eq $false) {
Write-Host "Installing language $LanguageSetting"
Install-Language -Language $LanguageSetting -CopyToSettings
$RebootRequired = $true
}
if ($(Get-WinSystemLocale).Name -ne $LanguageSetting) {
Write-Host "Setting system locale"
Set-WinSystemLocale -SystemLocale $LanguageSetting
$RebootRequired = $true
}
if ($(Get-Culture).Name -ne $LanguageSetting) {
Write-Host "Setting system culture"
Set-Culture $LanguageSetting
$RebootRequired = $true
}
if ($(Get-WinHomeLocation).GeoId -ne $GeoId) {
Write-Host "Setting home location"
Set-WinHomeLocation -GeoId $GeoId
$RebootRequired = $true
}
if ($(Get-WinUserLanguageList).LanguageTag -ne $LanguageSetting) {
Write-Host "Setting language to $LanguageSetting"
Set-WinUserLanguageList $LanguageSetting -Force
$RebootRequired = $true
}
if ($(Get-SystemPreferredUILanguage) -ne $LanguageSetting) {
Write-Host "Setting UI language"
Set-SystemPreferredUILanguage -Language $LanguageSetting
$RebootRequired = $true
}
if ($RebootRequired -eq $true) {
Write-Host "Reboot required"
}
Stop-Transcript
if ($RebootRequired -eq $true) {
Exit 3010
} else {
Exit 0
}
Once complete the script will return 0 if a reboot is not required, or 3010 if a reboot is needed. Remember to set InTune to reboot based on the return code, as the changes will not take effect until the system as been restarted.
Detection
InTune requires some criteria to detect if the package has been installed. Attach the below script during the detection rules phase.
Remember to update the $LanguageSetting variable to match the install script.
$TranscriptPath = [IO.Path]::Combine($env:ProgramData, "Scripts", "LanguageSetup", "DetectLog.txt")
Start-Transcript -Path $TranscriptPath -Force -IncludeInvocationHeader
Import-Module International
Import-Module LanguagePackManagement
$LanguageSetting = "en-AU"
if (Get-Command Install-Language) {
$Languages = Get-InstalledLanguage
$LanguagePresent = $false
foreach ($Language in $Languages) {
Write-Host "Found installed language $($Language.LanguageId)"
if ($Language.LanguageId -eq $LanguageSetting) {
$LanguagePresent = $true
}
}
if ($LanguagePresent -eq $false) {
Write-Host "$LanguageSetting is not installed"
Stop-Transcript
Exit 1
}
} else {
Write-Host "Missing language install command"
Exit 1
}
$UIPreferred = Get-SystemPreferredUILanguage
if ($UIPreferred -ne $LanguageSetting) {
Write-Host "Preferred UI language is not $LanguageSetting"
Stop-Transcript
Exit 1
}
$Locale = (Get-WinSystemLocale).Name
if ($Locale -ne $LanguageSetting) {
Write-Host "Locale is not $LanguageSetting"
Stop-Transcript
Exit 1
}
Write-Host "All tests passed!"
Stop-Transcript
Exit 0
The return code 0 means that the package is installed and nothing needs to happen, while a non-zero return code means the package was not detected.