Difference between revisions of "Exemples de règles de transfert"

From Apertium
Jump to navigation Jump to search
(Lien page anglaise)
 
Line 1,557: Line 1,557:
   
 
[[Category:Documentation en français]]
 
[[Category:Documentation en français]]
  +
[[Category:Transfer]]

Latest revision as of 21:10, 20 November 2019

In English

Cette page est destinée à compléter la page Introduction aux règles de transfert. Les exemples utilisés concernent la paire apertium-eo-fr. Il s'agit d'une paire le langues validée pour le sens de traduction français → espéranto. Par contre, le sens de traduction espéranto → français n'a pas été implémenté par le développeur initial. C'est un autre développeur, totalement débutant pour l'écriture des règles de transfert qui a choisi de le faire. Les exemples fournis concernent les toutes premières règles écrites pour traduire un groupe d'un, deux ou trois mots espéranto en un groupe de deux ou trois mots français.

Cette page ne concerne que l'écriture du fichier de règles destiné à être utilisé par l'outil apertium-transfer dont le suffixe est .t1x. L'écriture de balises destinée à la fragmentation dans le cadre d'un transfert en 3 étapes n'y est pas abordé.

Les différentes étapes d'une traduction avec apertium[edit]

Commençons par lister les différentes opérations qui sont exécutées pour une traduction.

Opération Rôle Langues concernées
Déformatage Permet de marquer des zones du texte source à ne pas traduire. Par exemple, on ne traduit pas dans une autre langue les balises HTML, mais seulement le texte de la page web. Les mêmes logiciels sont utilisés pour toutes les paires de langues. C'est le format des données à traduire qui emmènera à utiliser tel ou tel déformateur.
Analyse Chaque mot du texte source est décomposé en un lemme suivi du type de mot et de ses attributs (genre, nombre, personne et temps pour un verbe ...). Pour certains mots, plusieurs analyses sont possibles. Dans ce cas, elles sont toutes envoyées en sortie. Valable pour toutes les langues, elle fait appel au dictionnaire morphologique de la langue source.
Désambiguïsation Lorsqu'un mot dispose de plusieurs analyses, cette étape permet de n'en conserver qu'une seule. Valable pour toutes les langues, elle fait appel à un fichier de suffixe .prob
Pour les langues non ambiguës comme l'espéranto, cette étape reste nécessaire pour supprimer la forme de surface de chaque mot analysé (pré-formatage pour l'étape de transfert).
Pré-transfert Traitement des multi-mots avant l'étape de transfert. Toutes langues. Ne nécessite pas de fichier de données particulier.
Transfert Transforme les analyses issues de la langue source en leur version traduite dans la langue cible. Valable pour toutes les paires de langues, il fait appel au dictionnaire bilingue et au fichier de transfert de suffixe .t1x
Traitement inter-fragments Permet des traitements sur un groupe de mots (le sujet, un complément ...)
Comme indiqué plus haut, on ne s'occupera pas de cette étape (ni de la suivante).
Utilisé à priori pour simplifier l'étape de transfert, il nécessite de rajouter quelques balises à l'étape de transfert. Il fait appel à un fichier de suffixe .t2x et éventuellement à d'autres fichiers si on exécute plusieurs passes de ce type.
Post-fragmentation Fin du ou des traitement(s) inter-fragments Nécessaire si un ou plusieurs traitements inter-fragments ont été exécutés. Elle fait appel à un fichier de suffixe .t3x
Génération Génère la forme de surface des mots de la langue cible à partir de la décomposition en lemme + attributs obtenue suite aux étapes précédentes. Valable pour toutes les paires de langues, elle fait appel au dictionnaire morphologique de la langue cible.
Post-génération Permet des corrections orthographiques entre mots voisins lorsqu'il y a des cas particuliers non traités par la génération. Utilisé pour beaucoup de langues cibles (dont le français), peut être pas pour toutes.
Reformatage Remet les données traduites au format du document source. Les mêmes logiciels sont utilisés pour toutes les paires de langues. Il existe un reformateur pour chaque déformateur disponible bien que tous les reformateurs fassent un traitement similaire.

La page Préparation pour utiliser les outils de transfert donne un exemple de la manière dont une phrase espagnole est transformée à chaque étape du traitement pour aboutir finalement à une traduction en anglais.

Comment trouver ce qu'on doit faire[edit]

Fondamentalement, l'étape de transfert part d'une analyse désambiguïsée du texte en langue source pour fournir un équivalent dans la langue cible. L'étape de génération effectue alors le traitement inverse de l'analyse. Ça a une conséquence : il faut que les données fournies au générateur correspondent exactement à ce que donnerait une nouvelle analyse du texte traduit dans la langue cible. Sinon, la génération ne sera que partielle avec des # apparaissant au début de certains mots qui seront alors présentés sous la forme de lemmes.

Exemple :

On veut traduire en français les 3 mots espéranto :

la aŭtomata traduko

Après analyse et désambiguïsation, on obtient :

^la<det><def><sp>$ ^aŭtomata<adj><sg><nom>$ ^traduko<n><sg><nom>$

Une étape de transfert lexical (utilisant seulement le dictionnaire bilingue) donnera :

^le<det><def><sp>$ ^automatique<adj><sg><nom>$ ^traduction<n><f><sg><nom>$

Le morceau de phrase que l'on veut obtenir en français est :

la traduction automatique

En analysant ce morceau de phrase, on obtient :

^le<det><def><f><sg>$ ^traduction<n><f><sg>$ ^automatique<adj><mf><sg>$

qui est le texte qu'on devra fournir au générateur pour obtenir la traduction souhaitée.

Il faudra donc dans l'étape de transfert de structure réaliser la transformation suivante :

Origine :

^le<det><def><sp>$ ^automatique<adj><sg><nom>$ ^traduction<n><f><sg><nom>$

Résultat :

^le<det><def><f><sg>$ ^traduction<n><f><sg>$ ^automatique<adj><mf><sg>$

C'est pour cela, qu'on écrit des règles de transferts. Leur but est d'ajouter ou de supprimer certaines balises dans les descriptions de mots, et éventuellement de changer l'ordre de certains mots.

Structure d'un fichier .t1x[edit]

Le fichier contenant les règles de transfert a comme suffixe .t1x . Ce fichier est composé de plusieurs sections obligatoires et peut contenir d'autres sections facultatives. Chacune des sections devra contenir au moins un élément.

 <?xml version="1.0" encoding="UTF-8"?>
 <transfer>
    <section-def-cats>
       ..........
    </section-def-cats>

    <section-def-attrs>
       ..........
    </section-def-attrs>

    <section-def-vars>
       ..........
    </section-def-vars>

    <section-def-macros>
       ..........
    </section-def-macros>

    <section-rules>
       ..........
    </section-rules>
 </transfer>

Section def-cats[edit]

