Generator XML pakietów językowych ODT
📦 Office 365 POWERSHELL ChrisTitusTechTworzy plik konfiguracyjny XML dla Office Deployment Tool (ODT) do wdrożenia dodatkowych pakietów językowych. Automatycznie wykrywa zainstalowane języki i generuje odpowiedni config.xml.
Opis
This script will create a new xml file that should be used to deploy additional language packs to computers with Office 365 ProPlus already installed.
📄 Generate-ODTLanguagePackXML.ps1
🕒 2026-04-13
📦 Źródło: christitustech
Generate-ODTLanguagePackXML.ps1
function Generate-ODTLanguagePackXML {
<#
.SYNOPSIS
Create an ODT configuration file to deploy additional language packs
.DESCRIPTION
This script will create a new xml file that should be used to deploy additional
language packs to computers with Office 365 ProPlus already installed.
.PARAMETER TargetFilePath
The full path where to save the file.
.PARAMETER OfficeClientEdition
The bit of Office. Choose between 32 and 64.
.PARAMETER Languages
The list of available languages.
.EXAMPLE
Generate-ODTLanguagePackXML -TargetFilePath $env:temp\LanguagePacks.xml -Languages de-de,es-es,fr-fr -OfficeClientEdition 64
A new xml file will be created in the temp directory called LanguagePacks.xml which will be used to install the 64-bit
editions of German, Spanish, and French language packs.
.EXAMPLE
Generate-ODTLanguagePackXML -TargetFilePath $env:temp\LanguagePacks.xml -Languages de-de,es-es,fr-fr | fl
A new xml file will be created in the temp directory called LanguagePacks.xml which will be used to install the 32-bit
editions of German, Spanish, and French language packs. The output of the xml file will be displayed on the PowerShell console.
.NOTES
Date created: 03-02-2017
Date modified: 03-02-2017
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(ValueFromPipelineByPropertyName=$true)]
[String]$TargetFilePath = $NULL,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[ValidateSet("32","64")]
[string]$OfficeClientEdition = '32',
[Parameter(ValueFromPipelineByPropertyName=$true)]
[ValidateSet("en-us","MatchOS","ar-sa","bg-bg","zh-cn","zh-tw","hr-hr","cs-cz","da-dk","nl-nl","et-ee","fi-fi","fr-fr","de-de","el-gr","he-il","hi-in","hu-hu","id-id","it-it",
"ja-jp","kk-kz","ko-kr","lv-lv","lt-lt","ms-my","nb-no","pl-pl","pt-br","pt-pt","ro-ro","ru-ru","sr-latn-rs","sk-sk","sl-si","es-es","sv-se","th-th",
"tr-tr","uk-ua","vi-vn")]
[string[]]$Languages
)
begin {
[string]$tempStr = $MyInvocation.MyCommand.Path
$scriptPath = GetScriptPath
}
process{
if ($TargetFilePath) {
$folderPath = Split-Path -Path $TargetFilePath -Parent
$fileName = Split-Path -Path $TargetFilePath -Leaf
if ($folderPath) {
[system.io.directory]::CreateDirectory($folderPath) | Out-Null
}
}
[System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument
#Generate the language pack xml file
odtAddLanguagePackProduct -ConfigDoc $ConfigFile -Platform $OfficeClientEdition -LanguageIds $Languages
$formattedXml = Format-XML ([xml]($ConfigFile)) -indent 4
if ($TargetFilePath) {
$formattedXml | Out-File -FilePath $TargetFilePath
}
#Display the results to the console
$Result = New-Object -TypeName PSObject
Add-Member -InputObject $Result -MemberType NoteProperty -Name "TargetFilePath" -Value $TargetFilePath
Add-Member -InputObject $Result -MemberType NoteProperty -Name "LanguageIds" -Value $Languages
Add-Member -InputObject $Result -MemberType NoteProperty -Name "ConfigurationXML" -Value $formattedXml
$Result
}
}
function odtAddLanguagePackProduct() {
param(
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[System.XML.XMLDocument]$ConfigDoc = $NULL,
[Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$true)]
[string]$ProductId = "LanguagePack",
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true)]
[string]$Platform = $NULL,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[string[]]$LanguageIds = @()
)
[System.XML.XMLElement]$ConfigElement=$NULL
if($ConfigDoc.Configuration -eq $null){
$ConfigElement=$ConfigDoc.CreateElement("Configuration")
$ConfigDoc.appendChild($ConfigElement) | Out-Null
}
[System.XML.XMLElement]$AddElement=$NULL
if($ConfigFile.Configuration.Add -eq $null){
$AddElement=$ConfigDoc.CreateElement("Add")
$ConfigDoc.DocumentElement.appendChild($AddElement) | Out-Null
} else {
$AddElement = $ConfigDoc.Configuration.Add
}
if ($Platform) {
$AddElement.SetAttribute("OfficeClientEdition", $Platform) | Out-Null
}
[System.XML.XMLElement]$ProductElement = $ConfigDoc.Configuration.Add.Product | where { $_.ID -eq $ProductId }
if($ProductId){
if($ProductElement -eq $null){
[System.XML.XMLElement]$ProductElement=$ConfigDoc.CreateElement("Product")
$AddElement.appendChild($ProductElement) | Out-Null
$ProductElement.SetAttribute("ID", $ProductId) | Out-Null
}
}
foreach($LanguageId in $LanguageIds){
if ($LanguageId) {
if ($LanguageId.Length -gt 0) {
[System.XML.XMLElement]$LanguageElement = $ProductElement.Language | where { $_.ID -eq $LanguageId }
if($LanguageElement -eq $null){
[System.XML.XMLElement]$LanguageElement=$ConfigFile.CreateElement("Language")
$ProductElement.appendChild($LanguageElement) | Out-Null
$LanguageElement.SetAttribute("ID", $LanguageId.ToString().ToLower()) | Out-Null
}
}
}
}
}
Function Remove-ODTProductToAdd{
<#
.SYNOPSIS
Removes an existing product to add from the configuration file
.PARAMETER ProductId
Required. ID must be set to a valid ProductRelease ID.
See https://support.microsoft.com/en-us/kb/2842297 for valid ids.
.PARAMETER TargetFilePath
Full file path for the file to be modified and be output to.
.Example
Remove-ODTProductToAdd -ProductId "O365ProPlusRetail" -TargetFilePath "$env:Public/Documents/config.xml"
Removes the ProductToAdd with the ProductId 'O365ProPlusRetail' from the XML Configuration file
#>
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true, Position=0)]
[string] $ConfigurationXML = $NULL,
[Parameter(ValueFromPipelineByPropertyName=$true)]
[string[]] $ProductId = "Unknown",
[Parameter(ValueFromPipelineByPropertyName=$true)]
[string] $TargetFilePath,
[Parameter(ParameterSetName="All", ValueFromPipelineByPropertyName=$true)]
[switch] $All
)
Process{
$TargetFilePath = GetFilePath -TargetFilePath $TargetFilePath
foreach($Product in $ProductId){
if ($Product -eq "Unknown") {
$Product = SelectProductId
}
$Product = IsValidProductId -ProductId $Product
#Load the file
[System.XML.XMLDocument]$ConfigFile = New-Object System.XML.XMLDocument
if ($TargetFilePath) {
$ConfigFile.Load($TargetFilePath) | Out-Null
} else {
if ($ConfigurationXml)
{
$ConfigFile.LoadXml($ConfigurationXml) | Out-Null
$global:saveLastConfigFile = $NULL
$global:saveLastFilePath = $NULL
}
}
$global:saveLastConfigFile = $ConfigFile.OuterXml
#Check that the file is properly formatted
if($ConfigFile.Configuration -eq $null){
throw $NoConfigurationElement
}
if($ConfigFile.Configuration.Add -eq $null){
throw $NoAddElement
}
if (!($All)) {
#Set the desired values
[System.XML.XMLElement]$ProductElement = $ConfigFile.Configuration.Add.Product | Where { $_.ID -eq $Product }
if($ProductElement -ne $null){
$ConfigFile.Configuration.Add.removeChild($ProductElement) | Out-Null
}
if ($ConfigFile.Configuration.Add.Product.Count -eq 0) {
[System.XML.XMLElement]$AddNode = $ConfigFile.SelectSingleNode("/Configuration/Add")
if ($AddNode) {
$ConfigFile.Configuration.removeChild($AddNode) | Out-Null
}
}
} else {
$ConfigFile.Configuration.Add.RemoveAll() | Out-Null
}
$ConfigFile.Save($TargetFilePath) | Out-Null
$global:saveLastFilePath = $TargetFilePath
if (($PSCmdlet.MyInvocation.PipelineLength -eq 1) -or `
($PSCmdlet.MyInvocation.PipelineLength -eq $PSCmdlet.MyInvocation.PipelinePosition)) {
Write-Host
Format-XML ([xml](cat $TargetFilePath)) -indent 4
Write-Host
Write-Host "The Office XML Configuration file has been saved to: $TargetFilePath"
} else {
$results = new-object PSObject[] 0;
$Result = New-Object –TypeName PSObject
Add-Member -InputObject $Result -MemberType NoteProperty -Name "TargetFilePath" -Value $TargetFilePath
$Result
}
}
}
}
Function GetScriptPath() {
[string]$scriptPath = "."
if ($PSScriptRoot) {
$scriptPath = $PSScriptRoot
} else {
$scriptPath = (Get-Item -Path ".\").FullName
}
return $scriptPath
}
function Format-XML ([xml]$xml, $indent=2) {
$StringWriter = New-Object System.IO.StringWriter
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
$xmlWriter.Formatting = "indented"
$xmlWriter.Indentation = $Indent
$xml.WriteContentTo($XmlWriter)
$XmlWriter.Flush()
$StringWriter.Flush()
Write-Output $StringWriter.ToString()
}