How to support this blog?

To support this blog, you can hire me as an OmegaT consultant/trainer, or you can send translation and project management jobs my way.

Search the site:

Convertir un fichier TMX en TBX avec une transformation XSLT

<?xml version='1.0' encoding="UTF-8"?>


<!--

Ce document est une tentative pour créer une transformation XSL (XSLT) simple entre un fichier TMX (mémoire de traduction) et un fichier TBX (glossaire).


Il permet d’utiliser la TMX créée à partir de la traduction d’un fichier des chaînes de l’interface utilisateur d’un logiciel et d’utiliser le contenu en tant que glossaire pour vérifier que les chaînes de l’IU sont bien traduites dans les documents qui la décrivent (manuels, etc.)


Il est possible d'utiliser ce document en l'enregistrant dans un fichier texte, et en l'associant à une liste de documents dans Rainbow ou avec un processeur XSLT tel que xsltproc, à la ligne de commande :


xsltproc -o monFuturFichierTBX.tbx cetteTransformationXSLT.xsl monFichierTMX.tmx


La transformation a été écrite par Sirine Ben Hadj Khalifa et moi-même lors du stage de fin d’études de M2 de madame Ben Hadj Khalifa.


Les explications sont écrites par moi et correspondent à mon niveau de compréhension des standards à la date de leur écriture.


Le document peut être utilisé en l’état car les explications sont toutes à l'intérieur de commentaires XML et ne gênent en aucun cas le traitement du document.


Le document est un logiciel libre qui est utilisable et modifiable selon les termes de la licence GPL 3.0 (ou plus).


Copyright Sirine Ben Hadj Khalifa, Jean-Christophe Helary


Références :

– TMX = Translation Memory eXchange (format d’échange de mémoire de traduction)

  https://www.gala-global.org/tmx-14b


– Rappel sur la structure d’une mémoire TMX :

  une TMX est constituée de balises « tu » (« translation unit ») qui contiennent des « tuv » (« translation unit variant »). Chaque « tuv » a un attribut « xml-lang » qui spécifie la langue de son contenu, et contient, quand elle contient quelque chose, une balise « seg » (« segment ») qui elle contiendra le texte.


    <tu>

      <note>UI</note>

      <tuv xml:lang="en">

        <seg>OmegaT options :</seg>

      </tuv>

      <tuv xml:lang="fr" creationid="OmegaT Aligner" creationdate="20230401T121435Z">

        <seg>Options OmegaT :</seg>

      </tuv>


    </tu>


– TBX = TermBase eXchange (format d’échange de base terminologique)

  https://www.iso.org/schema/isosts/v0.6/doc/tbx/


– Rappel sur la structure d’un glossaire TBX (simple) :

  un TBX est constitué de balises « termEntry » qui contiennent des « langSet » dans lesquels on trouve des « tig » (« term information group ») qui à leur tour contiennent les « term ».


      <termEntry id="OmegaT options:">

        <note xml:lang="en">UI</note>

        <langSet xml:lang="en">

          <tig>

            <term>OmegaT options :</term>

          </tig>

        </langSet>

        <langSet xml:lang="fr">

          <tig>

            <term>Options OmegaT :</term>

          </tig>

        </langSet>

      </termEntry>


On remarque que les deux hiérarchies ont une structure extrêmement similaire.


– Rainbow

  https://www.okapiframework.org


– xsltproc (disponible sur Linux, macOS, Cygwin pour Windows)

  https://gitlab.gnome.org/GNOME/libxslt/-/wikis/home


– Qu'est-ce que le logiciel libre

  https://www.gnu.org/philosophy/free-sw.fr.html


– La licence GPL 3.0

  https://www.gnu.org/licenses/quick-guide-gplv3.fr.html

-->



<xsl:stylesheet

    version="1.0"

    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

    xmlns:local="http://www.w3.org/2005/xquery-local-functions">


  <!--

      La syntaxe d’un document XML est très claire, mais les ajouts de crochets et autres décorations rendent sa lecture difficile à un être humain. C’est pour ceci que lorsqu’on publie des documents XML il est préférable d’utiliser des fonctions automatiques de mise en retrait des lignes en fonction de leur niveau d’emboîtement, et donc d’utiliser correctement l’emboîtement (les sauts de ligne) pour correctement identifier les rapports entre balises (pour lesquelles on utilise la métaphore familiale : parent, enfant, ancêtre, descendant, etc.) et leurs attributs.


On peut diviser la structure d’une balise en 3 éléments, et ce sont ces éléments sur lesquels notre attention doit porter pour comprendre la structure, et dans le cas d’une feuille XSL le fonctionnement, du document.


