PowerShell: Translations-Datei via Translator Hub übersetzen

5. Februar 2016 11:24

Mit diesem Skript können auf direktem Wege die englischen Captions aus einer NAV-Translations-Datei über den Microsoft Translator Hub über eine REST-Abfrage in eine beliebige unterstützte Zielsprache (Translator Language Codes) maschinell übersetzt werden. Die REST-Code im Skript stammt weitgehend von hier (Nachtrag 31.08 2022: dezidierter MSDN-Link ist mittlerweile verwaist, geht daher nun zu web.archive.org), eine kleine Korrektur beim $uri-String war erforderlich ($TextEncoded statt $Text, sonst z.B. Fehler bei allen Captions mit #) und die CategoryID ergänzt.

Ich habe mich hier auf Englisch als Quellsprache beschränkt, weil für andere Ausgangssprachen die Übersetzungsergebnisse deutlich schlechter sind. Das kann aber natürlich auch leicht im Skript geändert werden.

Die über den NAV-Client erzeugte OEM850 Ausgangsdatei wird erst UTF-8 gewandelt, dann pro Zeile die Übersetzung aus dem Hub geholt und mit der geänderten Code-ID und der übersetzten Caption in eine neue UTF-8-Datei geschrieben, aus der dann am Schluss eine OEM850-Datei erzeugt wird, die man dann theoretisch direkt per Cmdlet oder über den Client in NAV-Objekte importieren könnte. Alternativ kann ab Version NAV 2013 R2 die UTF-8 Datei auch direkt auf dem Server abgelegt werden (How to: Add Translated Strings for Conflicting Text Encoding Formats). Wenn die Zielsprache Zeichen außerhalb von Codepage 850 für Westeuropa enthält, muss dieses sogar so passieren, falls bei den Windows Regionen/Gebieten keine andere Region gewählt wurde, die diese Sonderzeichen enthält.

Da die Datei nach der maschinellen Übersetzung je nach Umfang und "Problemcaptions" meist noch an vielen Stellen nachbearbeitet werden muss, ist die UTF8-Version besser geeignet falls das außerhalb von NAV erfolgen soll, dann erst am Schluss die manuelle OEM850-Konvertierung vornehmen :wink: .

Formatierungsfehler in den Übersetzungen
  • Captions mit # (wie in Laufzeitfenstern häufiger anzutreffen) werden beim Übersetzen dermaßen ramponiert, dass ich diese ab diesem Zeichen abschneide, weil die Nachbearbeitung so etwas weniger aufwendig ist.
    Im Bild ist der Effekt zu sehen, wenn ohne Abschneiden übersetzt wird.

Lattenfehler.png

Nach einem # in einer Caption wird also bis zum Zeilenende nichts übersetzt.

Die Wörter sollte man in solchen Captions deshalb möglichst nach vorne stellen, z.B. so
MeinText #1#######

und nicht
#1####### MeinText


  • &-Shortcutzeichen in Pages und Forms, Optionswerte und Filterausdrücke müssen auch allesamt nach der Übersetzung von schädlichen Leerzeichen "befreit" werden, bei den Optionswerten kommen die meist erforderlichen Großbuchstaben am Anfang noch dazu. Die &-Shortcutzeichen stören außerdem teilweise die Übersetzungen erheblich, ggf. also vorab entfernen und manuell nachtragen.
  • Alle DateFilter-Ausdrücke nachbearbeiten (bzw. generell alle Captions mit <>-Zeichen), diese erhalten sonst auch Leerstellen und zusätzliche =""- Einschübe.

Voraussetzungen zur Nutzung:
  • Azure Marketplace Account Azure-Account (DataMarket-Account nur noch verwendbar bis 31.03.2017, dann wird der DataMarket eingestellt und es ist ein regulärer Azure-Account erforderlich (Link))
  • Translator Hub im Azure Marketplace-Account (bzw. Azure-Account) freigeschaltet (bis zu 2.000.000 Zeichen pro Monat sind kostenlos)
    TranslatorKontingent.png
  • Das Skript mit selbstgewähltem Application-Name (das ist dann die ClientID im Skript, nicht die Azure-Kunden-ID, der "Primäre Kontoschlüssel" wird ebenfalls nicht benötigt) registiert und (mit zugehörigem ClientSecret, dies ist auch frei wählbar) versehen.
    ClientID und ClientSecret müssen im Skript danach individell an diese Werte angepasst werden. :greenarrow: Neue Anmeldemethode siehe Folgebeitrag
    MachineTranslateEDIT.png
  • Optional: Wenn man den Hub vorab trainiert hat und das System für die Zielsprache den Status "Deployed" hat, kann man zusätzlich die individuelle CategoryID bei der Abfrage mitgeben um die Übersetzungergebnisse zu verbessern (PDF: Translator Hub API Guide). Ansonsten muss man diese weglassen und es wird dann der Bing-Standardübersetzer verwendet.

Das Access-Token wird pro Zeile im Skript jeweils neu übertragen, da diese nur 10 Minuten gültig sind und die Abarbeitung einer kompletten Add-on-Datei nicht überleben :-). Bei kleinen Dateihäppchen könnte man den Codeblock auch außerhalb der ForEach-Schleife legen oder eleganter in der Schleife den Ablauf überwachen und rechtzeitig neu übertragen.
MachineTranslateIncomingTokenExpired.png


