PowerShell: Aus XLIFF eine NAV-Translationsdatei erzeugen

24. August 2015 00:07

Die Rückumwandlung einer überarbeiteten XLIFF-Datei in eine NAV-Translate Datei ist mittels der in PowerShell direkt nutzbaren XML-DOM-Funktionen vergleichsweise sehr schnell möglich, da die Nodes mit den IDs der Sourcelanguage (Quellsprache) und die beiden Übersetzungen hier direkt gelesen werden können.
Als Eingabe ist hierbei nur der Pfad zur XLIFF-Datei erforderlich, der Dateiname der .xlf-Datei wird dabei wegen der folgenden Umwandlung von UTF8 nach OEM 850 mit Suffix "_OEM850.txt" ergänzt.

Die NAV-Sprachcodes ergeben sich dabei aus den ISO 639-Sprachcodes der XLIFF (die Switch-Befehle zum Mappen der Codes ggf. nach Bedarf erweitern), da für Österreich (de -> DEA -> A3079) kein separater 'de'-Code vorhanden ist, muss das Skript hierfür in den Switch-Befehlen angepasst werden (de -> DEU -> A1031 auskommentieren) , wenn IDs mit diesen Codes erzeugt werden sollen bzw. in der XLIFF vorhanden sind.

Bei manuellen Änderungen in der XLIFF mit ",',<,> und & (XML Reserved Characters) beachten, dass diese Zeichen maskiert werden müssen (Link). In der NAV-Translationsdatei werden diese dann richtig dargestellt.

Durch die Verwendung des Industriestandards XLIFF ist es mit dieser und der Funktion XLIFF-Datei aus NAV-Translationsdatei erzeugen somit problemlos möglich, Übersetzungen auch durch externe Dienstleister durchführen zu lassen und anschließend in NAV zu übernehmen. Aktuelle Objektversionen ab NAV 2013 können per Cmdlets bedient werden, alternativ bzw. in älteren NAV-Versionen im Objektdesigner den Objektdatum, Zeit und Geändert-Status der betroffenen Objekte per Report sichern, die NAV-Translationsdatei importieren und anschließend den Objektstatus wieder zurückschreiben.

Ausgangsdatei
XLFToTrans.jpg

Überarbeitete Datei
XLFToTrans1.png


