Difference between revisions of "Transfer rules examples"

From Apertium
Jump to navigation Jump to search
(going on with the translation)
Line 189: Line 189:
 
== Examples of transfer rules ==
 
== Examples of transfer rules ==
   
  +
=== Transfering two words making them agree ===
''the following part will have to be translated later''
 
   
  +
We will start to translate to French the Esperanto determinant '''la''' followed buy a common noun.
=== Transférer deux mots en les accordant ===
 
   
 
==== Search for modifications ====
On va commencer par traduire en French l'article Esperanto '''la''' suivi d'un nom commun.
 
 
==== Recherche des modifications à apporter ====
 
   
En Esperanto, l'article défini '''la''' est invariant, alors qu'en French, il possède 3 formes : '''le''', '''la''', '''les''' selon le genre et le nombre du nom auquel il s'accorde.
+
In Esperanto, the definite determinant '''la''' is invariant, while in French, it has three forms: '''le''', '''la''', '''les''' according to gender and number of the noun to witch it agrees.
   
Pour le nom commun, il a deux formes en Esperanto selon qu'il fasse partie du sujet ou du complément d'objet dans la phrase. En French, il s'écrit pareil dans les deux cas.
+
For the common noun, there are two forms in Esperanto depending on it belongs to the subject or the object complement in the sentence. In French, it is written the same in both cases.
   
 
'''Examples :'''
 
'''Examples :'''
   
 
{|class=wikitable
 
{|class=wikitable
! Esperanto !! Analyse Esperanto !! French !! Analyse French
+
! Esperanto !! Esperanto analyzes !! French !! French analyzes
 
|-
 
|-
 
| la tago<br/>la tagon || ^la<det><def><sp>$ ^tago<n><sg><nom>$<br/>^la<det><def><sp>$ ^tago<n><sg><acc>$
 
| la tago<br/>la tagon || ^la<det><def><sp>$ ^tago<n><sg><nom>$<br/>^la<det><def><sp>$ ^tago<n><sg><acc>$
Line 220: Line 218:
 
|}
 
|}
   
  +
Let examine what the lexical translation of the Esperanto analysis gives and compare it to the analysis in French we wants to submit to the generator:
Examinons ce que donne la traduction lexicale de l'analyse Esperanto et comparons-la à l'analyse en French que l'on veut soumettre au générateur :
 
   
 
{|class=wikitable
 
{|class=wikitable
! Analyse Esperanto !! Analyse Esperanto traduite en French !! L'analyse en French que l'on veut obtenir
+
! Esperanto analyzes !! Esperanto analyzes translated in French !! The analyzes in French of what we want to get
 
|-
 
|-
 
| ^la<det><def><sp>$ ^tago<n><sg><nom>$<br/>^la<det><def><sp>$ ^tago<n><sg><acc>$
 
| ^la<det><def><sp>$ ^tago<n><sg><nom>$<br/>^la<det><def><sp>$ ^tago<n><sg><acc>$
Line 243: Line 241:
 
|}
 
|}
   
On constate que :
+
We can note :
   
* 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.
+
* for the determinant, the lexical translation always gives ^le<det><def><sp>$ . It will be necessary to remplace the last tag <sp> (singular or plural) by tags used by the common noun giving its gender and number.
* pour le nom commun, la traduction lexicale a trouvé (dans le [[bilingual dictionary]]) le genre du nom traduit en French. Pour savoir si ce nom est au singulier ou au pluriel, elle a conservé l'attribut nombre de la language d'origine. Par contre, on a aussi conservé les attributs <nom> ou <acc> dont on n'a pas besoin en French et qui empêcheraient la generation du mot. Il faudra donc les supprimer dans la règle de transfer.
+
* for the common noun, the lexical translation found (in the [[bilingual dictionary]]) the gender of the noun translated to French. To know if this noun is singular or plural, it kept the number attribute of the original language. But the attribute <nom> or <acc> which is not needed in French was also kept and it can prevent to generate the word. So, this attribute will have to be removed by the transfer rule.
   
==== Écriture de la règle de transfer ====
+
==== Writing the transfer rule ====
   
Pour cette première règle, nous partons d'un fichier de suffixe <code>.t1x</code> "vide" ayant la structure décrite [[Examples de transfer rules#Structure d'un fichier .t1x|ici]].
+
For this first rule, we start from a "empty" file with <code>.t1x</code> suffix having the structure described [[Transfer rules examples#Structure of a .t1x file|here]].
   
La section '''def-macros''' étant facultative, comme elle n'est pas utilisée pour les premières transfer rules décrites dans cette page, nous ne la mettrons pas pour l'instant.
+
As the '''def-macros''' section is optional and not used for the first transfer rules described in this page, we will not put it for the present.
   
La section '''def-vars''' est obligatoire. Bien qu'elle ne sera jamais utilisée dans les examples de cette page, nous nous contenterons d'y mettre un contenu minimal pour que le fichier <code>.t1x</code> puisse être compilé :
+
The '''def-vars''' section is mandatory. Although it will never be used in the examples this page, we will just put a minimum content so that the file <code>.t1x</code> can be compiled:
   
 
<pre>
 
<pre>
Line 261: Line 259:
 
</section-def-vars>
 
</section-def-vars>
 
</pre>
 
</pre>
  +
 
''the following part will have to be translated later''
   
 
Les autres sections pourront contenir des informations utiles à notre première règle de transfer.
 
Les autres sections pourront contenir des informations utiles à notre première règle de transfer.
Line 319: Line 319:
   
 
* '''type_mot''' (peut être pas obligatoire, mais il n'y a pas de solution alternative documentée). Pour l'instant, les types disponibles sont :
 
* '''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)
+
** n (common noun)
 