Une balise dans une langue conforme à la norme XML est en général composée ainsi:


– le nom de la balise

– les attributs de la balise (avec pour chaque attribut son nom et sa valeur)

– le contenu de la balise


La plupart des langues XML autorisent des balises au contenu vide, et des valeurs d’attributs par défaut, etc.


Certaines langues autorisent le mélange à l’intérieur du document de balises provenant de langues externes. Pour s’assurer que la distinction est faite entre leurs propres balises et les balises « externes », elles vont systématiquement ajouter un préfixe à leurs propres balises. Ainsi, la lectrice saura toujours que les balises préfixées sont à interpréter dans le cadre de la langue du document alors que les balises non préfixées sont externes et à interpréter, éventuellement, dans le cadre de la langue externe.


C’est le cas de XSLT qui va décrire la manière dont la transformation doit s’opérer avec ses propres balises et qui va utiliser les balises externes (ici les balises TBX) pour créer le fichier TBX. Les balises XSLT vont toutes être préfixées avec « xsl: » pour indiquer que seules ces balises sont à interpréter dans le cadre de la langue XSLT.


Références :

– Stylesheet element

  https://www.w3.org/TR/1999/REC-xslt-19991116#stylesheet-element


– XML = eXtensible Markup Language, donc « langue extensible de balisage »

  XML est un ensemble de règles qui permet de définir des langues de balisage de document

  https://www.w3.org/TR/REC-xml/


– XSL = eXtensible Stylesheet Language, donc « langue extensible de feuille de style »

  XSL est un ensemble de recommandations pour définir des transformations et des présentations pour documents XML

  https://www.w3.org/Style/XSL/


– XSL est composé de :

  – XSLT = XSL Transformations, qui est utilisée pour définir les règles de transformation d’un document XML

  – XPATH = XML Path Language, qui est utilisé pour trouver son chemin dans un document XML et éventuellement identifier les éléments qui seront la cible d’une transformation

  – XSL-FO = XSL Formatting Objects, qui est utilisé principalement pour produire des documents PDF


Il faut noter que la complexité de XSL-FO et l’évolution des technologies du Web font que XSL-FO a tendance à être remplacé par CSS pour produire des documents lisibles dans un navigateur.

https://www.w3.org/TR/NOTE-XSL-and-CSS


– CSS = Cascading Stylesheet Language (langue de feuilles de style en cascade)

  https://www.w3.org/TR/CSS/

  -->


  

  <xsl:output

      method="xml"

      encoding="UTF-8"

      indent="yes"

      doctype-public="ISO 12200:1999A//DTD MARTIF core (DXFcdV04)//EN"

      doctype-system="TBXcdv04.dtd"

    />


 
<!--

      Ici, on va produire (« output ») un fichier qui sera

      – du XML, de version 1.0 par défaut

      – en encodage UTF-8, déclaré dans le document.

      – Ses lignes de la sortie seront mises en retrait en fonction de leur emboîtement

      – Son « doctype » public et le « doctype » local sont également définis ici, et ils spécifient que le document sera un document TBX.


Références :

– Output

  https://www.w3.org/TR/1999/REC-xslt-19991116#output

  -->


  

  <xsl:template match="/">

    <martif type="TBX" xml:lang="en">

      <martifHeader>

        <fileDesc>

          <sourceDesc>

            <p>tmx2tbx</p>

          </sourceDesc>

        </fileDesc>

      </martifHeader>

      <text>

        <body>

          <xsl:apply-templates select="tmx/body/tu"/>

        </body>

      </text>

    </martif>

  </xsl:template>


  <!--

      Une feuille de transformation fonctionne en gros de la manière suivante :

      – on définit une « template » (un modèle) qui s’applique à certains éléments du fichier d’origine (ici, des parties du fichier TMX que nous cherchons à transformer en fichier TBX)

      – on définit dans ce « modèle » les manières de transformer ces éléments (pour produire ici des parties du fichier TBX final).


Notre premier modèle va s’appliquer à la totalité du document d’origine (TMX) car le symbole « / » dans le contexte d’une arborescence de document XML correspond à l’origine du document. Pour en savoir plus, il est nécessaire de consulter des tutoriels XPATH.


Puis on inscrit à l’intérieur de la définition du modèle la manière de modifier ce contenu auquel il s’applique.


Tout ce qui se trouve entre le
<xsl:template match="/"> et le </xsl:template> de notre premier modèle est le contenu qui va être mis à la place de la totalité du document d’origine. Toutes les balises qui n’y sont pas préfixées par « xsl: » sont des éléments qui seront reproduits tels quels dans le document final. En ce qui nous concerne, ces parties sont donc des éléments du fichier TBX final.