Alte Skriptversion, hier nur noch zu Vergleichszwecken. Azure DataMarket ist nicht mehr im Betrieb, die Anmelde- und Abrufverfahren haben sich geändert. Die neue Version ist hier im Folgebeitrag.
Code:
Function MTfromNAVtranslateFile
{

    Function WriteToFile
    {
        out-file $TranslatedfileName -inputobject $args -force -append -Width 1024 -Encoding utf8
    }
       
    $NAVtransfile = Read-host "Existing NAV translation file with ENU -A1033- Captions"
   $WorkingFolder = Split-Path -Parent $NAVtransfile
     
    $lines = Get-Content $NAVtransfile | Measure-Object –Line
    $Nooflines = $lines.Lines
    write-host "File has $Nooflines lines"
             
   $ENUlines = Get-Content $NAVtransfile | select-string -pattern "-A1033-" -Allmatches -CaseSensitive | Measure-Object –Line
    $NoofENUlines = $ENUlines.Lines
    write-host "File has $NoofENUlines ENU lines (Code A1033)"

    $SourceLangCode = '-A1033-' # en = ENU

    $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
    $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)

    $convertedFileName = [System.IO.Path]::GetDirectoryName($NAVtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVtransfile) +"_UTF8" + [System.IO.Path]::GetExtension($NAVtransfile)

    if (Test-Path $convertedFileName) {Remove-Item $convertedFileName}

    $convertedBaseName =  Split-Path -Leaf $convertedFileName
    $convertedfile = New-Item -path "$WorkingFolder\$convertedBaseName" -type file -Force

    $textfile = [System.IO.File]::ReadAllText($NAVtransfile, $sourceencoding)
    [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
    Write-host $NAVtransfile 'OEM850 converted to UTF8' $convertedFileName
                   
    $TargetLanguage = Read-host "Target Language: de,es,fi,fr,nl,no,pt,sv,en-gb,..."

    # Supported Translator Codes: https://msdn.microsoft.com/en-us/library/hh456380.aspx
    Switch ($TargetLanguage)
    {
        "de" {$NAVTargetlangCode = '-A1031-'}
        "es" {$NAVTargetlangCode = '-A1034-'}
        "fi" {$NAVTargetlangCode = '-A1035-'}
        "fr" {$NAVTargetlangCode = '-A1036-'}
        "nl" {$NAVTargetlangCode = '-A1043-'}
        "no" {$NAVTargetlangCode = '-A1044-'}
        "pt" {$NAVTargetlangCode = '-A1046-'}
        "sv" {$NAVTargetlangCode = '-A1053-'}
        # "gsw" {$NAVTargetlangCode = '-A2055-'} Swiss German currently not supported
        "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"}
    }



    $TranslatedFileName = [System.IO.Path]::GetDirectoryName($NAVtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVtransfile) +"_$TargetLanguage" + [System.IO.Path]::GetExtension($NAVtransfile)


    foreach ($line in [System.IO.File]::ReadLines($convertedFileName))
    {
        $SourceTextLine = $line.ToString()
        if ($SourceTextLine.contains($SourceLangCode))
        {
            #region Construct Azure Datamarket access_token
            #Get ClientId and Client_Secret from https://datamarket.azure.com/developer/applications/
            #Refer obtaining AccessToken (http://msdn.microsoft.com/en-us/library/hh454950.aspx)

            ### Use your own account credentials here #########
            # Note ClientID is the registered application id !
            # Use the app's designated client_Secret
            #################################################

            $ClientID = '<---------------------->'
            $client_Secret = '<---------------------->'
           

           
            # If ClientId or Client_Secret has special characters, UrlEncode before sending request
            $clientIDEncoded = [System.Web.HttpUtility]::UrlEncode($ClientID)
            $client_SecretEncoded = [System.Web.HttpUtility]::UrlEncode($client_Secret)

            #Define uri for Azure Data Market
            $Uri = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"

            #Define the body of the request
            $Body = "grant_type=client_credentials&client_id=$clientIDEncoded&client_secret=$client_SecretEncoded&scope=http://api.microsofttranslator.com"

            #Define the content type for the request
            $ContentType = "application/x-www-form-urlencoded"

            #Invoke REST method.  This handles the deserialization of the JSON result.  Less effort than invoke-webrequest
            $admAuth=Invoke-RestMethod -Uri $Uri -Body $Body -ContentType $ContentType -Method Post

            #Construct the header value with the access_token just recieved
            $HeaderValue = "Bearer " + $admauth.access_token
            #endregion

           
            $TargetLine = ''
            Write-host "Source line $SourceTextLine"
             
               
           
            $pos1 = $SourceTextLine.IndexOf(":")

                 
            # Start-Sleep -Seconds 1 -verbose
            $SourceCodestringID = $SourceTextLine.Substring(0,$pos1)

           
           
            $SourceCaption = $SourceTextLine.Substring($pos1 + 1)
            Write-host "$SourceCaption" -ForegroundColor Green
           
            # Cut off trailing #1###,#2### etc,as these are battered in the translation process, but not if at first pos)
            $posHashKey = $SourceCaption.IndexOf("#")
            $TrailingSourceCaption = '';
            if ($posHashKey -gt 1)
            {
                $TrailingSourceCaption = $SourceCaption.Substring($posHashKey)
                $SourceCaption =  $SourceCaption.Substring(0,$posHashKey)
            }
            $TargetCodestringID = $SourceCodestringID -replace $SourceLangCode,$NAVTargetLangCode
            $TargetTextLine = ''
            Write-host "$TargetCodestringID" -ForegroundColor Yellow

           
                #region Construct and invoke REST request to Microsoft Translator Service
                [string] $text = $SourceCaption;
                [string] $textEncoded = [System.Web.HttpUtility]::UrlEncode($text)
                [string] $from = "en";
                [string] $to = $TargetLanguage;
                # Use category only if translation language pair has been deployed in the hub, otherwise without (Bing standard is used then)
                [string] $uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + $textEncoded + "&from=" + $from + "&to=" + $to
                #[string] $uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + $textEncoded + "&from=" + $from + "&to=" + $to + "&category=xxxxInsertYourCodeHerexxxx"

            $result = Invoke-RestMethod -Uri $uri -Headers @{Authorization = $HeaderValue}
            #endregion
       
            $result.string.'#text'
            $TargetTextLine = $result.string.'#text'
            $TranslatedLine = $TargetCodestringID + ':' + $TargetTextLine + $TrailingSourceCaption
            Write-host "$TargetTextLine$TrailingSourceCaption" -ForegroundColor Yellow
            WriteToFile $TranslatedLine
            #write-host "Waiting 2 seconds..."
            # Start-Sleep -Seconds 2
           
        }
    }
     
     if (Test-Path $translatedfilename)
     {   
        $translatedfilename = resolve-path $translatedfilename
        $WorkingFolder = Split-Path -Parent $translatedfilename
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
           
        $OEM850FileName = [System.IO.Path]::GetFileNameWithoutExtension($translatedfilename) +"_OEM850" + [System.IO.Path]::GetExtension($translatedfilename)
        $OEM850file = New-Item -path "$WorkingFolder\$OEM850FileName" -type file
           
        $UTF8file = [System.IO.File]::ReadAllText($translatedfilename, $sourceencoding)
        [System.IO.File]::WriteAllText($OEM850file, $UTF8file, $targetencoding)
        Write-host $translatedfilename  'converted to' $OEM850FileName
     }
 
   
 
}


