Au cours de mon analyse de code j'ai essayé de comprendre certains résultats très bizarres comme cette traduction du token {.dl} devant le village Etirfurd dans la phrase "Les terres autour des Etirfurd sont possédées pour la plupart par Derthert, roi des Vlandais" qui s'affiche quand on arrive à un village, en l’occurrence ici au village d'Etirfurd.
Cette phrase provient de
std_TaleWorlds_CampaignSystem-fre.xml du module SandBox :
"Les terres autour {.d}{SETTLEMENT_LINK} sont possédées pour la plupart par {.l}{LORD.LINK}, {FACTION_OFFICIAL} {.dl}{FACTION_TERM}."
Pourquoi "des Etirfurd" alors qu'on attendrait plutôt "de" ou même "de l'" si Etirfurd est considéré comme non genré par le token {.dl}. Et d'autres exemples dans d'autres villages montrent aussi que souvent le token {.dl} devant {SETTLEMENT_LINK} est interprété avec un genre incohérent avec le contenu de la variable.
Je me suis lancé dans une longue session de debug grâce à dnSpy et
j'ai fini par trouver un bug dans une des routines appelées par ProcessToken. Pour faire court, c'est le genre de la dernière variable de la phrase qui reste actif, donc ici celui de "Vlandais" qui est tagué masculin et surtout pluriel : "{.M}{.P}Vlandais".
Le bug se trouve dans la routine ProcessLink qui recherche le genre et le nombre d'une variable "link" qui est mise en couleur dans les textes pour signifier qu'on peut cliquer dessus pour aller voir dans l'encyclopédie. Dans cette phrase il y a trois links, même si le troisième n'est pas évident dans le texte : {SETTLEMENT_LINK}, {LORD.LINK} et {FACTION_TERM}. Les trois links sont d'abord tous interprétés pour trouver leur contenu, puis la phrase entière est balayée une seconde fois pour traiter les tokens et une nouvelle fois les links sont interprétés (oui, il y a beaucoup de redondances dans le code).
ProcessLink contient ce code :
Code:
if (this._wordGroups.TryGetValue(key, out valueTuple))
{
this.SetGenderInfo(valueTuple.Item1);
if (valueTuple.Item3)
{
this.SetPlural();
}
}
...
return;
Traduction : Sachant que
key contient le nom exact remonté dans la variable, on cherche dans le dictionnaire
_wordGroups si ce mot possède un genre et un nombre (dictionnaire créé lors de la lecture des fichiers à chaque fois que des tokens de genre ont été trouvés).
Si oui, les deux valeurs sont renvoyées du dictionnaire via les champs
Item1 et
Item3 de
valueTuple : on appelle
SetGenderInfo qui donne à la variable globale
_curGender le genre du mot contenu dans
valueTuple.Items1 et si
Item3 est true alors la fonction
setPlural positionne la variable globale
_isPlural à true.
Si non... on ne fait rien.
Puis on termine la routine.
Donc là que se passe-t-il ? Quand la première passe sur la phrase interprète "Vlandais", elle donne aux deux variables globales
_curGender et
_isPlural les valeurs Masculin et Pluriel de "Vlandais", normal. Puis, dans la deuxième passe, lors de l'interprétation du premier token [.dl}, elle appelle à nouveau
ProcessLink pour "Etirfurd". Comme tous les noms de ville et de village, Etirfurd n'est pas genré, donc il n'est pas dans le dictionnaire
_wordGroups, donc
ProcessLink ne fait rien... et la variable
_isPlural reste à
true. En conséquence de quoi Etirfurd se voit affublé d'un "des" lors de l'interprétation de son {.dl}. CQFD !
Pour en avoir le cœur net, j'ai utilisé les fonctions d'édition de dnSpy et j'ai modifié le code de la façon suivante :
Code:
if (this._wordGroups.TryGetValue(key, out valueTuple))
{
this.SetGenderInfo(valueTuple.Item1);
if (valueTuple.Item3)
{
this.SetPlural();
}
}
else
{
this._curGender = FrenchTextProcessor.WordGenderEnum.NoDeclination;
this._isPlural = false;
}
Autrement dit, quand le mot n'est pas genré, j'initialise les deux variables globales à "pas de genre" et "pas pluriel".
Puis j'ai demandé à dnSpy de recompiler la dll , je suis allé la mettre dans le jeu à la place de l'originale, j'ai relancé le jeu, je suis allé à Etirfurd et il s'est affiché ceci : "Les terres autour de l'Etirfurd sont possédées...", ce qui l'interprétation correcte d'un mot au singulier commençant par une voyelle dans le code de traitement de {.dl}. Le bug est bien corrigé !
Bon, d'accord, l'article n'est toujours pas correct, mais là c'est parce que le token utilisé dans ce cas n'est pas le bon. Comme vous pouvez le voir dans mon document, le token {.dl} est fait pour générer un article du type "de la", "du" (de le), "des" (de les) ou "de l'". Donc ici il faut en réalité utiliser le token {.d}. J'ai bien entendu fait l'essai : j'ai mis {.d} à la place de {.dl}, j'ai relancé le jeu et cette fois la bonne syntaxe est enfin sortie : "Les terres autour d'Etirfurd sont possédées...".
Soit dit en passant, je soupçonne aussi un autre bug potentiel lié au pluriel. On voit que le code appelle setPlural si le
Item3 remonté indique le pluriel, mais dans le cas contraire on ne met pas la valeur "pas pluriel". Un pluriel pourrait donc rester actif même si le mot trouvé dans le dictionnaire indique qu'il ne l'est pas.
Il faut donc en fait mettre les deux lignes que j'ai ajoutées avant la recherche dans le dictionnaire
_wordGroups pour être certain que le résultat soit toujours correctement adapté au mot recherché :
Code:
this._curGender = FrenchTextProcessor.WordGenderEnum.NoDeclination;
this._isPlural = false;
if (this._wordGroups.TryGetValue(key, out valueTuple))
{
this.SetGenderInfo(valueTuple.Item1);
if (valueTuple.Item3)
{
this.SetPlural();
}
}
Soit :
Par défaut, mot non genré au singulier.
Si on le trouve dans le dictionnaire, on met son genre dans
_curGender et on passe
_isPlural à vrai si nécessaire.
J'ai posté un rapport de bug dans le forum de TaleWorlds :
https://forums.taleworlds.com/index.php?threads/bug-for-the-first-token-of-a-sentence.450327/
En attendant, moi je joue avec une dll corrigée ! Si certains sont intéressés pour la récupérer, contactez-moi.