Toutes les balises préfixées par « 
xsl: » sont des directives de transformation qui ne se retrouveront pas telles quelles dans le document final. Seulement le résultat de ces directives s’y retrouvera.


À l’intérieur des balises TBX de notre premier modèle, on trouve une nouvelle directive XSL :


<xsl:apply-templates select="tmx/body/tu"/>


Cette nouvelle directive nous indique qu’ici on va maintenant faire autre chose que d’ajouter des balises prédéfinies et qu’on va aller chercher des données à l’intérieur des « tu » du fichier TMX d’origine, qui se trouvent à l’intérieur de tmx/body. Cette notation avec des « / » indique la hiérarchie entre les éléments :


/ est l’origine du document

tmx est la balise racine du document (tout document XML a une balise racine, pour un fichier TMX c’est la balise tmx, pour un fichier TBX c’est la balise martif).

tmx/body est une balise body qui est directement incluse dans la balise tmx

tmx/body/tu est une balise tu qui est directement incluse dans la balise body, etc.


La directive nous demande donc d’appliquer un autre modèle, à l’intérieur du modèle principal, celle qui correspond aux éléments « tu » de la TMX.


Références :

– Defining Template Rules

  https://www.w3.org/TR/1999/REC-xslt-19991116#section-Defining-Template-Rules

– Applying Template Rules

  https://www.w3.org/TR/1999/REC-xslt-19991116#section-Applying-Template-Rules  

  -->


  

  <xsl:template match="tmx/body/tu">

    <termEntry>

      <xsl:attribute name="id">

        <xsl:value-of select="tuv[1]/seg"/>

      </xsl:attribute>

      <note xml:lang="en">UI</note>

      <xsl:apply-templates select="tuv"/>

    </termEntry>

  </xsl:template>


  <!--

      On retrouve ici la même structure que le premier modèle : on cherche des éléments auxquels on va appliquer une transformation.


Ici, les éléments sont les « tu » du document TMX d’origine.


De la même manière que le premier modèle remplaçait la totalité du document d’origine avec des balises de type TBX, ici on va remplacer les « tu » de la TMX d’origine par la balise TBX « termEntry ».


On va ajouter un attribut à cette balise. Le nom de l’attribut sera « id » et sa valeur est définie de la manière suivante :


<xsl:value-of select="tuv[1]/seg"/> qui nous indique qu’on doit prendre la valeur de l’élément sélectionné à droite : « tuv[1]/seg »


Nous nous trouvons dans le contexte d’une « tu » puisque c’est ce à quoi le modèle que nous considérons s’applique (
match="tmx/body/tu") et dans ce contexte, « tuv[1]/seg » veut dire la balise « seg » qui se trouve dans la première balise « tuv » de la balise « tu» considérée. Sachant que la transformation va s’appliquer à toutes les balises qui correspondent à la spécification « match ».


La directive « select » nous indique que nous allons prendre le contenu (ici textuel) qui se trouve entre la balise ouvrante « <seg> » et la balise fermante « </seg> » qui constituent les éléments de base d’une TMX (cf. le rappel plus haut).


Ce que nous avons défini ici c’est une balise <termEntry> dont l’attribut « id » aura pour contenu, le texte de la balise « seg » de la première « tuv » de notre « tu ». Vous pouvez trouver le résultat dans l’exemple donné dans le rappel plus haut.


À l’intérieur d’une « tu » on a potentiellement une « tuv » au minimum, et parfois plus. Ici, je décide que la valeur que doit prendre le nouvel attribut « id » d’un termEntry est le contenu de la balise « seg » qui est elle-même contenue dans le premier TUV (dans notre TMX nous en avons 2 par « tu »).


La syntaxe est le contenu de la balise « seg » à l’intérieur du premier « tuv » : « 
tuv[1]/seg ».


Une fois l’attribut « id » de termEntry défini, la directive
<xsl:attribute name="id"> se ferme avec </xsl:attribute> et on passe à l’ajout d’un contenu écrit en toutes lettres, qui est :


     
<note xml:lang="en">UI</note>


Cette note sera la même pour tous les « termEntry » de notre TBX, mais on pourrait imaginer un modèle qui y mettrait un contenu qui dépend d’un élément présent dans la TMX.


Après cette note, on trouve un autre appel à un modèle, qui va cette fois travailler sur le contenu des « tuv » de notre TMX.


Références :

- Creating Attributes with xsl:attribute

  https://www.w3.org/TR/1999/REC-xslt-19991116#creating-attributes