Anzeige zur Laufzeit mit Holländisch
HubTranslatorLaufzeitMitNL.png

Beispiele für Übersetzungen in den erzeugten Dateien. Der Translator Hub wurde vorab für die Zielsprachen nl, es und fr mit den vorhandenen NAV-Standardcaptions mittels XLIFFs trainiert (.xlf) und die zugehörige CategoryID im $uri-Abfragestring genutzt.

Niederländisch NLD Code A1043
OPP_ENU_NLD.png

Spanisch ESP Code A1034
OPP_ENU_ESP.png

Französisch FRA Code A1036
FRA_ENU.png



Um eine monolinguale Datei für einen direkten Zeilenvergleich zweiter Dateien wie die obigen zu erstellen genügt diese Pipelinekette, hier z.B. für ENU (= -A1033- im Codestring):
Bei der Originaldatei aus dem Clientexport
Code:
get-content C:\temp\translations.txt -encoding oem | select-string -pattern "-A1033-" -allmatches | Out-File C:\temp\translations_ENU.txt -Width 1024 -Encoding oem 

bzw. bei einer UTF8-datei
Code:
get-content C:\temp\translations.txt -encoding utf8 | select-string -pattern "-A1033-" -allmatches | Out-File C:\temp\translations_ENU.txt -Width 1024 -Encoding utf8 


