Fix qps-ploc generation for store translations (#17526)

* Modified `Generate-PseudoLocalizations.ps1` to find the .xml files.
  (As opposed to .resw for the other translations.)
* Added support for the new format by adding new XPath expressions,
  and stripping comments/attributes as needed.
* Fixed `PreserveWhitespace` during XML loading.
* Fixed compliance with PowerShell's strict mode.

## Validation Steps Performed
Ran it locally and compared the results. 
This commit is contained in:
Leonard Hecker
2024-07-09 00:26:16 +02:00
committed by GitHub
parent bc20225b08
commit 5bbd905ded
2 changed files with 71 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
Get-ChildItem -Recurse -Filter *.resw Get-ChildItem -Recurse -Directory -Filter qps-ploc*
| Where-Object { $_.Directory.Name.StartsWith("qps-ploc") } | Get-ChildItem -Include *.resw,*.xml
| ForEach-Object { | ForEach-Object {
$source = Join-Path $_.Directory "../en-US/$($_.Name)" $source = Join-Path $_.Directory "../en-US/$($_.Name)"
$target = $_ $target = $_

View File

@@ -1,5 +1,5 @@
param( param(
[Parameter(Mandatory=$True)] [Parameter(Mandatory = $True)]
[string]$Path [string]$Path
) )
@@ -55,20 +55,25 @@ $mapping['Y'[0]] = '¥ÝŶΎΥΫỲЎ'
$mapping['z'[0]] = 'źżž' $mapping['z'[0]] = 'źżž'
$mapping['Z'[0]] = 'ŹŻΖŽ' $mapping['Z'[0]] = 'ŹŻΖŽ'
[xml]$content = Get-Content $Path $content = [System.Xml.XmlDocument]::new()
$content.PreserveWhitespace = $true
$content.Load($Path)
function GetPseudoLocalization([string]$key, [string]$value, [string]$comment) {
$locked = $null
if ($comment -match '.*\{Locked=?([^}]*)\}.*') {
$locked = $Matches[1]
}
# Skip {Locked} and {Locked=qps-ploc} entries
if ($locked -and (($locked -eq '') -or $locked.Contains('qps-ploc'))) {
continue
}
foreach ($entry in $content.root.data) {
$value = $entry.value
$comment = $entry.comment ?? ''
$placeholders = @{} $placeholders = @{}
if ($comment.StartsWith('{Locked')) { if ($locked) {
# Skip {Locked} and {Locked=qps-ploc} entries $lockedList = $locked -split ','
if ($comment -match '\{Locked(\}|=[^}]*qps-ploc).*') {
continue
}
$lockedList = ($comment -replace '\{Locked=(.*?)\}.*','$1') -split ','
$placeholderChar = 0xE000 $placeholderChar = 0xE000
# Replaced all locked words with placeholders from the Unicode Private Use Area # Replaced all locked words with placeholders from the Unicode Private Use Area
@@ -86,34 +91,67 @@ foreach ($entry in $content.root.data) {
} }
} }
# We can't rely on $entry.name.GetHashCode() to be consistent across different runs, # We can't rely on $key.GetHashCode() to be consistent across different runs,
# because in the future PowerShell may enable UseRandomizedStringHashAlgorithm. # because in the future PowerShell may enable UseRandomizedStringHashAlgorithm.
$hash = [System.Text.Encoding]::UTF8.GetBytes($entry.name) $hash = [System.Text.Encoding]::UTF8.GetBytes($key)
$hash = [System.Security.Cryptography.SHA1]::Create().ComputeHash($hash) $hash = [System.Security.Cryptography.SHA1]::Create().ComputeHash($hash)
$hash = [System.BitConverter]::ToInt32($hash) $hash = [System.BitConverter]::ToInt32($hash)
# Replace all characters with pseudo-localized characters
$rng = [System.Random]::new($hash) $rng = [System.Random]::new($hash)
$newValue = ''
foreach ($char in $value.ToCharArray()) { $lines = $value.Split("`n")
if ($m = $mapping[$char]) { $lines = $lines | ForEach-Object {
$newValue += $m[$rng.Next(0, $mapping[$char].Length)] # Replace all characters with pseudo-localized characters
} else { $newValue = ''
$newValue += $char foreach ($char in $_.ToCharArray()) {
if ($m = $mapping[$char]) {
$newValue += $m[$rng.Next(0, $mapping[$char].Length)]
}
else {
$newValue += $char
}
}
# Replace all placeholders with their original values
foreach ($kv in $placeholders.GetEnumerator()) {
$newValue = $newValue.Replace($kv.Key, $kv.Value)
}
# Add 40% padding to the end of the string
$paddingLength = [System.Math]::Round(0.4 * $_.Length)
$padding = ' !!!' * ($paddingLength / 4 + 1)
$newValue + $padding.Substring(0, $paddingLength)
}
return $lines -join "`n"
}
if ($path.EndsWith(".resw")) {
foreach ($entry in $content.SelectNodes('/root/data')) {
$comment = $entry.SelectSingleNode('comment')?.'#text' ?? ''
$entry.value = GetPseudoLocalization $entry.name $entry.value $comment
}
}
elseif ($path.EndsWith(".xml")) {
foreach ($parent in $content.DocumentElement.SelectNodes('//*[@_locID]')) {
$locID = $parent.GetAttribute('_locID')
$comment = $parent.SelectSingleNode('comment()[contains(., "_locComment_text")]')?.'#text' ?? ''
foreach ($entry in $parent.SelectNodes('text()')) {
$value = $entry.Value
if ($value.Trim().Length -ne 0) {
$entry.Value = GetPseudoLocalization $locID $value $comment
}
} }
} }
# Replace all placeholders with their original values # Remove all _locComment_text comments
foreach ($kv in $placeholders.GetEnumerator()) { foreach ($entry in $content.DocumentElement.SelectNodes('//comment()[contains(., "_locComment_text")]')) {
$newValue = $newValue.Replace($kv.Key, $kv.Value) $null = $entry.ParentNode.RemoveChild($entry)
} }
# Add 40% padding to the end of the string # Remove all _locID attributes
$paddingLength = [System.Math]::Round(0.4 * $newValue.Length) foreach ($entry in $content.DocumentElement.SelectNodes('//*[@_locID]')) {
$padding = ' !!!' * ($paddingLength / 4 + 1) $entry.RemoveAttribute('_locID')
$newValue += $padding.Substring(0, $paddingLength) }
$entry.value = $newValue
} }
return $content return $content