Table of Contents

Übersetzen einer Extension

Im Folgenden wird der Prozess der Generierung und Pflege von Übersetzungen detailliert erläutert.

Prozessüberblick

In diesem Abschnitt wird ein grober Überblick über den Gesamtprozess gegeben.

Prozessüberblick zur Übersetzung von Extensions

Diagramm Übersetzungsprozess

Übersetzung während der Entwicklung

Während der Entwicklung wird jeder Text, also Captions, Labels, Tooltips oder InstructionalTexts, mit einem Comment versehen, der den Text der deutschen Übersetzung enthält. Nach der Fertigstellung eines PBIs oder Bugs, werden diese Comments mithilfe von Xliff Sync in Übersetzungen umgewandelt. Bei der Umwandlung überprüft Xliff Sync die Übersetzungen auf technische Korrektheit und ob es fehlende Übersetzungen gibt.
Sobald eventuell gefundene Probleme behoben wurden, kann abschließend ein Pull Request erstellt werden.

Im Verlauf dieses Artikels ist an einigen Stellen von einer Qualitätssicherung die Rede, da an diesen Stellen eine besondere Betrachtung der Übersetzungen notwendig ist, wenn ein Qualitätssicherungsprozess angewandt wird. Inwiefern und in welchem Umfang diese Qualitätssicherung stattfindet bleibt den Projektteams überlassen.

Entwicklung im Detail

Technische Grundlagen

Technisch gesehen bestehen Übersetzungen aus zwei Komponenten: Den Übersetzungskommentaren und den sprachspezifischen .xlf Dateien. Die Übersetzungskommentare dienen dazu, bereits während der Entwicklung Übersetzungen festlegen zu können. Bei den .xlf Dateien handelt es sich um XML Dateien mit einem bestimmten, standardisiertem Schema namens XLIFF. Diese Dateien haben den Vorteil, dass mit ihnen die Übersetzungen auch Nicht-Entwicklern zugänglich gemacht werden können.

XML Struktur von XLIFF

Zur Bearbeitung von .xlf Dateien ist es hilfreich, vorher das Schema verstanden zu haben. Daher folgt eine kurze Erklärung aller wichtigen Elemente. Das Codebeispiel zeigt, wie eine technische Caption aus dem AL Code in der .xlf Datei aussieht.

Caption = 'Default Language Code',
    Comment = 'de-DE=Standard Sprachcode|en-US=Default Language Code';
<trans-unit id="Table 1837367835 - Field 2066782256 - Property 2879900210" size-unit="char" translate="yes" xml:space="preserve">
    <source>Default Language Code</source>
    <target state="final">Standard Sprachcode</target>
    <note from="Developer" annotates="general" priority="2">de-DE=Standard Sprachcode|en-US=Default Language Code</note>
    <note from="Xliff Generator" annotates="general" priority="3">Table GOB MDE Setup - Field Default Language Code - Property Caption</note>
</trans-unit>

Elemente und Attribute

Element Attribut Beschreibung
trans-unit Für jeden Text gibt es eine "Übersetzungseinheit"
trans-unit id Ein eindeutiger Hashwert, der aus Objektname, Funktionsname und Feld/Variablenname gebildet wird. Ändert sich einer dieser Namen, ändert sich auch die id und die Übersetzung geht verloren
trans-unit translate Wird über das Locked Property der technischen Caption bestimmt
source Der Inhalt von Caption: "technische Caption"
target Die eigentliche Übersetzung
target state translated: während Entwicklung / final: nach QS / needs-adaptation / needs-translation

Übersetzungskommentare

Die initiale Übersetzung wird vom Entwickler festgelegt. Dies geschieht durch Comments an Captions, Labels, Tooltips und InstructionalTexts, bei denen ein bestimmtes Format eingehalten werden muss. Ein gültiger Comment besteht aus folgenden Elementen:

  • Länderspezifisches Sprachkürzel de-DE= für deutsch oder en-US= für englisch
  • Einem Separator |
  • Dem entsprechenden Text der Übersetzung
  • Optional: Properties Locked und/oder MaxLength

Es ist außerdem möglich, normale Kommentare einzufügen, indem man das Sprachkürzel weglässt und den Kommentar einfach nur mit | abtrennt. Das Sprachkürzel en-US= samt Übersetzung kann auch weggelassen werden. In diesem Fall wird die technische Caption als englische Übersetzung verwendet.

Comments, die nicht übersetzt werden sollen, müssen unbedingt das Property Locked = true gesetzt haben.

Warnung

Zwischen dem Sprachkürzel und dem Gleichheitszeichen, darf kein Leerzeichen eingefügt werden! de-DE =<text> ist ebenso unzulässig wie de-DE= <text>. Steht hinter dem Gleichheitszeichen ein Leerzeichen, so wird das Leerzeichen so interpretiert, als gehöre es zum Text.