La section def-cats est obligatoire. Elle permet de déclarer des catégories de mots que l'on va rechercher pour appliquer une règle de transfert particulière. Il peut s'agir de mots simples (un article (déterminant), un nom, un adjectif, un verbe, ...) ou de choses un peu plus compliquées comme un nom possédant dans sa description la balise <nom> (nominatif) signifiant qu'il fait partie du sujet de la phrase.

Cette section contient un ou plusieurs éléments qui ont la structure suivante :

    <def-cat n="nom_de_ce_qu'on_veut_décrire">
      <cat-item tags="sa_description"/>
      .... (il peut y avoir une ou plusieurs balises <cat-item .../>)
    </def-cat>

Section def-attrs[edit]

La section def-attrs est obligatoire. Elle permet de regrouper par fonctionnalités des noms d'attributs de mots définis dans la section sdefs d'un dictionnaire morphologique. Par exemple, on regroupera dans cette section toutes les balises correspondant au :

  • genre d'un mot
  • nombre d'un mot (singulier, pluriel, ...)
  • personne d'un verbe
  • temps d'un verbe
  • ...

Cette section contient un ou plusieurs éléments qui ont la structure suivante :

    <def-attr n="nom_d'une_liste_d'attributs_jouant_un_rôle_commun">
      <attr-item tags="un_attribut_de_la_section_sdef_d'un_dictionnaire"/>
      .... (on a plusieurs balises <attr-item .../> autant que de valeurs
            possibles pour l'attribut)
    </def-attr>

Section def-vars[edit]

La section def-vars est obligatoire et doit comporter au moins un élément respectant la syntaxe <def-var n="..."/> . Il s'agit de lister les variables globales utilisées dans les règles de transferts. Toutefois, pour les règles décrites dans cette page, nous n'aurons besoin d'aucune de ces variables.

Section def-macros[edit]

La section def-macros est facultative. Néanmoins, elle sera très utile pour écrire des fichiers de transfert moins longs en évitant de dupliquer à l'identique (ou presque) un même traitement dans plusieurs règles de transfert.

Cette section contient un ou plusieurs éléments qui ont la structure suivante :

    <def-macro n="nom_de_la_macro" npar="nombre_de_paramètres">
      .... (le code de la macro)
    </def-macro>

Section rules[edit]

Enfin, La section rules est obligatoire. C'est la plus longue du fichier de transfert et celle qui justifie son existence. Elle permet en effet de définir les traitements à effectuer pour traduire des groupes de mots (ou quelquefois des mots isolés, comme on le verra).

Cette section contient un ou plusieurs éléments qui ont la structure suivante :

    <rule>
      <pattern>
        <pattern-item n="nom_défini_comme_def-cat_correspondant_au_premier_mot_à_traiter"/>
        .... (autant de balises <pattern-item ..../> que de mots qu'on veut traiter ensemble)
      </pattern>
      <action>
        .... (description de la règle de transfert)
      </action>
    </rule>

Exemples de règles de transfert[edit]

Transférer deux mots en les accordant[edit]

On va commencer par traduire en français l'article espéranto la suivi d'un nom commun.

Recherche des modifications à apporter[edit]

En espéranto, l'article défini la est invariant, alors qu'en français, il possède 3 formes : le, la, les selon le genre et le nombre du nom auquel il s'accorde.

Pour le nom commun, il a deux formes en espéranto selon qu'il fasse partie du sujet ou du complément d'objet dans la phrase. En français, il s'écrit pareil dans les deux cas.

Exemples :

Espéranto Analyse espéranto Français Analyse français
la tago
la tagon
^la<det><def><sp>$ ^tago<n><sg><nom>$
^la<det><def><sp>$ ^tago<n><sg><acc>$
le jour ^le<det><def><m><sg>$ ^jour<n><m><sg>$
la nokto
la nokton
^la<det><def><sp>$ ^nokto<n><sg><nom>$
^la<det><def><sp>$ ^nokto<n><sg><acc>$
la nuit ^le<det><def><f><sg>$ ^nuit<n><f><sg>$
la tagoj
la tagojn
^la<det><def><sp>$ ^tago<n><pl><nom>$
^la<det><def><sp>$ ^tago<n><pl><acc>$
les jours ^le<det><def><mf><pl>$ ^jour<n><m><pl>$
la noktoj
la noktojn
^la<det><def><sp>$ ^nokto<n><pl><nom>$
^la<det><def><sp>$ ^nokto<n><pl><acc>$
les nuits ^le<det><def><mf><pl>$ ^nuit<n><f><pl>$

Examinons ce que donne la traduction lexicale de l'analyse espéranto et comparons-la à l'analyse en français que l'on veut soumettre au générateur :

Analyse espéranto Analyse espéranto traduite en français L'analyse en français que l'on veut obtenir
^la<det><def><sp>$ ^tago<n><sg><nom>$
^la<det><def><sp>$ ^tago<n><sg><acc>$
^le<det><def><sp>$ ^jour<n><m><sg><nom>$
^le<det><def><sp>$ ^jour<n><m><sg><acc>$
^le<det><def><m><sg>$ ^jour<n><m><sg>$
^la<det><def><sp>$ ^nokto<n><sg><nom>$
^la<det><def><sp>$ ^nokto<n><sg><acc>$
^le<det><def><sp>$ ^nuit<n><f><sg><nom>$
^le<det><def><sp>$ ^nuit<n><f><sg><acc>$
^le<det><def><f><sg>$ ^nuit<n><f><sg>$
^la<det><def><sp>$ ^tago<n><pl><nom>$
^la<det><def><sp>$ ^tago<n><pl><acc>$
^le<det><def><sp>$ ^jour<n><m><pl><nom>$
^le<det><def><sp>$ ^jour<n><m><pl><acc>$
^le<det><def><m><pl>$ ^jour<n><m><pl>$
^la<det><def><sp>$ ^nokto<n><pl><nom>$
^la<det><def><sp>$ ^nokto<n><pl><acc>$
^le<det><def><sp>$ ^nuit<n><f><sg><nom>$
^le<det><def><sp>$ ^nuit<n><f><pl><acc>$
^le<det><def><f><pl>$ ^nuit<n><f><pl>$

On constate que :

  • pour l'article, la traduction lexicale donne systématiquement ^le<det><def><sp>$ . Il faudra remplacer la dernière balise <sp> (singulier ou pluriel) par les balises du nom commun indiquant son genre et son nombre.
  • pour le nom commun, la traduction lexicale a trouvé (dans le dictionnaire bilingue) le genre du nom traduit en français. Pour savoir si ce nom est au singulier ou au pluriel, elle a conservé l'attribut nombre de la langue d'origine. Par contre, on a aussi conservé les attributs <nom> ou <acc> dont on n'a pas besoin en français et qui empêcheraient la génération du mot. Il faudra donc les supprimer dans la règle de transfert.

Écriture de la règle de transfert[edit]

Pour cette première règle, nous partons d'un fichier de suffixe .t1x "vide" ayant la structure décrite ici.

La section def-macros étant facultative, comme elle n'est pas utilisée pour les premières règles de transfert décrites dans cette page, nous ne la mettrons pas pour l'instant.

La section def-vars est obligatoire. Bien qu'elle ne sera jamais utilisée dans les exemples de cette page, nous nous contenterons d'y mettre un contenu minimal pour que le fichier .t1x puisse être compilé :

  <section-def-vars>
    <def-var n="aucune_variable"/>
  </section-def-vars>

Les autres sections pourront contenir des informations utiles à notre première règle de transfert.

Section def-cats[edit]

Dans cette section, on va définir 2 catégories de mots :

  • les déterminants qu'on appellera det et qu'on identifiera dans les analyses par la balise <det> suivie de n'importe quoi.
  • les noms communs qu'on appellera nom_commun et qu'on identifiera dans les analyses par la balise <n> suivie de n'importe quoi.

La section def-cats s'écrira comme ceci :

  <section-def-cats>
    <def-cat n="det">
      <cat-item tags="det.*"/>
    </def-cat>

    <def-cat n="nom_commun">
      <cat-item tags="n.*"/>
    </def-cat>
  </section-def-cats>
  • les noms des catégories de mots sont dans l'attribut n des balises <def-cat n="...">
  • les description de ce qu'on doit trouver dans l'analyse pour reconnaître la catégorie de mot sont dans l'attribut tags des balises <cat-item tags="..."/>
Section def-attrs[edit]

On va à présent définir les attributs possibles pour les différentes balises des mots

  <section-def-attrs>
    <def-attr n="type_mot">
      <attr-item tags="n"/>
      <attr-item tags="det"/>
    </def-attr>

    <def-attr n="genre">
      <attr-item tags="m"/>
      <attr-item tags="f"/>
      <attr-item tags="mf"/>
    </def-attr>

    <def-attr n="nombre">
      <attr-item tags="sg"/>
      <attr-item tags="pl"/>
      <attr-item tags="sp"/>
    </def-attr>
  </section-def-attrs>
  • dans l'attribut n des balises <def-attr n="...">, on donne un nom aux différentes caractéristiques des mots que l'on veut traiter
  • pour chacune de ces caractéristiques, les balises <attr-item tags="..."/> indiquent les différentes valeurs possibles de cette caractéristique.

Dans le cas de la règle que l'on veut écrire, on a défini 3 caractéristiques :

  • type_mot (peut être pas obligatoire, mais il n'y a pas de solution alternative documentée). Pour l'instant, les types disponibles sont :
    • n (nom commun)
    • det (déterminant)
On en rajoutera plus tard lorsqu'on écrira d'autres règles.
  • genre avec comme valeurs possibles
    • m (masculin)
    • f (féminin)
    • mf (masculin ou féminin)
  • nombre avec comme valeurs possibles
    • sg (singulier)
    • pl (pluriel)
    • sp (singulier ou pluriel)
Section rules[edit]

Une section rules contenant uniquement la règle qu'on veut écrire contiendra :

  <section-rules>
    <rule>
      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="nom_commun"/>
      </pattern>
      <action>
        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <lit-tag v="def"/>
            <clip pos="2" side="tl" part="genre"/>
            <clip pos="2" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="genre"/>
            <clip pos="2" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>
  </section-rules>

La règle est composée de 2 sections :

      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="nom_commun"/>
      </pattern>

Dans ce morceau, on précise quelles sont les catégories de mots successives que l'on doit trouver dans l'analyse du texte source pour que la règle puisse s'appliquer. Dans le cas présent, il faudra trouver un déterminant, suivi d'un nom commun. Les attributs des balises <pattern-item n="..."/> doivent tous avoir été définis dans la section def-cats, sinon la règle ne pourra jamais être appliquée.

La partie la plus intéressante de la règle est à partir de la balise <action>. Elle a la structure suivante :

      <action>
        <out>
          <lu>
            ... (génération de l'unité lexicale pour le premier mot)
          </lu>
          <b />
          <lu>
            ... (génération de l'unité lexicale pour le deuxième mot)
          </lu>
        </out>
      </action>

Dans cette règle, on ne fait que générer des données que l'on envoie en sortie. Le contenu de la balise <action> se limite donc à de la génération de texte qui est indiquée par la balise <out>.

On devra générer l'analyse de 2 mots dans la langue cible. Chaque analyse de mot constitue une unité lexicale (balise <lu>) qui en sortie sera symbolisée par les caractères ^...$ où la description de l'unité lexicale remplacera les pointillés.

Entre les deux unités lexicales, on laissera un espace (balise ) sinon, les deux mots générés se toucheraient.

Examinons l'écriture de chacune des unités lexicales :

La première balise <clip pos="1" side="tl" part="lem"/> possède élément par élément la signification suivante :

Morceau Signification
clip C'est un mot-clé qui peut être traduit par "récupère"
pos="1" C'est le numéro du pattern-item dans la liste <pattern>...</pattern> de la règle. Ici, pos="1" correspond à l'analyse du déterminant
side="tl" On récupère l'information dans la langue cible. Pour accéder à la langue source, on mettrait side="sl"
part="lem" C'est un mot clé réservé correspondant au lemme.

La troisième balise <lit-tag v="def"/> possède élément par élément la signification suivante :

Morceau Signification
lit-tag C'est un mot-clé qui peut être traduit par "génère une balise"
v="def" On précise ici le contenu de la balise. Dans le cas présent, on générera <def>.

L'ensemble des 5 instructions nécessaires pour générer l'analyse du déterminant possède la signification suivante :

Instruction Signification
<clip pos="1" side="tl" part="lem"/> Récupérer le lemme du premier mot du pattern dans la langue cible. Ce sera toujours l'article français "le".
<clip pos="1" side="tl" part="type_mot"/> Récupérer le type du premier mot du pattern dans la langue cible. Ce sera det.
<lit-tag v="def"/> Générer une balise def, c'est à dire le texte <def> qui permet de préciser que l'article est défini.
<clip pos="2" side="tl" part="genre"/> Récupérer le genre du deuxième mot du pattern de la langue cible, c'est à dire le genre du nom commun.
<clip pos="2" side="tl" part="nombre"/> Récupérer le nombre du deuxième mot du pattern de la langue cible, c'est à dire le nombre du nom commun.

L'ensemble de ces 5 éléments récupérés constitue l'unité lexicale <lu>...</lu> qui sera envoyée en sortie grâce à la balise <out>...</out>

Pour la deuxième unité lexicale correspondant à la traduction du nom commun, on peut remarquer qu'on a dans chaque ligne : pos="2" side="tl" ce qui signifie qu'on recopiera simplement certaines balises du nom commun (2ème mot de la règle).

Explication détaillée des 4 instructions :

Instruction Signification
<clip pos="2" side="tl" part="lem"/> Récupérer le lemme du deuxième mot du pattern dans la langue cible (le nom commun en français).
<clip pos="2" side="tl" part="type_mot"/> Récupérer le type du deuxième mot. Ce sera n.
<clip pos="2" side="tl" part="genre"/> Récupérer le genre du nom commun.
<clip pos="2" side="tl" part="nombre"/> Récupérer le nombre du nom commun.
Remarque[edit]

Si on envoie au générateur le résultat obtenu en sortie du transfert, on n'obtient pas tout à fait ce qu'il faudrait :

Analyse Français Résultat génération Ce qu'il faudrait
^le<det><def><m><sg>$ ^jour<n><m><sg>$ ~le jour le jour
^le<det><def><f><sg>$ ^nuit<n><f><sg>$ ~la nuit la nuit
^le<det><def><mf><pl>$ ^jour<n><m><pl>$ ~les jours les jours
^le<det><def><mf><pl>$ ^nuit<n><f><pl>$ ~les nuits les nuits
^le<det><def><m><sg>$ ^arbre<n><m><sg>$ ~le arbre l'arbre
^le<det><def><f><sg>$ ^histoire<n><f><sg>$ ~la histoire l'histoire
^le<det><def><m><pl>$ ^arbre<n><m><pl>$ ~les arbres les arbres
^le<det><def><f><pl>$ ^histoire<n><f><pl>$ ~les histoires les histoires

Le remplacement de l'article le/la par l' en fonction de la première lettre du mot suivant n'est pas fait au moment de la génération mais juste après dans l'étape de post-génération qui s'occupe des mots marqués par une ~ . Cette remarque étant faite, la post-génération ne sera plus mentionnée dans cette page.

Rajouter un mot dans la langue cible[edit]

L'espéranto ne possède pas d'article indéfini. Pour exprimer un, une, des, on se contente de ne pas mettre l'article défini la devant la nom commun. Un nom commun isolé écrit en espéranto devra donc être précédé de l'article indéfini un, une ou des adéquat, si on le traduit en français.

Notre deuxième règle va faire cette transformation.

Examinons ce que donne la traduction lexicale de l'analyse espéranto et comparons-la à l'analyse en français que l'on veut soumettre au générateur :

Analyse espéranto Analyse espéranto traduite en français L'analyse en français que l'on veut obtenir
^tago<n><sg><nom>$
^tago<n><sg><acc>$
^jour<n><m><sg><nom>$
^jour<n><m><sg><acc>$
^un<det><ind><m><sg>$ ^jour<n><m><sg>$
^nokto<n><sg><nom>$
^nokto<n><sg><acc>$
^nuit<n><f><sg><nom>$
^nuit<n><f><sg><acc>$
^un<det><ind><f><sg>$ ^nuit<n><f><sg>$
^tago<n><pl><nom>$
^tago<n><pl><acc>$
^jour<n><m><pl><nom>$
^jour<n><m><pl><acc>$
^un<det><ind><m><pl>$ ^jour<n><m><pl>$
^nokto<n><pl><nom>$
^nokto<n><pl><acc>$
^nuit<n><f><sg><nom>$
^nuit<n><f><pl><acc>$
^un<det><ind><f><pl>$ ^nuit<n><f><pl>$

Par rapport à la règle précédente, au lieu de générer ^le<det><def><genre><nombre>$ on va générer ^un<det><ind><genre><nombre>$. Tout le reste est sans changement.

Pour écrire la nouvelle règle, on dispose déjà de tout ce qu'il faut dans les sections def-cats et def-attrs. Il suffira donc de rajouter la nouvelle règle dans la section rules qui va devenir :

  <section-rules>
    <rule>
      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="nom_commun"/>
      </pattern>
      <action>
        ... (voir le contenu au paragraphe précédent)
      </action>
    </rule>

    <rule>
      <pattern>
        <pattern-item n="nom_commun"/>
      </pattern>
      <action>
        <out>
          <lu>
            <lit v="un"/>
            <lit-tag v="det.ind"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

Dans cette nouvelle règle, on trouve pour la première fois l'instruction lit qui va générer une chaîne de caractères, par opposition à lit-tag qui englobe la chaîne générée de < > pour qu'elle devienne une balise.

Comme dans le texte de la langue source à transférer, il n'y a qu'un mot (le nom commun mentionné dans le pattern), on accède à ses attributs par pos="1" alors que c'était pos="2" dans la première règle.

Les 4 instructions nécessaires pour générer l'analyse de l'article indéfini possèdent la signification suivante :

Instruction Signification
<lit v="un"> Générer le lemme "un".
<lit-tag v="det.ind"/> Générer une balise det suivie d'une balise ind, c'est à dire le texte <det><ind> qui permet de préciser qu'on génère un article indéfini.
<clip pos="1" side="tl" part="genre"/> Récupérer le genre du nom commun.
<clip pos="1" side="tl" part="nombre"/> Récupérer le nombre du nom commun.

Les instructions pour générer la traduction en français du nom commun sont les mêmes que pour la règle précédente, à part que maintenant pos="1".

Intervertir deux mots[edit]

Nous allons voir à présent une règle pour changer l'ordre de deux mots lors d'une traduction.

En espéranto, il est préconisé de mettre l'adjectif avant le nom mais ce n'est pas imposé. Le traducteur Apertium espagnol -> espéranto conserve l'ordre des mots de la phrase espagnole alors que le traducteur Apertium français -> espéranto met l'adjectif avant le nom.

En français, la plupart des adjectifs se placent après le nom qu'ils qualifient, mais certains adjectifs se placent avant.

La solution complète traiterait tous les cas possibles en espéranto comme en français. Nous allons nous limiter au cas le plus fréquent en réalisant une règle qui à partir d'une forme "la" + adjectif + nom en espéranto, fournit une traduction du type "le/la/les" + nom + adjectif en français.

Rajout dans la section def-cats[edit]

Dans cette section, nous allons rajouter une catégorie pour les adjectifs :

    <def-cat n="adj">
      <cat-item tags="adj.*"/>
    </def-cat>

Rajout dans la section def-attrs[edit]

Dans les types de mots, on rajoute les adjectifs :

    <def-attr n="type_mot">
      <attr-item tags="n"/>
      <attr-item tags="det"/>
      <attr-item tags="adj"/>
    </def-attr>

Rajout de la règle qui va intervertir l'adjectif et le nom[edit]

    <rule>
      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="adj"/>
        <pattern-item n="nom_commun"/>
      </pattern>

      <action>
        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <lit-tag v="def"/>
            <clip pos="3" side="tl" part="genre"/>
            <clip pos="3" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="3" side="tl" part="lem"/>
            <clip pos="3" side="tl" part="type_mot"/>
            <clip pos="3" side="tl" part="genre"/>
            <clip pos="3" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="3" side="tl" part="genre"/>
            <clip pos="3" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

On constate dans cette règle qu'on génère d'abord le déterminant (pos = 1), puis le nom (pos = 3 dans le pattern) et enfin l'adjectif (pos = 2 dans le pattern). Pour intervertir deux mots, il a suffit de générer les unités lexicales <lu>...</lu> dans un ordre différent.

Dans cette règle, le déterminant et l'adjectif s'accordent en genre et en nombre avec le nom.

Changer des attributs en fonction de conditions[edit]

A présent, nous allons examiner une règle permettant de traduire un pronom personnel suivi d'un verbe en appliquant les règles de conjugaison.

Recherche des modifications à apporter[edit]

  • En espéranto, le verbe est invariant par rapport au pronom personnel qui le précède (ou plus généralement par rapport au sujet)
  • En français, le verbe s'accorde avec la personne et le nombre du pronom personnel (mais pas son genre)

De plus, certains pronoms personnel du français n'ont pas d'équivalent spécifique en espéranto qui sur ce point est comme l'anglais :

  • tu (2ème personne du singulier) et vous (2ème personne du pluriel) en français sont tous deux traduits par vi en espéranto.
  • ils et elles (les formes masculines et féminines de la 3ème personne du pluriel) sont traduites par ili en espéranto.

pour traduire de l'espéranto au français, on fera donc des choix :

  • vivous 2ème personne du pluriel ou forme de politesse pour s'adresser à une seule personne
  • iliils on choisit le masculin pour la 3ème personne du pluriel en français.

De même, l'espéranto ne dispose que d'un temps pour le passé là où le français en a quatre. En plus, dans une analyse, les dictionnaires espéranto et français n'utilisent pas la même abréviation pour le présent de l'indicatif. Il faudra donc changer tout ça lors de la traduction.

Nous allons voir ce que tout cela donne pour le verbe kantichanter conjugué au présent de l'indicatif.

Espéranto Analyse espéranto Analyse espéranto traduite L'analyse qu'on voudrait Français
mi kantas ^prpers<prn><subj><p1><mf><sg>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p1><mf><sg>$
^chanter<vblex><pres>$
^prpers<prn><p1><mf><sg>$
^chanter<vblex><pri><p1><sg>$
je chante
vi kantas ^prpers<prn><subj><p2><mf><sp>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p2><mf><sp>$
^chanter<vblex><pres>$
^prpers<prn><p2><mf><pl>$
^chanter<vblex><pri><p2><pl>$
tu chantes →
vous chantez
li kantas ^prpers<prn><subj><p3><m><sg>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p3><m><sg>$
^chanter<vblex><pres>$
^prpers<prn><p3><m><sg>$
^chanter<vblex><pri><p3><sg>$
il chante
ŝi kantas ^prpers<prn><subj><p3><f><sg>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p3><f><sg>$
^chanter<vblex><pres>$
^prpers<prn><p3><f><sg>$
^chanter<vblex><pri><p3><sg>$
elle chante
ni kantas ^prpers<prn><subj><p1><mf><pl>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p1><mf><pl>$
^chanter<vblex><pres>$
^prpers<prn><p1><mf><pl>$
^chanter<vblex><pri><p1><pl>$
nous chantons
vi kantas ^prpers<prn><subj><p2><mf><sp>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p2><mf><sp>$
^chanter<vblex><pres>$
^prpers<prn><p2><mf><pl>$
^chanter<vblex><pri><p2><pl>$
vous chantez
ili kantas ^prpers<prn><subj><p3><mf><pl>$
^kanti<vbtr_ntr><pres>$
^prpers<prn><p3><mf><pl>$
^chanter<vblex><pres>$
^prpers<prn><p3><m><pl>$
^chanter<vblex><pri><p3><pl>$
ils chantent
(elles chantent)

Écriture de la règle de transfert[edit]

Rajouts dans la section def-cats[edit]

Dans cette section, nous allons rajouter une catégorie pour les pronoms et une catégorie pour les verbes :

    <def-cat n="prn">
      <cat-item tags="prn.*"/>
    </def-cat>

    <def-cat n="verbe">
      <cat-item tags="vbser.*"/>
      <cat-item tags="vblex.*"/>
      <cat-item tags="vbtr.*"/>
      <cat-item tags="vbntr.*"/>
      <cat-item tags="vbtr_ntr.*"/>
    </def-cat>

Comme il existe en espéranto plusieurs formes pour les verbes, on a mis plusieurs cat-item pour les énumérer toutes.

Rajouts dans la section def-attrs[edit]

En ce qui concerne les verbes, différents mots clés sont utilisés en espéranto, alors qu'en français, presque tous les verbes sont classés vblex.

Dans les types de mots, on rajoute les verbes (plusieurs possibilités) et les pronoms :

    <def-attr n="type_mot">
      .......... (ce qu'il y avait avant)
      <attr-item tags="prn"/>
      <attr-item tags="vblex"/>
      <attr-item tags="vbmod"/>
      <attr-item tags="vbser"/>
      <attr-item tags="vbhaver"/>
    </def-attr>

On rajoute aussi les 2 catégories personne et temps pour la conjugaison des verbes:

    <def-attr n="personne">
      <attr-item tags="p1"/>
      <attr-item tags="p2"/>
      <attr-item tags="p3"/>
    </def-attr>

    <def-attr n="temps">
      <attr-item tags="pres"/>
      <attr-item tags="past"/>
      <attr-item tags="pri"/>
      <attr-item tags="pii"/>
      <attr-item tags="fti"/>
    </def-attr>

Avant d'écrire la section rules, certaines transformations sont nécessaires pour le temps des verbes et pour le genre et le nombre des pronoms.

Transformation du temps[edit]

Pour cet exemple, on se limitera aux temps de l'indicatif.

En espéranto, il y a 3 temps pour l'indicatif :

  • le passé : past
  • le présent : pres
  • le futur : fti

En français, il y a 6 temps plus ou moins courants pour l'indicatif :

  • l'imparfait :pii
  • le passé simple : ifi
  • le passé composé qu'il faudrait fabriquer avec le verbe avoir + le participe passé.
  • le plus que parfait (même problème que pour le passé composé)
  • le présent : pri
  • le futur : fti

Pour les verbes au futur, l'attribut fti peut être conservé sans changement

Pour les verbes au présent, il faudra remplacer l'attribut pres de l'espéranto par pri.

Pour les verbes au passé, le passé composé serait pas mal pour une traduction, mais moins facile à générer. On va pour cet exemple remplacer l'attribut past de l'espéranto par pii (imparfait).

Sous forme algorithmique, cela donne les transformations conditionnelles suivantes :

 SI temps = "pres" ALORS
     temps <- "pri"
 SINON SI temps = "past" ALORS
     temps <- "pii"
 FIN SI
Transformation des attributs du pronom[edit]

Pour le pronom, on fera les changements suivants :

 SI personne = "p2" ALORS
     nombre <- "pl"
 SINON SI (personne = "p3" ET nombre = "pl" ALORS
     genre <- "m"
 FIN SI
Section rules[edit]

La nouvelle règle a le contenu suivant :

    <rule>
      <pattern>
        <pattern-item n="prn"/>
        <pattern-item n="verbe"/>
      </pattern>

      <action>

        <choose>
          <when>
            <test>
               <equal>
                  <clip pos="2" side="sl" part="temps"/>
                  <lit-tag v="pres"/>
                </equal>
            </test>
            <let>
              <clip pos="2" side="tl" part="temps"/>
              <lit-tag v="pri"/>
            </let>
          </when>
          <when>
            <test>
               <equal>
                  <clip pos="2" side="sl" part="temps"/>
                  <lit-tag v="past"/>
                </equal>
            </test>
            <let>
              <clip pos="2" side="tl" part="temps"/>
              <lit-tag v="pii"/>
            </let>
          </when>
        </choose>

        <choose>    <!--  cas particuliers de transferts des pronoms  -->
          <when>    <!--  2ème personne toujours au pluriel : vi -> vous  -->
            <test>
               <equal>
                  <clip pos="1" side="sl" part="personne"/>
                  <lit-tag v="p2"/>
                </equal>
            </test>
            <let>
              <clip pos="1" side="tl" part="nombre"/>
              <lit-tag v="pl"/>
            </let>
          </when>
          <when>    <!--  3ème personne du pluriel toujours au masculin : ili -> ils  -->
            <test>
               <and>
                 <equal>
                    <clip pos="1" side="sl" part="personne"/>
                    <lit-tag v="p3"/>
                  </equal>
                 <equal>
                    <clip pos="1" side="sl" part="nombre"/>
                    <lit-tag v="pl"/>
                  </equal>
                </and>
            </test>
            <let>
              <clip pos="1" side="tl" part="genre"/>
              <lit-tag v="m"/>
            </let>
          </when>
        </choose>

        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="temps"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

Pour la première fois, la partie action de la règle ne se limite pas à un bloc <out>...</out>, mais commence par deux blocs choose ayant chacun la structure suivante :

        <choose>
          <when>
            <test>
               .... (une condition)
            </test>
            <let>
               .... (action si cette condition est réalisée)
            </let>
          </when>
          <when>
            <test>
               .... (condition alternative à la précédente)
            </test>
            <let>
               .... (action si la condition alternative est réalisée)
            </let>
          </when>
        </choose>

Examinons en détail le premier bloc <when>...</when>

          <when>
            <test>
               <equal>
                  <clip pos="2" side="sl" part="temps"/>
                  <lit-tag v="pres"/>
                </equal>
            </test>
            <let>
              <clip pos="2" side="tl" part="temps"/>
              <lit-tag v="pri"/>
            </let>
          </when>

Nous commençons par l'intérieur des balises, puis on remontera vers les balises englobantes.

Instruction Signification
<clip pos="2" side="sl" part="temps"/> Récupère l'attribut "temps" du 2ème mot concerné par la règle (c'est à dire le verbe) du coté langue source
<lit-tag v="pres"/> Génère une balise pres
<equal>...</equal> Vérifie si'il y a égalité entre les 2 valeurs précédentes
<test>...</test> Décide si on doit exécuter le bloc d'instruction placé juste après.

Ensuite, voici ce qui est fait lorsque la condition du test est vraie :

Instruction Signification
<clip pos="2" side="tl" part="temps"/> Récupère (ou accède à) l'attribut "temps" du 2ème mot concerné par la règle (c'est à dire le verbe) du coté langue cible
<lit-tag v="pri"/> Génère une balise pri
<let>...</let> Semble correspondre à une affectation de la 2ème valeur dans la première

De la même manière, le deuxième bloc <when>...</when>

          <when>
            <test>
               <equal>
                  <clip pos="2" side="sl" part="temps"/>
                  <lit-tag v="past"/>
                </equal>
            </test>
            <let>
              <clip pos="2" side="tl" part="temps"/>
              <lit-tag v="pii"/>
            </let>
          </when>

teste si le temps du verbe correspond au passé ("past") et dans ce cas lui donne la valeur "pii" pour la langue cible.

Dans les instructions conditionnelles qui concernent le pronom, on trouve un bloc test plus compliqué :

            <test>
               <and>
                 <equal>
                    <clip pos="1" side="sl" part="personne"/>
                    <lit-tag v="p3"/>
                  </equal>
                 <equal>
                    <clip pos="1" side="sl" part="nombre"/>
                    <lit-tag v="pl"/>
                  </equal>
                </and>
            </test>

à l'intérieur du bloc <and>...</and>, il y a deux blocs <equal>...</equal> (il pourrait y en avoir davantage) et la condition est vraie si des deux égalités sont vérifiées simultanément : dans le cas présent "p3" pour l'attribut personne et "pl" pour l'attribut nombre.

Dans d'autres règles, on pourrait aussi trouver des blocs <or>...</or> pour lesquels la condition est vraie si au moins l'une des conditions présentes dans le bloc l'est.

De même, il existe des balises <not> et </not> pour prendre l'opposé d'une condition. Si deux choses qu'on compare doivent être différentes, on écrira :

     <not>
       <equal>
          ......
       </equal>
     </not>

Pour terminer, on pourrait se demander si les deux blocs choose de la règle qu'on vient d'étudier pourrait être regroupés en un seul.

Un essai montre que non. Lorsqu'à l'intérieur d'un bloc <choose>...</choose> on trouve plusieurs blocs <when>...</when>, le premier de ces blocs pour lequel la condition est réalisée voit les instructions du bloc <let>...</let> exécutées, et ensuite, les autres blocs <when>...</when> qui suivent ne sont pas traités. Les différents tests à l'intérieur des blocs <when>...</when> concernent des conditions exclusives que l'on traduit en langage algorithmique par SINON SI. Il existe d'ailleurs la possibilité de mettre un bloc <otherwise>...</otherwise> pour préciser ce qui doit être fait lorsqu'aucune des conditions des différents blocs <when>...</when> n'est vraie. Ce qui correspond en langage algorithmique au mot-clé SINON.

La fin de la règle :

       ......
        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="temps"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

ne présente pas de nouvelle difficulté de compréhension. On va envoyer en sortie deux unités lexicales correspondants chacune à la traduction d'un mot, et pour le faire, on va utiliser les nouvelles valeurs des attributs que l'on a modifiés.

N'écrire qu'une fois des traitements communs à plusieurs règles[edit]

Après avoir écrit une règle pour un pronom personnel suivi d'un verbe, nous allons en rajouter 2 autres pour un nom (sujet dans la phrase) suivi d'un verbe et pour un article (déterminant), suivi d'un nom (sujet), puis d'un verbe.

Une première nouveauté est qu'on ne va pas se contenter de chercher des groupes de mots (déterminant, nom, verbe, adjectif, ...) mais qu'on rajoute une contrainte : le nom doit faire partie du sujet de la phrase. En espéranto, un nom qui sert de sujet n'est pas terminé par la lettre n et dans son analyse, on trouvera la balise <nom> (nominatif) alors que pour un complément d'objet, on a la balise <acc> (accusatif).

Par ailleurs, les deux nouvelles règles ont un point commun avec la règle précédente : il faudra faire des transformations sur le temps du verbe qui ne s'écrit pas pareil dans tous les cas en espéranto et en français. Mais cette transformation va être la même dans toutes les règles comprenant un verbe conjugué. Donc, autant ne l'écrire qu'à un seul endroit et l'utiliser autant de fois que nécessaire. Outre l'économie de code, un seul exemplaire sera plus facile à compléter pour rajouter les temps du conditionnel et du subjonctif ou n'importe quelle autre correction. En programmation, on utilise des fonctions pour définir des morceaux de codes utilisés à plusieurs endroits du programme. Pour les règles de transfert, ce sont des macros.

Définition d'un type de mot avec des attributs[edit]

Pour définir un nom possédant l'attribut <nom> dans ses balises, il suffit de rajouter une catégorie :

    <def-cat n="nom_sujet">
      <cat-item tags="n.*.nom"/>
    </def-cat>

La page Introduction aux règles de transfert précise que le .* lorsqu'il n'est pas placé à la fin signifie "une seule balise". C'est le cas pour les analyses de la plupart des noms espéranto qui n'ont pas de genre. Toutefois, il semble que cette définition fonctionne aussi avec 2 balises entre le n et le <nom>. Sinon, au pire, pour les noms possédant un genre (humains et animaux), on pourrait rajouter un deuxième cat-item :

      <cat-item tags="n.*.*.nom"/>

pour spécifier 2 balises intermédiaires.

Écriture d'une macro[edit]

Maintenant, nous allons mettre dans une macro les opérations nécessaires au transfert du temps d'un verbe. Comme c'est notre première macro, il va falloir créer la section def-macros (qui est une section facultative) avec le contenu suivant :

  <section-def-macros>
    <def-macro n="set_temps" npar="1">    <!--  concordance des temps  -->
      <choose>
        <when>
          <test>
             <equal>
                <clip pos="1" side="sl" part="temps"/>
                <lit-tag v="pres"/>
              </equal>
          </test>
          <let>
            <clip pos="1" side="tl" part="temps"/>
            <lit-tag v="pri"/>
          </let>
        </when>
        <when>
          <test>
             <equal>
                <clip pos="1" side="sl" part="temps"/>
                <lit-tag v="past"/>
              </equal>
          </test>
          <let>
            <clip pos="1" side="tl" part="temps"/>
            <lit-tag v="pii"/>
          </let>
        </when>
      </choose>
    </def-macro>
  </section-def-macros>

La seule vrai nouveauté est l'instruction : <def-macro n="set_temps" npar="1"> :

Elle contient 2 informations :

Paramètre Signification
n="set_temps" le nom qu'on donne à la macro
npar="1" le nombre de paramètres de la macro

Ensuite, le code est identique à celui qu'on avait écrit pour la règle pronom personnel + verbe, à part que dans cette règle, on précisait pos="2" (le verbe était le 2ème mot du pattern), alors qu'ici, on a pos="1" qui est le numéro du paramètre de la macro. Or cette macro n'a besoin que d'un paramètre de type verbe pour fonctionner.

Règles de transfert utilisant la macro[edit]

Voyons donc comment est utilisée la macro dans la règle précédente (transformée) et les deux nouvelles règles :

    <rule>
      <pattern>
        <pattern-item n="prn"/>
        <pattern-item n="verbe"/>
      </pattern>

      <action>
        <choose>    <!--  cas particuliers de transferts des pronoms  -->
          <when>    <!--  2ème personne toujours au pluriel : vi -> vous  -->
            <test>
               <equal>
                  <clip pos="1" side="sl" part="personne"/>
                  <lit-tag v="p2"/>
                </equal>
            </test>
            <let>
              <clip pos="1" side="tl" part="nombre"/>
              <lit-tag v="pl"/>
            </let>
          </when>
          <when>    <!--  3ème personne du pluriel toujours au masculin : ili -> ils  -->
            <test>
               <and>
                 <equal>
                    <clip pos="1" side="sl" part="personne"/>
                    <lit-tag v="p3"/>
                  </equal>
                 <equal>
                    <clip pos="1" side="sl" part="nombre"/>
                    <lit-tag v="pl"/>
                  </equal>
                </and>
            </test>
            <let>
              <clip pos="1" side="tl" part="genre"/>
              <lit-tag v="m"/>
            </let>
          </when>
        </choose>

        <call-macro n="set_temps">
          <with-param pos="2"/>
        </call-macro>

        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="temps"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

    <rule>
      <pattern>
        <pattern-item n="nom_sujet"/>
        <pattern-item n="verbe"/>
      </pattern>

      <action>
        <call-macro n="set_temps">
          <with-param pos="2"/>
        </call-macro>

        <out>
          <lu>
            <lit v="un"/>
            <lit-tag v="det.ind"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="temps"/>
            <lit-tag v="p3"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

    <rule>
      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="nom_sujet"/>
        <pattern-item n="verbe"/>
      </pattern>

      <action>
        <call-macro n="set_temps">
          <with-param pos="3"/>
        </call-macro>

        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <lit-tag v="def"/>
            <clip pos="2" side="tl" part="genre"/>
            <clip pos="2" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <clip pos="2" side="tl" part="type_mot"/>
            <clip pos="2" side="tl" part="genre"/>
            <clip pos="2" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="3" side="tl" part="lem"/>
            <clip pos="3" side="tl" part="type_mot"/>
            <clip pos="3" side="tl" part="temps"/>
            <lit-tag v="p3"/>
            <clip pos="2" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

Dans les deux premières règles correspondant aux patterns suivant :

      <pattern>
        <pattern-item n="prn"/>
        <pattern-item n="verbe"/>
      </pattern>

et

      <pattern>
        <pattern-item n="nom_sujet"/>
        <pattern-item n="verbe"/>
      </pattern>

on appelle la macro ainsi :

        <call-macro n="set_temps">
          <with-param pos="2"/>
        </call-macro>

alors que pour la dernière règle correspondant au pattern :

      <pattern>
        <pattern-item n="det"/>
        <pattern-item n="nom_sujet"/>
        <pattern-item n="verbe"/>
      </pattern>

l'appel de la macro devient :

        <call-macro n="set_temps">
          <with-param pos="3"/>
        </call-macro>

Dans chacun des 3 cas, la valeur de pos de la balise with-param correspond à la position du verbe dans le pattern. En procédant ainsi, on va transmettre à la macro toutes les informations concernant le verbe dans la langue source et la langue cible.

Et si on voulait faire une macro avec plusieurs paramètres, il y aurait autant de balises with-param que de paramètres dans l'appel de cette nouvelle macro.

Le reste des deux dernières règles de transfert ne contient pas de difficulté particulière :

  • on génère l'analyse d'un déterminant accordé au nom
  • puis celle du nom

comme on le faisait dans les règles qui n'avaient pas de verbe.

Ensuite, on génère l'analyse du verbe, utilisant l'attribut temps mis à jour dans la macro. Ce verbe est conjugué à la 3ème personne avec le nombre (singulier ou pluriel) du nom sujet dans la phrase.

Utilisation de variables[edit]

Pour terminer, nous allons examiner une règle qui nécessite de mémoriser une valeur dans une variable.

Cette règle va traduire un pronom personnel, suivi du verbe être, puis d'un autre verbe au participe passé.

Nous savons déjà traiter le pronom suivi d'un verbe, on l'a fait au paragraphe Changer des attributs en fonction de conditions. Il restera à accorder le participe passé avec le pronom personnel. Mais un problème se pose :

  • à la 1ère et la 2ème personne, le pronom personnel doit avoir le genre mf (masculin/féminin) pour être généré,
  • pour le participe passé, les genres autorisés sont m et f (masculin ou féminin, mais seulement l'un des deux).

En conséquence, on ne pourra pas toujours utiliser la même balise pour le genre du pronom personnel et celui du participe passé. L'idée pour s'en sortir est de fabriquer le genre du participe passé à partir de celui du pronom personnel et d'utiliser une variable pour mémoriser le résultat.

Le calcul du genre du participe passé est le suivant :

 SI genre du pronom = "mf" ALORS
     genre_pp <- "m"
 SINON
     genre_pp <- genre du pronom
 FIN SI

La variable qui mémorise le genre du participe passé s'appelle genre_pp. Dans le cas du pronom personnel à la 1ère ou la 2ème personne, il faudrait faire une analyse profonde pour trouver (éventuellement dans une phrase précédente) le meilleur genre pour accorder le participe passé. Apertium ne permet pas ce genre d'analyse complexe. On choisira donc le masculin dans ce cas. Au contraire, si le pronom personnel est à la 3ème personne, on utilisera son genre pour le participe passé.

Une première chose à faire est de déclarer la variable. Pour cela, la section def-vars devient :

  <section-def-vars>
    <def-var n="genre_pp"/>
  </section-def-vars>

Nous n'avons pas encore écrit de règle utilisant le verbe être conjugué ou le participe passé. Il faudra donc compléter la section def-cats en rajoutant les deux déclarations :

    <def-cat n="etre_conj">
      <cat-item tags="vbser.pres"/>
      <cat-item tags="vbser.past"/>
      <cat-item tags="vbser.fti"/>
    </def-cat>

    <def-cat n="verbe_pp">
      <cat-item tags="vbser.pp.*"/>
      <cat-item tags="vblex.pp.*"/>
      <cat-item tags="vbtr.pp.*"/>
      <cat-item tags="vbntr.pp.*"/>
      <cat-item tags="vbtr_ntr.pp.*"/>
    </def-cat>

La règle effectuant le travail demandé est la suivante :

    <rule>
      <pattern>
        <pattern-item n="prn"/>
        <pattern-item n="etre_conj"/>
        <pattern-item n="verbe_pp"/>
      </pattern>

      <action>
        <choose>    <!--  cas particuliers de transferts des pronoms  -->
          <when>    <!--  2ème personne toujours au pluriel : vi -> vous  -->
            <test>
               <equal>
                  <clip pos="1" side="sl" part="personne"/>
                  <lit-tag v="p2"/>
                </equal>
            </test>
            <let>
              <clip pos="1" side="tl" part="nombre"/>
              <lit-tag v="pl"/>
            </let>
          </when>
          <when>    <!--  3ème personne du pluriel toujours au masculin : ili -> ils  -->
            <test>
               <and>
                 <equal>
                    <clip pos="1" side="sl" part="personne"/>
                    <lit-tag v="p3"/>
                  </equal>
                 <equal>
                    <clip pos="1" side="sl" part="nombre"/>
                    <lit-tag v="pl"/>
                  </equal>
                </and>
            </test>
            <let>
              <clip pos="1" side="tl" part="genre"/>
              <lit-tag v="m"/>
            </let>
          </when>
        </choose>

        <choose>    <!--  si le genre du pronom est mf, celui du participe passé sera m  -->
          <when>
            <test>
               <equal>
                  <clip pos="1" side="tl" part="genre"/>
                  <lit-tag v="mf"/>
                </equal>
            </test>
            <let>
              <var n="genre_pp"/>
              <lit-tag v="m"/>
            </let>
          </when>
          <otherwise>
            <let>
              <var n="genre_pp"/>
              <clip pos="1" side="tl" part="genre"/>
            </let>
          </otherwise>
        </choose>

        <call-macro n="set_temps">
          <with-param pos="2"/>
        </call-macro>

        <out>
          <lu>
            <clip pos="1" side="tl" part="lem"/>
            <clip pos="1" side="tl" part="type_mot"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="genre"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="2" side="tl" part="lem"/>
            <lit-tag v="vbser"/>
            <clip pos="2" side="tl" part="temps"/>
            <clip pos="1" side="tl" part="personne"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
          <b />
          <lu>
            <clip pos="3" side="tl" part="lem"/>
            <clip pos="3" side="tl" part="type_mot"/>
            <lit-tag v="pp"/>
            <var n="genre_pp"/>
            <clip pos="1" side="tl" part="nombre"/>
          </lu>
        </out>
      </action>
    </rule>

La partie vraiment nouvelle de la règle est le morceau :

    <choose>    <!--  si le genre du pronom est mf, celui du participe passé sera m  -->
      <when>
        <test>
           <equal>
              <clip pos="1" side="tl" part="genre"/>
              <lit-tag v="mf"/>
            </equal>
        </test>
        <let>
          <var n="genre_pp"/>
          <lit-tag v="m"/>
        </let>
      </when>
      <otherwise>
        <let>
          <var n="genre_pp"/>
          <clip pos="1" side="tl" part="genre"/>
        </let>
      </otherwise>
    </choose>

Il comporte deux affectations de valeurs dans la variable genre_pp :

        <let>
          <var n="genre_pp"/>
          <lit-tag v="m"/>
        </let>

qui permet de mettre dans genre_pp la balise <m>

        <let>
          <var n="genre_pp"/>
          <clip pos="1" side="tl" part="genre"/>
        </let>

qui permet de mettre dans genre_pp le genre du pronom personnel.

On peut aussi remarquer que le traitement conditionnel réalisé utilise pour la première fois les balises <otherwise>...</otherwise> .

Il ne reste plus qu'à utiliser la variable genre_pp pour générer l'unité lexicale relative au participe passé :

    <lu>
      <clip pos="3" side="tl" part="lem"/>
      <clip pos="3" side="tl" part="type_mot"/>
      <lit-tag v="pp"/>
      <var n="genre_pp"/>
      <clip pos="1" side="tl" part="nombre"/>
    </lu>

C'est la même instruction :

      <var n="genre_pp"/>

qui permet d'initialiser la variable ou d'accéder à la valeur qu'elle contient.