Code:
function XLFtoNAVtransFile
{
$XLFtransfile = Read-host "Path of XLIFF file"
$FileExtension = [System.IO.Path]::GetExtension($XLFtransfile)
if (!($FileExtension -eq '.xlf')) {Throw 'Please use a XLIFF file with .xlf extension for this script.'}
$NAVoutfile = [System.IO.Path]::GetDirectoryName($XLFtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($XLFtransfile) + '.txt'
if ($XLFtransfile -eq $NAVoutfile)
  {
   Throw "Source and target file are identical. Source: $XLFtransfile Target: $NAVoutfile"
  }

if (test-path $NAVoutfile) {remove-item -path $NAVoutfile}

$xml = [xml] (get-content $XLFtransfile -Encoding UTF8)

foreach ($XLFnode in $xml.GetElementsByTagName('trans-unit'))
{
$sourceid = $XLFnode.getAttribute("id")

ForEach ($item in $XLFnode)
{
$sourceLanguage = $item.source.'lang'.ToString()
Switch ($SourceLanguage)
    {
    "dk" {$NAVSourcelangCode = '-A1030-'}
    "de" {$NAVSourcelangCode = '-A1031-'}
    "en" {$NAVSourcelangCode = '-A1033-'}
    "es" {$NAVSourcelangCode = '-A1034-'}
    "fi" {$NAVSourcelangCode = '-A1035-'}
    "fr" {$NAVSourcelangCode = '-A1036-'}
    "it" {$NAVSourcelangCode = '-A1040-'}
    "nl" {$NAVSourcelangCode = '-A1043-'}
    "no" {$NAVSourcelangCode = '-A1044-'}
    "pl" {$NAVSourcelangCode = '-A1045-'}
    "pt" {$NAVSourcelangCode = '-A1046-'}
    "se" {$NAVSourcelangCode = '-A1053-'}
    "gsw" {$NAVSourcelangCode = '-A2055-'}
    "en-gb" {$NAVSourcelangCode = '-A2057-'}
    # "de" {$NAVlangCode = '-A3079-'} # activate in AT and deactivate de -> A1031
    default {Throw "Please assign a NAV translation code for $NAVSourcelangCode  in the script"}
    }
$sourceCaption = $item.source.'#text'.ToString()
$sourceline = $sourceid + ':' + $sourcecaption
Out-File $NAVoutfile -inputobject $sourceline -Encoding UTF8 -force -Append -Width 1024

$TargetLanguage = $item.target.'lang'.ToString()
$TargetCaption = $item.target.'#text'.ToString()
Switch ($TargetLanguage)
    {
    "dk" {$NAVTargetlangCode = '-A1030-'}
    "de" {$NAVTargetlangCode = '-A1031-'}
    "en" {$NAVTargetlangCode = '-A1033-'}
    "es" {$NAVTargetlangCode = '-A1034-'}
    "fi" {$NAVTargetlangCode = '-A1035-'}
    "fr" {$NAVTargetlangCode = '-A1036-'}
    "it" {$NAVTargetlangCode = '-A1040-'}
    "nl" {$NAVTargetlangCode = '-A1043-'}
    "no" {$NAVTargetlangCode = '-A1044-'}
    "pt" {$NAVTargetlangCode = '-A1046-'}
    "se" {$NAVTargetlangCode = '-A1053-'}
    "gsw" {$NAVTargetlangCode = '-A2055-'}
    "en-gb" {$NAVTargetlangCode = '-A2057-'}
    # "de" {$NAVlangCode = '-A3079-'} # activate in AT and deactivate de -> A1031
    default {Throw "Please assign a NAV translation code for $NAVTargetlangCode in the script"}
    }

$targetid = $sourceid -replace $NAVSourcelangCode, $NAVTargetlangCode
$targetline = $targetid + ':' + $targetcaption
Out-File $NAVoutfile -inputobject $targetline -Encoding UTF8 -force -Append -Width 1024
}
}
$sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
$targetEncoding = [System.Text.Encoding]::GetEncoding(850)
$convertedFileName = [System.IO.Path]::GetDirectoryName($NAVoutfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVoutfile) +"_OEM850" + [System.IO.Path]::GetExtension($NAVoutfile)
if (Test-Path $convertedFileName) {Remove-Item $convertedFileName}
$convertedfile = New-Item -path $convertedFileName -type file
$textfile = [System.IO.File]::ReadAllText($NAVoutfile, $sourceencoding)
[System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
if (Test-Path $NavOutFile) {Remove-Item $NAVoutfile}
Write-host $XLFtransfile 'converted to' $convertedFileName
}
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Re: PowerShell: Aus XLIFF eine NAV-Translationsdatei erzeuge

25. Januar 2019 10:01

Bei dieser Variante kommt die Zusatzfrage
Do you want to write the source language to the NAV file (yes,no) ?

damit man optional die Ausgangssprache weglassen kann, falls man Bedenken hat, dass die nach der Übersetzung ebenfalls hier und da versehentlich zur Zielsprache wurde :wink: . Somit kann man bei "no" ein Überschreiben der Captions der Ausgangssprache verhindern.

Code:
function XLFtoNAVtransFile2
{

$XLFtransfile = Read-host "Path of XLIFF file"
$FileExtension = [System.IO.Path]::GetExtension($XLFtransfile)
if (!($FileExtension -eq '.xlf')) {Throw 'Please use a XLIFF file with .xlf extension for this script.'}


$NAVoutfile = [System.IO.Path]::GetDirectoryName($XLFtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($XLFtransfile) + '.txt'
if ($XLFtransfile -eq $NAVoutfile)
  {
   Throw "Source and target file are identical. Source: $XLFtransfile Target: $NAVoutfile"
  }

if (test-path $NAVoutfile) {remove-item -path $NAVoutfile}

[ValidateSet('yes','no')]$WriteSourceCaptions = Read-Host "Do you want to write the source language to the NAV file (yes,no) ?"


$xml = [xml] (get-content $XLFtransfile -Encoding UTF8)

foreach ($XLFnode in $xml.GetElementsByTagName('trans-unit'))
{
$sourceid = $XLFnode.getAttribute("id")

ForEach ($item in $XLFnode)
{
$sourceLanguage = $item.source.'lang'.ToString()
Switch ($SourceLanguage)
    {
    "dk" {$NAVSourcelangCode = '-A1030-'}
    "de" {$NAVSourcelangCode = '-A1031-'}
    "en" {$NAVSourcelangCode = '-A1033-'}
    "es" {$NAVSourcelangCode = '-A1034-'}
    "fi" {$NAVSourcelangCode = '-A1035-'}
    "fr" {$NAVSourcelangCode = '-A1036-'}
    "it" {$NAVSourcelangCode = '-A1040-'}
    "nl" {$NAVSourcelangCode = '-A1043-'}
    "no" {$NAVSourcelangCode = '-A1044-'}
    "pl" {$NAVSourcelangCode = '-A1045-'}
    "pt" {$NAVSourcelangCode = '-A1046-'}
    "se" {$NAVSourcelangCode = '-A1053-'}
    "gsw" {$NAVSourcelangCode = '-A2055-'}
    "en-gb" {$NAVSourcelangCode = '-A2057-'}
    # "de" {$NAVlangCode = '-A3079-'} # activate in AT and deactivate de -> A1031
    default {Throw "Please assign a NAV translation code for $NAVSourcelangCode  in the script"}
    }
$sourceCaption = $item.source.'#text'.ToString()
$sourceline = $sourceid + ':' + $sourcecaption

if ($WriteSourceCaptions -eq 'yes')
{Out-File $NAVoutfile -inputobject $sourceline -Encoding UTF8 -force -Append -Width 1024}

$TargetLanguage = $item.target.'lang'.ToString()
$TargetCaption = $item.target.'#text'.ToString()
Switch ($TargetLanguage)
    {
    "dk" {$NAVTargetlangCode = '-A1030-'}
    "de" {$NAVTargetlangCode = '-A1031-'}
    "en" {$NAVTargetlangCode = '-A1033-'}
    "es" {$NAVTargetlangCode = '-A1034-'}
    "fi" {$NAVTargetlangCode = '-A1035-'}
    "fr" {$NAVTargetlangCode = '-A1036-'}
    "it" {$NAVTargetlangCode = '-A1040-'}
    "nl" {$NAVTargetlangCode = '-A1043-'}
    "no" {$NAVTargetlangCode = '-A1044-'}
    "pt" {$NAVTargetlangCode = '-A1046-'}
    "se" {$NAVTargetlangCode = '-A1053-'}
    "gsw" {$NAVTargetlangCode = '-A2055-'}
    "en-gb" {$NAVTargetlangCode = '-A2057-'}
    # "de" {$NAVlangCode = '-A3079-'} # activate in AT and deactivate de -> A1031
    default {Throw "Please assign a NAV translation code for $NAVTargetlangCode in the script"}
    }

$targetid = $sourceid -replace $NAVSourcelangCode, $NAVTargetlangCode
$targetline = $targetid + ':' + $targetcaption
Out-File $NAVoutfile -inputobject $targetline -Encoding UTF8 -force -Append -Width 1024
}
}
$sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
$targetEncoding = [System.Text.Encoding]::GetEncoding(850)
$convertedFileName = [System.IO.Path]::GetDirectoryName($NAVoutfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVoutfile) +"_OEM850" + [System.IO.Path]::GetExtension($NAVoutfile)
if (Test-Path $convertedFileName) {Remove-Item $convertedFileName}
$convertedfile = New-Item -path $convertedFileName -type file
$textfile = [System.IO.File]::ReadAllText($NAVoutfile, $sourceencoding)
[System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
if (Test-Path $NavOutFile) {Remove-Item $NAVoutfile}
Write-host $XLFtransfile 'converted to' $convertedFileName
}

Re: PowerShell: Aus XLIFF eine NAV-Translationsdatei erzeuge

12. Januar 2023 12:53

Moin!

Anscheinend gibt es einen Unterschied bei den XLF-Dateien von BC21.
In dem o. g. Script wird die Angabe der Sprachen in dem Element "source" bzw. "target" erwartet.
Bei den in BC21 bereitgestellten Language Modules stehen die Sprachen jedoch einmalig in der dritten Zeile als Parameter ("source-language" / "target-language") des Elements "file".

Bestünde die Möglichkeit, dass dieses Script in einer an BC21 angepassten Struktur zur Verfügung gestellt werden könnte?
Das würde mir/uns sehr helfen, daher bedanke ich mich schon jetzt für jede Unterstützung.

Re: PowerShell: Aus XLIFF eine NAV-Translationsdatei erzeuge

12. Januar 2023 13:57

Timo Lässer hat geschrieben:In dem o. g. Script wird die Angabe der Sprachen in dem Element "source" bzw. "target" erwartet.
Bei den in BC21 bereitgestellten Language Modules stehen die Sprachen jedoch einmalig in der dritten Zeile als Parameter ("source-language" / "target-language") des Elements "file".

Die Sprachen stehen immer in (Beispiel: source-language="en-US" target-language="da-DK"), in "source" bzw. "target" jeweils die zur Trans-Unit-ID gehörenden übersetzten Inhalte.
Das ist unverändert, BC nutzt weiterhin XLIFF 1.2, lediglich <?xml version="1.0" encoding="utf-8"?> steht zusätzlich als erste Zeile drin. Dadurch rutschen source-language/target-language von Zeile 2 in Zeile 3.
The XLIFF file
Ich kann gerne eine Variante mit <?xml version="1.0" encoding="utf-8"?> erstellen, die Trans-Unit-IDs sind aber zwischen C/AL und AL inkompatibel (Beispiel in AL: trans-unit id="PageExtension 1255613137 - Property 2879900210)", rückkonvertieren für NAV kann man da ohnehin nichts.

Re: PowerShell: Aus XLIFF eine NAV-Translationsdatei erzeuge

12. Januar 2023 14:19

Kowa hat geschrieben:die Trans-Unit-IDs sind aber zwischen C/AL und AL inkompatibel (Beispiel in AL: trans-unit id="PageExtension 1255613137 - Property 2879900210)", rückkonvertieren für NAV kann man da ohnehin nichts.

Dann erspare dir die Mühe und ich wende mich an IDYN.
Eigentlich sollte OMA365 v16.00 in der Lage sein, die *.xlf aus dem Source Code einer Extension einzulesen.
OMA erkennt auch ordnungsgemäß die "Base Application.de-DE.xlf" aus der Extension "German language (Germany).Source", importiert jedoch die "target" Captions nicht in die Translation Tool Line.