Comment Amal gère les diacritiques arabes
6 min de lectureMohammad Shaker

Comment Amal gère les diacritiques arabes

Amal gère la complexité des diacritiques arabes avec 8 marques tathkeel, variantes alef, hamza et ligatures Lam-Alef.

Engineering

Réponse rapide

Amal gère la complexité des diacritiques arabes avec 8 marques tathkeel, variantes alef, hamza et ligatures Lam-Alef.

Amal traite toute la complexité des diacritiques arabes : 8 marques tashkeel (fatha, damma, kasra, shadda, sukun, fathatan, dammatan, kasratan), 4 variantes d'alef (standard, madda, hamza au-dessus, hamza en-dessous, wasla), 3 variantes de hamza (isolée, sur waw, sur ya) et les ligatures Lam-Alef. La reconnaissance vocale de l'application, le rendu du texte et le scoring de similarité traitent tous l'arabe diacritisé ("كَتَبَ") différemment de l'arabe non diacritisé ("كتب") — une distinction cruciale ignorée par la plupart des applications d'apprentissage de l'arabe.

Importance des diacritiques pour l'apprentissage

Le problème de l'ambiguïté

L'arabe sans diacritiques est ambigu :

  • "كتب" peut signifier :
    • "kataba" (il a écrit) — passé
    • "kutub" (livres) — nom pluriel
    • "kutiba" (il a été écrit) — voix passive

Tout est orthographié identiquement sans diacritiques. Les diacritiques lèvent l'ambiguïté.

La progression de l'apprentissage

  • Débutant : Apprendre à lire AVEC diacritiques (facile — voyelles marquées)
  • Intermédiaire : S'entraîner AVEC diacritiques jusqu'à automatisation
  • Avancé : Retirer peu à peu les diacritiques, lecture devient plus difficile
  • Fluent : Lire sans diacritiques couramment (niveau natif)

La plupart des applications d'apprentissage de l'arabe ignorent l'étape 1 — elles n'enseignent pas les diacritiques du tout, ou les suppriment. Cela engendre de mauvaises habitudes. La progression d'Amal est scientifiquement correcte.

Notre implémentation au niveau Unicode

Les marques diacritiques (8 au total)

// lib/src/utils/arabic_extension.dart
class ArabicExtension {
  static const Map tashkeelMarks = {
    'FATHA': '\u064E',      // َ (voyelle 'a')
    'DAMMA': '\u064F',      // ُ (voyelle 'u')
    'KASRA': '\u0650',      // ِ (voyelle 'i')
    'SUKUN': '\u0652',      // ْ (pas de voyelle)
    'SHADDA': '\u0651',     // ّ (lettre doublée)
    'FATHATAN': '\u064B',   // ً (tanween 'an')
    'DAMMATAN': '\u064C',   // ٌ (tanween 'un')
    'KASRATAN': '\u064D',   // ٍ (tanween 'in')
  };

  static const Map alefVariants = {
    'ALEF_STANDARD': 'ا',      // ا
    'ALEF_WITH_MADDA': 'آ',    // آ (allongé)
    'ALEF_WITH_HAMZA_ABOVE': 'أ', // أ
    'ALEF_WITH_HAMZA_BELOW': 'إ', // إ
    'ALEF_WASLA': 'ٰ',         // ٰ (alef de connexion)
  };

  static const Map hamzaVariants = {
    'HAMZA_ISOLATED': 'ء',  // Hamza seul
    'HAMZA_ON_WAW': 'ؤ',    // Hamza sur waw (و + hamza)
    'HAMZA_ON_YEH': 'ئ',    // Hamza sur yeh (ي + hamza)
  };
}

Diacritiques coraniques et arrêts Uthmani

Pour Thurayya, nous prenons en charge des marques spécifiques au Coran :

static const Map quranicMarks = {
  'STOP_FULL': 'ۖ',         // Arrêt complet (‖)
  'STOP_HALF': 'ۗ',         // Demi-arrêt
  'STOP_QUA': 'ۙ',          // Arrêt Qua
  'STOP_NECESSARY': 'ۚ',     // Arrêt nécessaire
  'TAJWEED_ELONGATION': '۝', // Indicateur d'allongement
};

Reconnaissance vocale sensible aux diacritiques

Biais contextuel avec diacritiques

Lorsqu'un enfant apprend "كَتَبَ" (il a écrit, temps passé), nous biaisons la reconnaissance vocale vers cette vocalisation exacte :

# src/services/stt_client.py
def recognize_with_diacritical_context(audio_bytes, expected_text):
    # expected_text = "كَتَبَ" (avec diacritiques)
    
    # Créer un indice de contexte vocal
    speech_context = {
        'phrases': [expected_text],
        'boost': 20.0  # Fort boost pour texte attendu
    }
    
    # Envoyer à Google Cloud STT
    response = google_stt_client.recognize(
        audio=audio_bytes,
        language_code='ar-SA',
        speech_contexts=[speech_context]
    )
    
    # Résultat : Google STT est biaisé vers la prononciation "kataba"
    return response