Hinweis: Bei der Originaldatei aus dem NAV-Client den Encodingparameter beachten:
-Encoding oem , nicht -Encoding ascii, das bedeutet in der Powershell Codepage 437 (und nicht die erforderliche Codepage 850) und dann werden aus den vielen dort fehlenden Sonderzeichen (z.B. Großbuchstaben mit Umlauten) Fragezeichen in der Ausgabedatei und es kann auch zu Fehlzuordnungen kommen. Im Englischen stört das natürlich eher selten, aber bei anderen Sprachen schon eher :mrgreen: .


Links
Microsoft Dynamics ERP Translation Solution
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Neue Skriptversion für Azure Marketplace

1. August 2017 16:18

Azure Data Market ist eingestellt, der Translator Hub-Dienst wurde daher verschoben, jetzt zu finden bei den Azure Cognitive Services, dort gibt es jetzt die Translator-Texteingabe-API.
Goofing around with the Cognitive Services Translator API

Dadurch ändern sich auch die Anmelde- und Abrufverfahren im Skript. Ansonsten bleibt die Bedienung gleich. Der Dienst ist auch weiterhin bei bis zu 2.000.000 Zeichen pro Monat kostenlos.

Es wird jetzt nur noch ein Schlüssel benötigt, ClientID und ClientSecret fallen weg.
Wenn man die Translator-Texteingabe-API als Ressource bei seinem Azure-Account erstellt hat, ist unter "Manage Keys" ein KEY 1 ersichtlich, dieser muss in dieser Zeile im Skript eingetragen werden. Dieser kann bei Bedarf in Azure jederzeit neu generiert werden. Das sollte man auch nutzen, wenn auch nur der leiseste Verdacht besteht, dass dieser in falsche Hände geraten ist, denn ein Login findet hier ja nun nicht mehr statt. Jeder, der den Key kennt, kann damit diesen Dienst nutzen, die Rechnung bekommt man dann später, falls der Dieb einem nicht den Gefallen tut, unterhalb der monatlichen 2.000.000 Zeichen zu bleiben :mrgreen: .
Code:
$accountKey = "xxxxxxxxxxxxxxxxxxxxxxxx" # <- Enter your own key here !

TranslatorAPI.png


Die eigenen Category-IDs sind weiterhin gültig und können, falls vorhanden und das eigene Subsystem der beiden verwendeten Sprachen auf "Deployed" steht, an den Uri-String angehängt werden, um die Übersetzungsergebnisse auf das Themengebiet abzustimmen.
CategoryID.png

Diese wäre dann also am Ende in dieser Variante der uri-Zeile einzutragen:
Code:
 [string] $uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + $textEncoded + "&from=" + $from + "&to=" + $to + "&category=<EnterYourOwnCategoryIDhere...>