- Generating Text with xsl:value-of

  https://www.w3.org/TR/1999/REC-xslt-19991116#value-of    

  -->



  <xsl:template match="tuv">

    <langSet>

      <xsl:attribute name="xml:lang">

        <xsl:value-of select="@xml:lang"/>

      </xsl:attribute>

      <xsl:apply-templates select="seg"/>

    </langSet>

  </xsl:template>


  <!--

      Comme on l’a vu plus haut avec « termEntry », on ajoute ici une balise TBX « langSet » à laquelle on va associer un attribut.


Cette fois-ci, la définition de l’attribut utilise une autre syntaxe, mais elle va toujours sélectionner le contenu textuel d’un élément.


Cet élément est spécifié avec la notation « @ », ce qui signifie qu’il s’agit non pas d’une balise descendante de « tuv » mais d’un attribut de « tuv », dont le nom est « xml-lang », c’est-à-dire le code qui identifie la langue naturelle du contenu du segment. C’est le même code langue qui sera utilisé dans l’attribut « xml-lang » qui, par un heureux hasard, a exactement le même nom dans TMX et dans TBX, mais ça n’est pas exactement un hasard, puisque c’est la méthode recommandée dans la norme XML pour identifier des langages :

https://www.w3.org/TR/REC-xml/#sec-lang-tag


Une fois l’attribut créé, on trouve un nouvel appel à un modèle, cette fois-ci pour traiter les balises « seg », probablement pour associer leur contenu au contenu d’un « term » dans le fichier TBX final.

  -->



  <xsl:template match="seg">

    <tig>

      <term>

        <xsl:value-of select="."/>

      </term>

    </tig>

  </xsl:template>

</xsl:stylesheet>


  <!--

      Ce dernier modèle va mettre entre les balises <term> et </term> la valeur textuelle du contenu de « . » qui est, dans la syntaxe d’un cheminement XML le lieu même du contexte, ici notre balise « seg ».


Nous allons donc aller chercher le contenu textuel de nos segments et les copier (sans conserver d’éventuelles balises XML puisque « 
value-of » ne conserve que le contenu textuel) à l’intérieur des balises « term » de notre TBX, et avec ce dernier modèle nous avons fini notre transformation.


Il faut remarquer que tous les modèles s’appliquent à tous les éléments correspondants à la spécification « 
match », il n’est donc pas nécessaire dans notre transformation d’utiliser de boucles de traitement (xsl:for-each, https://www.w3.org/TR/1999/REC-xslt-19991116#for-each) qu’on utiliserait dans un langage de programmation.

  -->

Popular, if not outdated, posts...

.docx .NET .pptx .sdf .xlsx AASync accented letters Accessibility Accessibility Inspector Alan Kay alignment Apple AppleScript ApplescriptObjC AppleTrans applications Aquamacs Arabic archive Automator backup bash BBEdit Better Call Saul bug Butler C Calculator Calendar Chinese Cocoa Command line CSV CSVConverter database defaults Devon Dictionary DITA DocBook Dock Doxygen EDICT Emacs emacs lisp ergonomics Excel external disk file formats file system File2XLIFF4j Finder Fink Font français Free software FSF Fun Get A Mac git GNU GPL Guido Van Rossum Heartsome Homebrew HTML IceCat Illustrator InDesign input system ITS iWork Japanese Java Java Properties Viewer Java Web Start json keybindings keyboard Keynote killall launchd LISA lisp locale4j localisation MacPort Mail markdown MARTIF to TBX Converter Maxprograms Mono MS Office NeoOffice Numbers OASIS Ocelot ODF Okapi OLPC OLT OmegaT OnMyCommand oo2po OOXML Open Solaris OpenDocument OpenOffice.org OpenWordFast org-mode OSX Pages PDF PDFPen PlainCalc PO Preview programming python QA Quick Look QuickSilver QuickTime Player Rainbow RAM reggy regular expressions review rsync RTFCleaner Safari Santa Claus scanner Script Debugger Script Editor scripting scripting additions sdf2txt security Services shell shortcuts Skim sleep Smultron Snow Leopard Spaces Spanish spellchecking Spotlight SRX standards StarOffice Stingray Study SubEthaEdit Swordfish System Events System Preferences TBX TBXMaker Terminal text editing TextEdit TextMate TextWrangler The Tool Kit Time Capsule Time Machine tmutil TMX TMX Editor TMXValidator transifex Translate Toolkit translation Transmug troubleshooting TS TTX TXML UI Browser UI scripting Unix VBA vi Virtaal VirtualBox VLC W3C WebKit WHATWG Windows Wine Word WordFast wordpress writing Xcode XLIFF xml XO xslt YAML ZFS Zip