confluent/ConfluentTranslator/radicalMatcher.js
StillHammer 889cd24319 Amélioration système de traduction: normalisation, lexique et couverture
Corrections majeures:
- Normalisation ligatures (œ→oe, æ→ae) pour éviter fragmentation tokens
- Normalisation complète lexique (clés + synonymes) sans accents
- Correction faux positif "dansent"→"dans" (longueur radical ≥5)

Enrichissement lexique (+212 entrées):
- Verbes: battre (pulum), penser/réfléchir (umis), voler (aliuk)
- Mots grammaticaux: nous (tanu), possessifs (sa/mon→na), démonstratifs (ce→ko)
- Temporels: hier/avant (at), demain/après (ok), autour (no)
- Formes conjuguées ajoutées pour manger, battre, penser

Améliorations techniques:
- Lemmatisation verbale améliorée (radical ≥5 lettres)
- Système normalizeText() dans lexiqueLoader.js
- Liaisons sacrées pour compositions culturelles

Note: Problème connu de lemmatisation à investiguer (formes fléchies non trouvées)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 22:37:31 +08:00

161 lines
4.9 KiB
JavaScript

// radicalMatcher.js
// Système de recherche par radicaux pour le traducteur Confluent→Français
// Permet de trouver les formes conjuguées et dérivées à partir des racines
const lexique = require('../data/lexique.json');
// ============================================================================
// CHARGEMENT DYNAMIQUE DES SUFFIXES DEPUIS LE LEXIQUE
// ============================================================================
/**
* Extrait tous les conjugateurs depuis le lexique JSON
* @returns {Array<string>} Liste des conjugateurs (u, at, ok, ul, etc.)
*/
function getConjugateurs() {
const conjugateurs = [];
if (lexique.conjugateurs) {
// Temps : u, at, aan, ait, amat, en
if (lexique.conjugateurs.temps) {
conjugateurs.push(...Object.keys(lexique.conjugateurs.temps));
}
// Aspects : il, eol, eon, eom
if (lexique.conjugateurs.aspects) {
conjugateurs.push(...Object.keys(lexique.conjugateurs.aspects));
}
// Modes : ok, es, ul
if (lexique.conjugateurs.modes) {
conjugateurs.push(...Object.keys(lexique.conjugateurs.modes));
}
// Évidentiel : uv
if (lexique.conjugateurs.evidentiel) {
conjugateurs.push(...Object.keys(lexique.conjugateurs.evidentiel));
}
}
return conjugateurs;
}
/**
* Extrait les suffixes d'infinitif depuis la liste des verbes
* Analyse les patterns : racine "mira" → verbe "mirak" = suffixe "k"
* @returns {Array<string>} Liste des suffixes d'infinitif (k, s, n, m, etc.)
*/
function getInfinitifSuffixes() {
const suffixes = new Set();
if (lexique.verbes) {
for (const verbe of lexique.verbes) {
if (verbe.infinitif && verbe.racine) {
// Extraire le suffixe : infinitif - racine
// Ex: "mirak" - "mira" = "k"
if (verbe.infinitif.startsWith(verbe.racine)) {
const suffix = verbe.infinitif.slice(verbe.racine.length);
if (suffix.length > 0) {
suffixes.add(suffix);
}
}
}
}
}
// Aussi chercher dans les racines avec propriété "verbe"
if (lexique.racines && lexique.racines.standards) {
for (const categorie of Object.values(lexique.racines.standards)) {
if (Array.isArray(categorie)) {
for (const racine of categorie) {
if (racine.verbe && racine.forme_base) {
// Ex: forme_base "mira" → verbe "mirak" = suffixe "k"
if (racine.verbe.startsWith(racine.forme_base)) {
const suffix = racine.verbe.slice(racine.forme_base.length);
if (suffix.length > 0) {
suffixes.add(suffix);
}
}
}
}
}
}
}
return Array.from(suffixes);
}
// Charger les suffixes depuis le lexique
const CONJUGATEURS = getConjugateurs();
const INFINITIF_SUFFIXES = getInfinitifSuffixes();
// Tous les suffixes verbaux = conjugateurs + suffixes d'infinitif
const VERBAL_SUFFIXES = [...CONJUGATEURS, ...INFINITIF_SUFFIXES];
console.log('[radicalMatcher] Chargé depuis lexique.json:');
console.log(` - ${CONJUGATEURS.length} conjugateurs:`, CONJUGATEURS.join(', '));
console.log(` - ${INFINITIF_SUFFIXES.length} suffixes d'infinitif:`, INFINITIF_SUFFIXES.join(', '));
console.log(` - ${VERBAL_SUFFIXES.length} suffixes verbaux totaux`);
// ============================================================================
// EXTRACTION DES RADICAUX
// ============================================================================
/**
* Extrait tous les radicaux possibles d'un mot
* @param {string} word - Mot en confluent
* @returns {Array<{radical: string, suffix: string, type: string, confidence: number}>}
*/
function extractRadicals(word) {
const candidates = [];
// 1. Essayer chaque suffixe verbal connu (conjugateurs + infinitifs)
for (const suffix of VERBAL_SUFFIXES) {
if (word.endsWith(suffix) && word.length > suffix.length + 1) {
const radical = word.slice(0, -suffix.length);
// Différencier conjugateurs et infinitifs pour la confiance
const isConjugateur = CONJUGATEURS.includes(suffix);
const type = isConjugateur ? 'conjugaison' : 'infinitif';
candidates.push({
radical,
suffix,
type,
confidence: isConjugateur ? 0.95 : 0.9
});
}
}
// 2. Essayer sans suffixe (forme racine directe)
if (word.length >= 3) {
candidates.push({
radical: word,
suffix: '',
type: 'root',
confidence: 0.7
});
}
// 3. Essayer d'enlever dernière voyelle (forme liée -> forme pleine)
// Ex: mako → mak, voki → vok
if (word.length >= 4 && 'aeiou'.includes(word[word.length - 1])) {
candidates.push({
radical: word.slice(0, -1),
suffix: word[word.length - 1],
type: 'liaison',
confidence: 0.8
});
}
// Trier par confiance décroissante
return candidates.sort((a, b) => b.confidence - a.confidence);
}
module.exports = {
extractRadicals,
VERBAL_SUFFIXES,
CONJUGATEURS,
INFINITIF_SUFFIXES
};