Code:
Function MTfromNAVtranslateFileV2
{
    Add-Type -AssemblyName System.Web
    Function WriteToFile
    {
        out-file $TranslatedfileName -inputobject $args -force -append -Width 1024 -Encoding utf8
    }
           
    $NAVtransfile = Read-host "Existing NAV translation file with ENU -A1033- Captions"
    $WorkingFolder = Split-Path -Parent $NAVtransfile
         
    $lines = Get-Content $NAVtransfile | Measure-Object -Line
    $Nooflines = $lines.Lines
    write-host "File has $Nooflines lines"
                 
    $ENUlines = Get-Content $NAVtransfile | select-string -pattern "-A1033-" -Allmatches -CaseSensitive | Measure-Object -Line
    $NoofENUlines = $ENUlines.Lines
    write-host "File has $NoofENUlines ENU lines (Code A1033)"

    $SourceLangCode = '-A1033-' # en = ENU

    $sourceEncoding = [System.Text.Encoding]::GetEncoding(850)
    $targetEncoding = [System.Text.Encoding]::GetEncoding(65001)

    $convertedFileName = [System.IO.Path]::GetDirectoryName($NAVtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVtransfile) +"_UTF8" + [System.IO.Path]::GetExtension($NAVtransfile)

    if (Test-Path $convertedFileName) {Remove-Item $convertedFileName}

    $convertedBaseName =  Split-Path -Leaf $convertedFileName
    $convertedfile = New-Item -path "$WorkingFolder\$convertedBaseName" -type file -Force

    $textfile = [System.IO.File]::ReadAllText($NAVtransfile, $sourceencoding)
    [System.IO.File]::WriteAllText($convertedfile, $textfile, $targetencoding)
    Write-host $NAVtransfile 'OEM850 converted to UTF8' $convertedFileName
                       
    $TargetLanguage = Read-host "Target Language: de,es,fi,fr,nl,no,pt,sv,en-gb,..."

    # Supported Translator Codes: https://msdn.microsoft.com/en-us/library/hh456380.aspx
    Switch ($TargetLanguage)
    {
        "de" {$NAVTargetlangCode = '-A1031-'}
        "es" {$NAVTargetlangCode = '-A1034-'}
        "fi" {$NAVTargetlangCode = '-A1035-'}
        "fr" {$NAVTargetlangCode = '-A1036-'}
        "nl" {$NAVTargetlangCode = '-A1043-'}
        "no" {$NAVTargetlangCode = '-A1044-'}
        "pl" {$NAVTargetlangCode = '-A1045-'}
        "pt" {$NAVTargetlangCode = '-A1046-'}
        "ru" {$NAVTargetlangCode = '-A1049-'}
        "sv" {$NAVTargetlangCode = '-A1053-'}
      # "gsw" {$NAVTargetlangCode = '-A2055-'} Swiss German currently not supported
        "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"}
    }



    $TranslatedFileName = [System.IO.Path]::GetDirectoryName($NAVtransfile) + "\"+ [System.IO.Path]::GetFileNameWithoutExtension($NAVtransfile) +"_$TargetLanguage" + [System.IO.Path]::GetExtension($NAVtransfile)


    foreach ($line in [System.IO.File]::ReadLines($convertedFileName))
    {
        $SourceTextLine = $line.ToString()
        if ($SourceTextLine.contains($SourceLangCode))
        {

               
            $accountKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # <- Enter your own key here !
            $tokenServiceURL = "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"
            $query = "?Subscription-Key=$accountKey"
            $uri = $tokenServiceUrl + $query
               
           

            #Invoke REST method.  This handles the deserialization of the JSON result.  Less effort than invoke-webrequest
            $token = Invoke-RestMethod -Uri $Uri -Method Post

            #Construct the header value with the access_token just received
            $auth = "Bearer " + $token
            $header = @{Authorization = $auth}

               
            $TargetLine = ''
            Write-host "Source line $SourceTextLine"
                 
     
            $pos1 = $SourceTextLine.IndexOf(":")

                     
            # Start-Sleep -Seconds 1 -verbose
            $SourceCodestringID = $SourceTextLine.Substring(0,$pos1)

               
               
            $SourceCaption = $SourceTextLine.Substring($pos1 + 1)
            Write-host "$SourceCaption" -ForegroundColor Green
               
            # Cut off trailing #1###,#2### etc,as these are battered in the translation process, but not if at first pos)
            $posHashKey = $SourceCaption.IndexOf("#")
            $TrailingSourceCaption = ''
            if ($posHashKey -gt 1)
            {
                $TrailingSourceCaption = $SourceCaption.Substring($posHashKey)
                $SourceCaption =  $SourceCaption.Substring(0,$posHashKey)
            }
            $TargetCodestringID = $SourceCodestringID -replace $SourceLangCode,$NAVTargetLangCode
            $TargetTextLine = ''
            Write-host "$TargetCodestringID" -ForegroundColor Yellow

               
            #region Construct and invoke REST request to Microsoft Translator Service
            [string] $text = $SourceCaption
            [string] $textEncoded = [System.Web.HttpUtility]::UrlEncode($text)
            [string] $from = "en"
            [string] $to = $TargetLanguage
            # Use category only if translation language pair has been deployed in the hub, otherwise without (Bing standard is used then)
            [string] $uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + $textEncoded + "&from=" + $from + "&to=" + $to + "&contentType=text/plain"
            #[string] $uri = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text=" + $textEncoded + "&from=" + $from + "&to=" + $to + "&category=xxxxInsertYourCodeHerexxxx"

            # $result = Invoke-RestMethod -Uri $uri -Headers @{Authorization = $HeaderValue}
            $result = Invoke-RestMethod -Uri $uri -Method Get -Headers $header
            #endregion
           
            $result.string.'#text'
            $TargetTextLine = $result.string.'#text'
            $TranslatedLine = $TargetCodestringID + ':' + $TargetTextLine + $TrailingSourceCaption
            $TranslatedLine
            Write-host "$TargetTextLine$TrailingSourceCaption" -ForegroundColor Yellow
            WriteToFile $TranslatedLine
            #write-host "Waiting 2 seconds..."
            # Start-Sleep -Seconds 2
               
        }
    }
         
    if (Test-Path $translatedfilename)
    {   
        $translatedfilename = resolve-path $translatedfilename
        $WorkingFolder = Split-Path -Parent $translatedfilename
        $sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
        # Check if your local code page matches, and modify if necessary
        # 850 is for Western Europe, 852 for Central Europe, 866 for Russia etc.
        $targetEncoding = [System.Text.Encoding]::GetEncoding(850)
               
        $OEM850FileName = [System.IO.Path]::GetFileNameWithoutExtension($translatedfilename) +"_OEM850" + [System.IO.Path]::GetExtension($translatedfilename)
        $OEM850file = New-Item -path "$WorkingFolder\$OEM850FileName" -type file
               
        $UTF8file = [System.IO.File]::ReadAllText($translatedfilename, $sourceencoding)
        [System.IO.File]::WriteAllText($OEM850file, $UTF8file, $targetencoding)
        Write-host $translatedfilename  'converted to' $OEM850FileName
    }
     
       
     
}