Beispiele

Deutsche Übersetzung wird angegeben, englische Übersetzung ist gleich technische Caption, Beschreibung des Platzhalters wird bei Übersetzung ignoriert

FinishMessageTxt: Label '%1 membership templates created.',
            Comment = 'de-DE=%1 Mitgliedschaftsvorlagen erstellt.';

Keine Übersetzung notwendig

value(1; Slash)
    {
        Caption = '/', Locked = true;
    }

Arbeitsablauf

Nach der Fertigstellung einer Entwicklungsaufgabe sind folgende Schritte durchzuführen.

1. Extension kompilieren

Dies dient dazu, die automatisch vom Compiler generierte Sprachdatei zu aktualisieren.

2. Synchronisation

Mit dem von Xliff Sync bereitgestellten Befehl XLIFF: Synchronize Translation Units werden die bei der Entwicklungsaufgabe geänderten Texte in die sprachspezifischen Sprachdateien übernommen. Falls noch keine sprachspezifischen Sprachdateien vorhanden sind, so müssen diese zuvor mit Xliff Sync erstellt werden.

3. Probleme beheben

Xliff Sync kann eine ganze Reihe von Problemen detektieren. Die meisten dieser Probleme sind selbsterklärend (doppelte Leerzeichen, Anzahl Platzhalter, etc.) und werden hier nicht gesondert behandelt. Es werden nur die Fälle aufgeführt, in denen eine genauere Handlungsempfehlung sinnvoll ist.
Bei der Abarbeitung von Problemen, empfiehlt es sich mit der englischen Sprachdatei en-US zu beginnen, da hier die Problembehebungen zu Änderungen an der technischen Caption führen können, was sich wiederrum auf die anderen Sprachdateien auswirkt. Nachdem alle Probleme in der englischen Sprachdatei behoben sind, beginnt man wieder bei Schritt 1 mit der nächsten Sprachdatei.

Im Folgenden bezieht sich der Status translated oder final auf das <target> Element in der .xlf Datei.

Fehlende Übersetzung: missing-translation

Werden fehlende Übersetzungen detektiert, so empfiehlt es sich als erstes mit den regulären Ausdrücken im Abschnitt Regular Expressions zu überprüfen, ob Übersetzungskommentare fehlen oder im falschen Format vorliegen. In Einzelfällen kann es dazu kommen, dass der reguläre Ausdruck nicht alle Stellen erkennen kann.
Diese Einzelfälle müssen dann gesondert betrachtet und korrigiert werden. Nach erfolgreicher Bearbeitung wird der Status auf translated gesetzt.

Generelle Probleme: needs-adaptation

Sämtliche anderen Probleme werden mit dem Status needs-adaptation versehen. Darunter fallen auch die selbsterklärenden Probleme.
Folgende Fälle müssen allerdings genauer betrachtet werden:

Abweichung technische Caption zu en-US

Dieser Fall tritt auf, wenn es einen Übersetzungskommentar für en-US gibt, der von der technischen Caption abweicht. Dies ist nur in Ausnahmefällen zulässig und deutet in der Regel auf eine Altlast hin. Üblicherweise reicht es hier aus, den en-US Comment zu entfernen.

Viel häufiger tritt dieser Fall jedoch auf nachdem eine Sprachdatei übernommen wurde, die im Rahmen einer Qualitätssicherung überarbeitet wurde. Jede englische Übersetzung, die bearbeitet wurde, wird mit needs-adaptation markiert. Diese Übersetzungen müssen dann auf fachliche Korrektheit geprüft und in die technische Caption im Quellcode übernommen werden. Hierzu verwendet man am besten die Suchen und Ersetzen Funktion in VS Code. Falls die überarbeitete Übersetzung korrigiert werden musste, weil z. B. ein fachlicher Fehler in der Überarbeitung vorlag, wird der Status auf translated gesetzt. Wurde die überarbeitete Übersetzung übernommen, wird der Status auf final gesetzt.

Property Locked fehlt

Bei Texten, bei denen der Übersetzungskommentar fehlt, handelt es sich manchmal um Texte, die eigentlich gar nicht übersetzt werden sollen. Diesen muss das Property Locked = true angefügt werden.

Allgemein: Bearbeitung des deutschen Übersetzungskommentars

Es kann vorkommen, dass ein deutscher Übersetzungskommentar nachträglich bearbeitet werden muss, beispielsweise weil ein Tippfehler vorliegt. Falls dieser Kommentar bereits in die Sprachdatei übernommen wurde, so muss der deutsche Text auch in der Sprachdatei ersetzt werden. Deswegen muss in diesem Fall immer mit der Suchen und Ersetzen Funktion in VS Code gearbeitet werden.