** det (déterminant)
 
** det (déterminant)
 
:On en rajoutera plus tard lorsqu'on écrira d'autres règles.
 
:On en rajoutera plus tard lorsqu'on écrira d'autres règles.
Line 375: Line 375:
 
</pre>
 
</pre>
   
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.
+
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 common noun. 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 :
 
La partie la plus intéressante de la règle est à partir de la balise '''<action>'''. Elle a la structure suivante :
Line 438: Line 438:
 
| <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''.
 
| <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 target language, c'est à dire le genre du nom commun.
+
| <clip pos="2" side="tl" part="genre"/> || Récupérer le genre du deuxième mot du pattern de la target language, c'est à dire le genre du common noun.
 
|-
 
|-
| <clip pos="2" side="tl" part="nombre"/> || Récupérer le nombre du deuxième mot du pattern de la target language, c'est à dire le nombre du nom commun.
+
| <clip pos="2" side="tl" part="nombre"/> || Récupérer le nombre du deuxième mot du pattern de la target language, c'est à dire le nombre du common noun.
 
|-
 
|-
 
|}
 
|}
Line 446: Line 446:
 
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>'''
 
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).
+
Pour la deuxième unité lexicale correspondant à la traduction du common noun, on peut remarquer qu'on a dans chaque ligne : '''pos="2" side="tl"''' ce qui signifie qu'on recopiera simplement certaines balises du common noun (2ème mot de la règle).
   
 
Explication détaillée des 4 instructions :
 
Explication détaillée des 4 instructions :
Line 453: Line 453:
 
! width=280 | Instruction !! Signification
 
! width=280 | Instruction !! Signification
 
|-
 
|-
| <clip pos="2" side="tl" part="lem"/> || Récupérer le lemme du deuxième mot du pattern dans la target language (le nom commun en French).
+
| <clip pos="2" side="tl" part="lem"/> || Récupérer le lemme du deuxième mot du pattern dans la target language (le common noun en French).
 
|-
 
|-
 
| <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="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="genre"/> || Récupérer le genre du common noun.
 
|-
 
|-
| <clip pos="2" side="tl" part="nombre"/> || Récupérer le nombre du nom commun.
+
| <clip pos="2" side="tl" part="nombre"/> || Récupérer le nombre du common noun.
 
|-
 
|-
 
|}
 
|}
Line 468: Line 468:
   
 
{|class=wikitable
 
{|class=wikitable
! Analyse French !! Résultat generation !! Ce qu'il faudrait
+
! French analyzes !! Résultat generation !! Ce qu'il faudrait
 
|-
 
|-
 
| ^le<det><def><m><sg>$ ^jour<n><m><sg>$ || ~le jour || le jour
 
| ^le<det><def><m><sg>$ ^jour<n><m><sg>$ || ~le jour || le jour
Line 492: Line 492:
 
=== Rajouter un mot dans la target language ===
 
=== Rajouter un mot dans la target language ===
   
L'Esperanto 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 Esperanto devra donc être précédé de l'article indéfini '''un''', '''une''' ou '''des''' adéquat, si on le traduit en French.
+
L'Esperanto 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 common noun. Un common noun isolé écrit en Esperanto devra donc être précédé de l'article indéfini '''un''', '''une''' ou '''des''' adéquat, si on le traduit en French.
   
 
Notre deuxième règle va faire cette transformation.
 
Notre deuxième règle va faire cette transformation.
Line 501: Line 501:
   
 
{|class=wikitable
 
{|class=wikitable
! Analyse Esperanto !! Analyse Esperanto traduite en French !! L'analyse en French que l'on veut obtenir
+
! Esperanto analyzes !! Esperanto analyzes traduite en French !! L'analyse en French que l'on veut obtenir
 
|-
 
|-
 
| ^tago<n><sg><nom>$<br/>^tago<n><sg><acc>$
 
| ^tago<n><sg><nom>$<br/>^tago<n><sg><acc>$
Line 563: Line 563:
 
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.
 
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 source language à 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.
+
Comme dans le texte de la source language à transférer, il n'y a qu'un mot (le common noun 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 :
 
Les 4 instructions nécessaires pour générer l'analyse de l'article indéfini possèdent la signification suivante :
Line 574: Line 574:
 
| <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''.
 
| <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="genre"/> || Récupérer le genre du common noun.
 
|-
 
|-
| <clip pos="1" side="tl" part="nombre"/> || Récupérer le nombre du nom commun.
+
| <clip pos="1" side="tl" part="nombre"/> || Récupérer le nombre du common noun.
 
|-
 
|-
 
|}
 
|}
   
Les instructions pour générer la traduction en French du nom commun sont les mêmes que pour la règle précédent, à part que maintenant '''pos="1"'''.
+
Les instructions pour générer la traduction en French du common noun sont les mêmes que pour la règle précédent, à part que maintenant '''pos="1"'''.
   
 
=== Intervertir deux mots ===
 
=== Intervertir deux mots ===
Line 680: Line 680:
   
 
{|class=wikitable
 
{|class=wikitable
! Esperanto !! Analyse Esperanto !! Analyse Esperanto traduite || L'analyse qu'on voudrait !! French
+
! Esperanto !! Esperanto analyzes !! Esperanto analyzes traduite || L'analyse qu'on voudrait !! French
 
|-
 
|-
 
| mi kantas || ^prpers<prn><subj><p1><mf><sg>$<br/> ^kanti<vbtr_ntr><pres>$
 
| mi kantas || ^prpers<prn><subj><p1><mf><sg>$<br/> ^kanti<vbtr_ntr><pres>$

Revision as of 14:10, 19 April 2013

This page is intended to supplement the page A long introduction to transfer rules. Examples used are taken from apertium-eo-fr pair. It is (at the beginning of 2013) a released pair for translating French to Esperanto. But Esperanto → French translation direction had not been implemented by the initial developer. It is another developer, full beginner for writing transfer rules who chose to do that. The examples given are the first rules written to translate a group of one, two or three Esperanto words into a group of two or three French words.

This page is only about writing the file with the suffix .t1x with rules intended to be used by the tool apertium-transfer. Writing tags used for chunking in a 3-stage transfer is not approached there.

Different steps for a translation with apertium

Let start by making a list of the different operations done for a translation.

Operation Role Concerned languages
Deformatting Allows to mark zones of the source text not to be translated. For example, HTML tags must not be translated in another language, but only the text of the Web page. The same softwares are used for every language pairs. It is the format of the data to be translated which will take to use a particular deformatter.
Analysis Each word of the source text is decomposed into a lemma followed by the type of the word and its attributes (gender, number, person and time for a verb ...). For some words, several analyzes are possible. In this case, they all are sent on output. Valid for every languages, it uses the morphological dictionary of the source language.
Disambiguation When there are several analysis for a word, this step permits to keep only one. Valid for every languages, it uses a file with .prob suffix
For non ambiguous languages as Esperanto, this step stays necessary to take off the surface form of each analyzed word (pre-formatting for the transfer step).
Pre-transfer Processing multiwords before transfer step. All languages. Does not require a particular data file.
Transfer Transforms analyzes from the source language into their translated version in the target language. Valid for every languages, it uses the bilingual dictionary and the transfer file with .t1x suffix.
Interchunk processing Allows processing on groups of words (the subject, a complement ...)
As indicated above, we will not deal with this step (nor of the following).
Used a priori to make the transfer step more simple, it needs to add several tags during the transfer step. It uses a file with .t2x suffix and eventually other files if several pass of this kind are done.
Postchunk End of interchunk processing(s) Needed if one or more interchunk processing were done. It uses a file with .t3x suffix.
Generation Generate the surface forms of the target language words from the decomposition in lemma + attributes obtained from the previous steps. Valid for every languages, it uses the morphological dictionary of the target language.
Post-generation Allows spelling corrections between following words when particular cases are not processed by the generation. Used in a lot of target languages (including French), may be not for all.
Reformatting Put the translated data back to the format of the source document. The same software are used for every language pairs. There is a reformatter for each available deformatter even in every reformatter do a similar work.

The page Preparing to use apertium-transfer-tools gives an example about how a Spanish sentence is changed at every step of the process to lead finally to an English translation.

How to find what must be done

Basically, the transfer step starts from a disambiguated analysis of the source language text to provide an equivalent in the target language. The generation step then does the inverse processing as the analysis. It has a consequence : data given to generator must be exactly what a new analysis of the text translated in the target language would give. Otherwise, the generation will be only partial with some # appearing at the beginning of some words that will be written as lemmas.

Example :

We want to translate in French the 3 Esperanto words :

la aŭtomata traduko

After analysis and disambiguation, we get :

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

A lexical transfer step (using only the bilingual dictionary) will give :

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

The part of sentence we want to get in French is :

la traduction automatique

When analyzing this part of sentence, we get :

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

which is the text we must give to the generator to get the desired translation.

So, during the structural transfer step, we will have to do the following changes :

Origin :

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

Result :

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

For this, we write the transfer rules. Their goal is to add or remove several tags in words descriptions, and possibly to change the order of certain words.

Structure of a .t1x file

The file containing transfer rules has the suffix .t1x . This file is made of several mandatory sections and can also contain other optional sections. Each section will have to contain at least one element.

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

The def-cats section is mandatory. It allows to declare categories of word that we will fetch to apply a particular transfer rule. It can be simple words (a determinant, a noun, an adjective, a verb, ...) or a little more complicated things as a noun with in its description the tag <nom> (nominative) meaning it is part of the subject of the sentence.

This section contains one or more element with the following structure :

    <def-cat n="name_of_what_we_want_to_describe">
      <cat-item tags="its_description"/>
      .... (there can be one or more <cat-item .../> tags)
    </def-cat>

Section def-attrs

The def-attrs section is mandatory. It allows to put together by functionalities attribute names for words defined in the section sdefs of a morphological dictionary. For example, we will put together in this section every tag corresponding to the :

  • gender of a word
  • number of a word (singular, plural, ...)
  • person of a verb
  • time of a verb
  • ...

This section contains one or more element with the following structure :

    <def-attr n="name_of_a_list_of_attributes_with_a_common_rule">
      <attr-item tags="an_attribute_of_the_sdef_section_of_a_dictionary"/>
      .... (we have several tags <attr-item .../> as many as possible
            values for the attribute)
    </def-attr>

Section def-vars

The def-vars section is mandatory and must contain at least one element with the following syntax <def-var n="..."/> . It lists the global variables used in the transfer rules. However, for the rules described in this page, we will not need any of these variables.

Section def-macros

The def-macros section is optional. Nevertheless, it will be very useful to write shorter transfer files avoiding to duplicate identical (or almost) operations done in several transfer rules.

This section contains one or more element with the following structure :

    <def-macro n="name_of_the_macro" npar="number_of_parameters">
      .... (the code of the macro)
    </def-macro>

Section rules

Finally, the rules section is mandatory. It is the longest of the transfer file and the one that justifies its existence. It indeed makes it possible to define the operations to be performed to translate groups of words (or sometimes single words, as we will see).

This section contains one or more element with the following structure :

    <rule>
      <pattern>
        <pattern-item n="name_defined_in_def-cat_corresponding_to_the_first_word_to_process"/>
        .... (as many tags <pattern-item ..../> as words we want to process together)
      </pattern>
      <action>
        .... (description of the transfer rule)
      </action>
    </rule>

Examples of transfer rules

Transfering two words making them agree

We will start to translate to French the Esperanto determinant la followed buy a common noun.

Search for modifications

In Esperanto, the definite determinant la is invariant, while in French, it has three forms: le, la, les according to gender and number of the noun to witch it agrees.

For the common noun, there are two forms in Esperanto depending on it belongs to the subject or the object complement in the sentence. In French, it is written the same in both cases.

Examples :

Esperanto Esperanto analyzes French French analyzes
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>$

Let examine what the lexical translation of the Esperanto analysis gives and compare it to the analysis in French we wants to submit to the generator:

Esperanto analyzes Esperanto analyzes translated in French The analyzes in French of what we want to get
^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>$

We can note :

  • for the determinant, the lexical translation always gives ^le<det><def><sp>$ . It will be necessary to remplace the last tag <sp> (singular or plural) by tags used by the common noun giving its gender and number.
  • for the common noun, the lexical translation found (in the bilingual dictionary) the gender of the noun translated to French. To know if this noun is singular or plural, it kept the number attribute of the original language. But the attribute <nom> or <acc> which is not needed in French was also kept and it can prevent to generate the word. So, this attribute will have to be removed by the transfer rule.

Writing the transfer rule

For this first rule, we start from a "empty" file with .t1x suffix having the structure described here.

As the def-macros section is optional and not used for the first transfer rules described in this page, we will not put it for the present.

The def-vars section is mandatory. Although it will never be used in the examples this page, we will just put a minimum content so that the file .t1x can be compiled:

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

the following part will have to be translated later

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

Section def-cats

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

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 (common noun)
    • 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

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 common noun. 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>
            ... (generation de l'unité lexicale pour le premier mot)
          </lu>
          <b />
          <lu>
            ... (generation 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 generation de texte qui est indiquée par la balise <out>.

On devra générer l'analyse de 2 mots dans la target language. 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 target language. Pour accéder à la source language, 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 target language. Ce sera toujours l'article French "le".
<clip pos="1" side="tl" part="type_mot"/> Récupérer le type du premier mot du pattern dans la target language. 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 target language, c'est à dire le genre du common noun.
<clip pos="2" side="tl" part="nombre"/> Récupérer le nombre du deuxième mot du pattern de la target language, c'est à dire le nombre du common noun.

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 common noun, on peut remarquer qu'on a dans chaque ligne : pos="2" side="tl" ce qui signifie qu'on recopiera simplement certaines balises du common noun (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 target language (le common noun en French).
<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 common noun.
<clip pos="2" side="tl" part="nombre"/> Récupérer le nombre du common noun.
Remarque

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

French analyzes Résultat generation 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 generation mais juste après dans l'étape de post-generation qui s'occupe des mots marqués par une ~ . Cette remarque étant faite, la post-generation ne sera pas mentionnée dans cette page.

Rajouter un mot dans la target language

L'Esperanto 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 common noun. Un common noun isolé écrit en Esperanto devra donc être précédé de l'article indéfini un, une ou des adéquat, si on le traduit en French.

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

Examinons de que donne le transfer lexical of a word en Esperanto et comparons-le à ce qu'on voudrait obtenir en French.

Examinons ce que donne la traduction lexicale de l'analyse Esperanto et comparons-la à l'analyse en French que l'on veut soumettre au générateur :

Esperanto analyzes Esperanto analyzes traduite en French L'analyse en French 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 source language à transférer, il n'y a qu'un mot (le common noun 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 common noun.
<clip pos="1" side="tl" part="nombre"/> Récupérer le nombre du common noun.

Les instructions pour générer la traduction en French du common noun sont les mêmes que pour la règle précédent, à part que maintenant pos="1".

Intervertir deux mots

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

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

En French, 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 Esperanto comme en French. Nous allons nous limiter au cas le plus fréquent en réalisant une règle qui a partir d'une forme "la" + adjectif + nom en Esperanto, fournit une traduction du type "le/la/les" + nom + adjectif en French.

Rajout dans la section def-cats

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

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

    <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

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

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

De plus, certains pronoms personnel du French n'ont pas d'équivalent spécifique en Esperanto qui sur ce point est comme l'anglais :

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

pour passer de l'Esperanto au French, 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 French.

De même, l'Esperanto ne dispose que d'un temps pour le passé là où le French en a quatre. En plus, dans une analyse, les dictionnaires Esperanto et French 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.

Esperanto Esperanto analyzes Esperanto analyzes traduite L'analyse qu'on voudrait French
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 transfer

Rajouts dans la section def-cats

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 Esperanto plusieurs formes pour les verbes, on a mis plusieurs cat-item pour les énumérer toutes.

Rajouts dans la section def-attrs

En ce qui concerne les verbes, différents mots clés sont utilisés en Esperanto, alors qu'en French, 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

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

En Esperanto, il y a 3 temps pour l'indicatif :

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

En French, 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'Esperanto 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 example remplacer l'attribut past de l'Esperanto 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

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

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 transfers 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é source language
<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 vérifiée :

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é target language
<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 target language.

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 réalisée. 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 of a word, 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

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 Esperanto, 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 Esperanto et en French. Mais cette transformation va être le 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 transfer rules, ce sont des macros.

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

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 transfer rules précise que le .* lorsqu'il n'est pas placé à la fin signifie "une seule balise". C'est la cas pour les analyses de la plupart des noms Esperanto 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

Maintenant, nous allons mettre dans une macro les opérations nécessaires au transfer 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 transfer utilisant la macro

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 transfers 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 source language et la target language.

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 transfer rules n'offre 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.