Files
bg3-dnd55e-russian-localiza…/scripts/apply-translation-edits.ps1

211 lines
6.8 KiB
PowerShell

param(
[string]$RussianPath = "Mods/DnD 5.5e AIO Russian/Localization/Russian/russian.xml",
[Parameter(Mandatory = $true)]
[string]$EditsPath
)
$ErrorActionPreference = "Stop"
function Read-XmlDocument {
param(
[Parameter(Mandatory = $true)]
[string]$Path
)
$resolvedPath = [System.IO.Path]::GetFullPath($Path)
if (-not (Test-Path -LiteralPath $resolvedPath)) {
throw "XML file was not found: '$resolvedPath'."
}
[xml]$xml = Get-Content -LiteralPath $resolvedPath -Raw
if ($null -eq $xml.SelectSingleNode('/contentList')) {
throw "XML file does not contain '/contentList': '$resolvedPath'."
}
return @{
Path = $resolvedPath
Xml = $xml
}
}
function Get-ContentNodeMap {
param(
[Parameter(Mandatory = $true)]
[xml]$Xml
)
$map = @{}
foreach ($node in $Xml.SelectNodes('/contentList/content')) {
$contentUid = [string]$node.GetAttribute("contentuid")
if ([string]::IsNullOrWhiteSpace($contentUid)) {
continue
}
if ($map.ContainsKey($contentUid)) {
throw "Duplicate contentuid found in target XML: '$contentUid'."
}
$map[$contentUid] = $node
}
return $map
}
function Assert-UniqueEditContentUid {
param(
[AllowEmptyCollection()]
[Parameter(Mandatory = $true)]
[System.Collections.Generic.HashSet[string]]$Seen,
[Parameter(Mandatory = $true)]
[string]$ContentUid,
[Parameter(Mandatory = $true)]
[string]$Section
)
if (-not $Seen.Add($ContentUid)) {
throw "Edits file contains duplicate contentuid '$ContentUid' in '$Section'."
}
}
$russianDocument = Read-XmlDocument -Path $RussianPath
$temporaryRussianPath = "$($russianDocument.Path).tmp"
$validateScriptPath = Join-Path $PSScriptRoot "validate-translation-xml.ps1"
if (-not (Test-Path -LiteralPath $validateScriptPath)) {
throw "Validation script was not found: '$validateScriptPath'."
}
if (Test-Path -LiteralPath $temporaryRussianPath) {
Remove-Item -LiteralPath $temporaryRussianPath -Force
}
Copy-Item -LiteralPath $russianDocument.Path -Destination $temporaryRussianPath -Force
$russianDocument = Read-XmlDocument -Path $temporaryRussianPath
$resolvedEditsPath = [System.IO.Path]::GetFullPath($EditsPath)
if (-not (Test-Path -LiteralPath $resolvedEditsPath)) {
throw "Edits file was not found: '$resolvedEditsPath'."
}
$edits = Get-Content -LiteralPath $resolvedEditsPath -Raw | ConvertFrom-Json -Depth 10
if ($null -eq $edits) {
throw "Edits file is empty or invalid JSON: '$resolvedEditsPath'."
}
$contentListNode = $russianDocument.Xml.SelectSingleNode('/contentList')
if ($null -eq $contentListNode) {
throw "Target russian.xml does not contain '/contentList': '$($russianDocument.Path)'."
}
$nodeMap = Get-ContentNodeMap -Xml $russianDocument.Xml
$updatedEntries = New-Object System.Collections.Generic.List[string]
$addedEntries = New-Object System.Collections.Generic.List[string]
$seenEditContentUids = [System.Collections.Generic.HashSet[string]]::new()
$updates = @()
if ($edits.PSObject.Properties.Name -contains "updates" -and $null -ne $edits.updates) {
$updates = @($edits.updates)
}
foreach ($edit in $updates) {
$contentUid = [string]$edit.contentuid
if ([string]::IsNullOrWhiteSpace($contentUid)) {
throw "Each update entry must contain non-empty 'contentuid'."
}
Assert-UniqueEditContentUid -Seen $seenEditContentUids -ContentUid $contentUid -Section "updates"
if (-not $nodeMap.ContainsKey($contentUid)) {
throw "Target russian.xml does not contain contentuid '$contentUid' for update."
}
$node = $nodeMap[$contentUid]
if ($edit.PSObject.Properties.Name -contains "version" -and -not [string]::IsNullOrWhiteSpace([string]$edit.version)) {
$node.SetAttribute("version", [string]$edit.version)
}
if ($edit.PSObject.Properties.Name -contains "text") {
if ([string]::IsNullOrWhiteSpace([string]$edit.text)) {
throw "Update entry '$contentUid' must contain non-empty 'text' when provided."
}
$node.InnerText = [string]$edit.text
}
$updatedEntries.Add($contentUid) | Out-Null
}
$adds = @()
if ($edits.PSObject.Properties.Name -contains "adds" -and $null -ne $edits.adds) {
$adds = @($edits.adds)
}
if (($updates.Count -eq 0) -and ($adds.Count -eq 0)) {
if (Test-Path -LiteralPath $temporaryRussianPath) {
Remove-Item -LiteralPath $temporaryRussianPath -Force
}
Write-Host "[apply-translation-edits.ps1] No edits requested. Original russian.xml left unchanged."
return
}
foreach ($edit in $adds) {
$contentUid = [string]$edit.contentuid
$version = [string]$edit.version
$text = [string]$edit.text
if ([string]::IsNullOrWhiteSpace($contentUid)) {
throw "Each add entry must contain non-empty 'contentuid'."
}
Assert-UniqueEditContentUid -Seen $seenEditContentUids -ContentUid $contentUid -Section "adds"
if ($nodeMap.ContainsKey($contentUid)) {
throw "Target russian.xml already contains contentuid '$contentUid'; use 'updates' instead of 'adds'."
}
if ([string]::IsNullOrWhiteSpace($version)) {
throw "Add entry '$contentUid' must contain non-empty 'version'."
}
if ([string]::IsNullOrWhiteSpace($text)) {
throw "Add entry '$contentUid' must contain non-empty 'text'."
}
$newNode = $russianDocument.Xml.CreateElement("content")
$newNode.SetAttribute("contentuid", $contentUid)
$newNode.SetAttribute("version", $version)
$newNode.InnerText = $text
[void]$contentListNode.AppendChild($newNode)
$nodeMap[$contentUid] = $newNode
$addedEntries.Add($contentUid) | Out-Null
}
$settings = New-Object System.Xml.XmlWriterSettings
$settings.Encoding = New-Object System.Text.UTF8Encoding($true)
$settings.Indent = $true
$settings.IndentChars = " "
$settings.NewLineChars = "`n"
$settings.NewLineHandling = [System.Xml.NewLineHandling]::Replace
$writer = [System.Xml.XmlWriter]::Create($russianDocument.Path, $settings)
try {
$russianDocument.Xml.WriteTo($writer)
} finally {
$writer.Dispose()
}
try {
& $validateScriptPath -XmlPath $temporaryRussianPath
Move-Item -LiteralPath $temporaryRussianPath -Destination $RussianPath -Force
} finally {
if (Test-Path -LiteralPath $temporaryRussianPath) {
Remove-Item -LiteralPath $temporaryRussianPath -Force
}
}
Write-Host "[apply-translation-edits.ps1] Updated entries: $($updatedEntries.Count); Added entries: $($addedEntries.Count)."
if ($updatedEntries.Count -gt 0) {
Write-Host "[apply-translation-edits.ps1] Updated contentuid: $($updatedEntries -join ', ')"
}
if ($addedEntries.Count -gt 0) {
Write-Host "[apply-translation-edits.ps1] Added contentuid: $($addedEntries -join ', ')"
}