Wenn die Sprachdatei schon im Rahmen einer Qualitätssicherung bearbeitet wurde, muss der Status in der Sprachdatei von final zurück auf translated gesetzt werden. Alternativ kann auch die komplette <trans-unit> gelöscht werden.

Regular Expressions

Es gibt einige reguläre Ausdrücke, die bei der Identifizierung und Behebung von Problemen hilfreich sein können.

Warnung

Diese regulären Ausdrücke sind mit Vorsicht zu genießen! In Einzelfällen wird zu wenig/zu viel gematcht. Bevor also eine Ersetzung ausgeführt wird, ist diese in der Ersetzungsvorschau in VS Code zu kontrollieren.

Umwandlung altes Format in neues Format

Hierbei findet gleichzeitig auch eine Vereinheitlichung des Formates statt. Führende Leerzeichen in OptionCaption gehen dabei leider verloren. Dies wird aber bei der Synchronisation von Xliff Sync erkannt und mit needs-adaptation markiert.

(\s?(DEU){1}\s?=\s?)(?=.*?;)
(\s?(ENU){1}\s?=\s?)(?=.*?;)

Ersetzen durch

de-DE=
en-US=

Ersetzung ungültiger Separator

(Comment\s?=\s?'(?:DEU|ENU){1}\s?=\s?.*?)([^\|\w])((?:DEU|ENU){1}\s?=\s?.*?';)
(Comment\s?=\s?'(?:de-DE|en-US){1}\s?=\s?.*?)([^\|\w])((?:de-DE|en-US){1}\s?=\s?.*?';)

Ersetzen durch

$1|$3

Comments ohne Separator

Diese Fälle sind schwierig zu detektieren. Daher findet dieser reguläre Ausdruck zu viele Ergebnisse und diese müssen genau geprüft werden.

(Comment\s?=\s?'.*?)(\s{3,})(.*?';)

Ersetzen durch

$1|$3

Beispiel

ToolTip = 'Specifies the line type.',
    Comment = 'de-DE=Gibt die Zeilenart an.     BC STANDARD';

Comments ohne de-DE

Comment fehlt komplett

\b(Caption|ToolTip|Label|InstructionalText) ?=? '((?!Comment)(?!Locked = true).)*?'; 

Comment vorhanden, aber ohne de-DE

\b(Caption|ToolTip|Labe|InstructionalText) =? ?'(((?!de-DE)(?!Locked = true).)*)(;|[\r\t\n].*?Comment((?!de-DE)(?!Locked = true).)*;)

Deprecated Hotkey Syntax

Hotkeys, die durch ein & vor dem jeweiligen Buchstaben gekennzeichnet werden, sind nicht mehr unterstützt und müssen daher entfernt werden (Beispiel Fun&ktion). Shortcut Keys wie z. B. F9 für das Starten eines Buchungsprozess sind erlaubt und erwünscht.

(Caption|de-DE=|en-US=).*?(\S)?(&)(\S)((?!Locked = true).)*$

Beispiel

Caption = 'F&unctions',
    Comment = 'de-DE=F&unktion|en-US=F&unctions';

Seltener auch mit % statt &

(Caption|de-DE=|en-US=).*?(\S)?(%[a-zA-Z])(\S)((?!Locked = true).)*$

Snippets

Um das Einfügen von bestimmten Texten zu erleichtern, sind Code Snippets nützlich. Die Snippets können über den VS Code Befehl Preferences: Configure User Snippets konfiguriert werden.

Semicolon ersetzen mit Comment

Bei einer Caption ohne Comment, das abschließende ; markieren, Leertaste drücken und dann Snippet auswählen.

"de-DE Comment": {
        "prefix": "tCommentde-DE",
        "description": "Replace semicolon with comment de-DE",
        "body": [
            ",",
                "\tComment = 'de-DE=${2:GermanTranslation}';$0"
        ]
    }

ToolTip

"ToolTip With Comment de-DE": {
        "prefix": "tToolTipWithCommentde-DE",
        "description": "UI Texts: ToolTip with comment de-DE",
        "body": [
            "ToolTip = '${1:EnglishCaption}',",
                "\tComment = 'de-DE=${2:GermanTranslation}';$0"
        ]
    }

InstructionalText

"InstructionalText With Comment de-DE": {
        "prefix": "tInstructionalTextWithCommentde-DE",
        "description": "UI Texts: InstructionalText with comment de-DE",
        "body": [
            "InstructionalText = '${1:EnglishCaption}',",
                "\tComment = 'de-DE=${2:GermanTranslation}';$0"
        ]
    }

Label

"Label With Comment de-DE": {
        "prefix": "tLabelWithCommentde-DE",
        "description": "UI Texts: Label with comment de-DE",
        "body": [
            "${1:LabelName}: Label '${2:EnglishCaption}',",
                "\tComment = 'de-DE=${3:GermanTranslation}';$0"
        ]
    }