Scoring de similarité sensible aux diacritiques

Le scoring de similarité distingue le diacritisé du non-diacritisé :

def compare_pronunciations(expected, actual):
    """
    expected: "كَتَبَ" (avec diacritiques)
    actual: "كتب" (tentative de l'enfant, éventuellement non diacritisée)
    """
    
    # Supprimer les diacritiques pour une comparaison grossière
    expected_base = strip_diacritics(expected)  # "كتب"
    actual_base = strip_diacritics(actual)      # "كتب"
    
    # Similarité de base (ignorant les diacritiques)
    base_similarity = string_similarity(expected_base, actual_base)  # 1.0 (parfait)
    
    # Bonus diacritique (si la tentative de l'enfant inclut des diacritiques)
    diacritic_bonus = 0.0
    if has_diacritics(actual):
        diacritic_accuracy = diacritics_match_ratio(expected, actual)
        diacritic_bonus = diacritic_accuracy * 0.15  # Jusqu'à +15% pour diacritiques corrects
    
    # Score final
    final_score = min(base_similarity + diacritic_bonus, 1.0)
    
    return {
        'base_score': base_similarity,
        'diacritic_bonus': diacritic_bonus,
        'final_score': final_score,
        'feedback': 'Super ! La prononciation est parfaite. Ensuite, pratiquez les marques diacritiques.'
    }

Cela signifie :

  • L'enfant dit "كتب" (non diacritisé) → score 85-90% (base correcte, diacritiques manquants)
  • L'enfant dit "كَتَبَ" (entièrement diacritisé) → score 98%+ (parfait)
  • La progression est claire : maîtriser d'abord la prononciation de base, puis ajouter la subtilité diacritique

Défis d'affichage RTL

Gestion de la direction du texte

// lib/src/screens/lesson_screen.dart
Column(
  children: [
    Directionality(
      textDirection: TextDirection.rtl,  // Pour texte arabe
      child: Text(
        'كَتَبَ',
        textAlign: TextAlign.right,      // Aligné à droite pour RTL
        style: TextStyle(
          fontFamily: 'IBMPlexSansArabic',
          fontSize: 36,
          height: 1.8,  // Hauteur de ligne supplémentaire pour diacritiques
        ),
      ),
    ),
    // Instructions en anglais ci-dessous
    Directionality(
      textDirection: TextDirection.ltr,  // Pour anglais
      child: Text(
        'Pronounce: "he wrote"',
        textAlign: TextAlign.left,       // Aligné à gauche pour LTR
      ),
    ),
  ],
)

Façonnage des lettres connectées

Les lettres arabes changent de forme selon la position :

  • Isolée : "ك" (Kaf)
  • Initiale : "كَـــ" (Kaf au début du mot)
  • Médiane : "ـــكَـــ" (Kaf au milieu)
  • Finale : "ـــكَ" (Kaf à la fin)

La police IBMPlexSansArabic gère la formation automatiquement, mais nous avons besoin de séquences Unicode correctes :

// Correct : Utilise caractères de jonction Unicode
String word = 'ك' + '\u0640' + 'ت' + '\u0640' + 'ب';  // Kashida (caractère d'extension)

// Incorrect : Concaténation directe
String word = 'ك' + 'ت' + 'ب';  // Peut ne pas se former correctement sur tous les appareils

Mélange de texte bidirectionnel

Lorsque l'anglais et l'arabe apparaissent ensemble :

RichText(
  textDirection: TextDirection.rtl,  // Globalement RTL
  text: TextSpan(
    children: [
      TextSpan(text: 'means ', style: englishStyle),  // LTR
      TextSpan(text: 'كتاب', style: arabicStyle),    // RTL
      TextSpan(text: ' (book)', style: englishStyle), // LTR
    ],
  ),
)

Résultat : "means كتاب (book)" affiché avec flux bidirectionnel correct.

FAQ

Q : Pourquoi imposer les diacritiques aux débutants ? Cela ne rend-il pas l'apprentissage plus difficile ?
A : Initialement, oui. Mais apprendre avec diacritiques crée des associations son-lettre plus fortes. La recherche montre que l'apprentissage avec diacritiques produit une lecture fluide plus rapidement. Après la maîtrise avec diacritiques, lire sans eux devient une progression naturelle.

Q : Que faire si le clavier de mon enfant ne permet pas de taper des diacritiques ?
A : L'application ne demande jamais aux enfants de taper des diacritiques. La reconnaissance et la prononciation sont basées sur la voix. Seuls les adultes (enseignants, créateurs de contenu) doivent saisir des diacritiques, et ils utilisent des claviers spécialisés en arabe.

Q : Amal prend-il en charge les combinaisons diacritiques non standard ?
A : Nous prenons en charge toutes les combinaisons normalisées Unicode. Les combinaisons rares ou personnalisées peuvent ne pas s'afficher correctement, mais l'arabe coranique et moderne standard sont entièrement pris en charge.

Articles connexes