Falls die Unicodecodedatei in eine andere Codepage als 850 zurückkonvertiert werden soll, muss das Skript beim Targetencoding natürlich angepasst werden (statt 850 für Polnisch 852, für Russisch 866 usw. )
ruTranslatorHub.png


Das sind die Zeilen nach dieser Codestelle
Code:
# Check if your local code page matches, and modify if necessary
# 850 is for Western Europe, 852 for Central Europe, 866 for Russia etc.


Die Umwandlung in eine spezielle Codepage macht man aber ja ohnehin normalerweise erst, nachdem der Vergleich in UTF-8 und Korrekturen und Nacharbeiten hieran abgeschlossen sind :wink:, und diese Konvertierung auch nur, wenn man damit keine Codepagekonflikte bekommt. Wenn dieses gegeben ist (also auf jedem konventionellen NAV-System, welches z.B. in Westeuropa installiert ist, und Captioninhalte einer anderen Sprache außerhalb des Bereichs von Codepage OEM 850 bzw. Windows 1252 benötigt), dann darf statt dessen nur die UTF-8-Datei auf dem Server abgelegt werden, wie hier beschrieben:
How to: Add Translated Strings for Conflicting Text Encoding Formats (das Verfahren ist verfügbar ab NAV 2013 R2)
enurus.png
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.