<?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.
-->