Arabische Diakritika: Amal meistert Tashkeel & Co.
Amal bewältigt die vollständige Komplexität arabischer Diakritika: 8 Tashkeel-Zeichen (Fatha, Damma, Kasra, Shadda, Sukun, Fathatan, Dammatan, Kasratan), 4 Alef-Varianten (Standard, Madda, Hamza oben, Hamza unten, Wasla), 3 Hamza-Varianten (isoliert, auf Waw, auf Ya) und Lam-Alef-Ligaturen. Die App unterscheidet bei Spracherkennung, Textrendering und Ähnlichkeitsbewertung diakritisierte arabische Schrift ("كَتَبَ") von undiakritisierter arabischer Schrift ("كتب")—ein entscheidender Unterschied, den die meisten arabischen Lern-Apps ignorieren.
Warum Diakritika beim Lernen wichtig sind
Das Ambiguitätsproblem
Arabisch ohne Diakritika ist mehrdeutig:
- "كتب" kann bedeuten:
- "kataba" (er schrieb) — Vergangenheit
- "kutub" (Bücher) — Plural
- "kutiba" (es wurde geschrieben) — Passiv
Alle sind ohne Diakritika gleich geschrieben. Diakritika beseitigen diese Mehrdeutigkeit.
Der Lernprozess
- Anfänger: Mit Diakritika lesen lernen (einfach—Vokale sind markiert)
- Fortgeschrittene Anfänger: Mit Diakritika üben, bis es automatisiert wird
- Fortgeschrittene: Diakritika schrittweise entfernen, das Lesen wird schwieriger
- Flüssig: Ohne Diakritika flüssig lesen (lesen auf Muttersprachenniveau)
Die meisten arabischen Lern-Apps überspringen Schritt 1 — sie lehren überhaupt keine Diakritika oder entfernen sie. Das führt zu schlechten Angewohnheiten. Amals Progression ist wissenschaftlich korrekt.
Unsere Umsetzung auf Unicode-Ebene
Die Diakritischen Zeichen (insgesamt 8)
// lib/src/utils/arabic_extension.dart
class ArabicExtension {
static const Map<String, String> tashkeelMarks = {
'FATHA': '\u064E', // َ (Vokal 'a')
'DAMMA': '\u064F', // ُ (Vokal 'u')
'KASRA': '\u0650', // ِ (Vokal 'i')
'SUKUN': '\u0652', // ْ (kein Vokal)
'SHADDA': '\u0651', // ّ (doppelter Buchstabe)
'FATHATAN': '\u064B', // ً (Tanween 'an')
'DAMMATAN': '\u064C', // ٌ (Tanween 'un')
'KASRATAN': '\u064D', // ٍ (Tanween 'in')
};
static const Map<String, String> alefVariants = {
'ALEF_STANDARD': 'ا', // ا
'ALEF_WITH_MADDA': 'آ', // آ (verlängert)
'ALEF_WITH_HAMZA_ABOVE': 'أ', // أ
'ALEF_WITH_HAMZA_BELOW': 'إ', // إ
'ALEF_WASLA': 'ٰ', // ٰ (verbundenes Alef)
};
static const Map<String, String> hamzaVariants = {
'HAMZA_ISOLATED': 'ء', // Isoliertes Hamza
'HAMZA_ON_WAW': 'ؤ', // Hamza auf Waw (و + Hamza)
'HAMZA_ON_YEH': 'ئ', // Hamza auf Yeh (ي + Hamza)
};
}
Koranische Diakritika und Uthmani-Trennzeichen
Für Thurayya unterstützen wir koranspezifische Zeichen:
static const Map<String, String> quranicMarks = {
'STOP_FULL': 'ۖ', // Vollständiger Stopp (‖)
'STOP_HALF': 'ۗ', // Halber Stopp
'STOP_QUA': 'ۙ', // Qua-Stopp
'STOP_NECESSARY': 'ۚ', // Notwendiger Stopp
'TAJWEED_ELONGATION': '', // Verlängerungsanzeige
};
Diakritika-sensible Spracherkennung
Kontextbasierte Vorspannung mit Diakritika
Wenn ein Kind "كَتَبَ" (er schrieb, Vergangenheit) lernt, wird die Spracherkennung auf genau diese Aussprache ausgerichtet:
# src/services/stt_client.py
def recognize_with_diacritical_context(audio_bytes, expected_text):
# expected_text = "كَتَبَ" (mit Diakritika)
# Erstelle Sprechkontext-Hinweis
speech_context = {
'phrases': [expected_text],
'boost': 20.0 # Hohe Verstärkung für den erwarteten Text
}
# Senden an Google Cloud STT
response = google_stt_client.recognize(
audio=audio_bytes,
language_code='ar-SA',
speech_contexts=[speech_context]
)
# Ergebnis: Google STT ist auf "kataba"-Aussprache ausgerichtet
return response
Diakritika-bewusste Ähnlichkeitsbewertung
Ähnlichkeitsbewertung unterscheidet diakritisierte von undiakritisierter Schrift:
def compare_pronunciations(expected, actual):
"""
expected: "كَتَبَ" (mit Diakritika)
actual: "كتب" (Kinderversuch, möglicherweise undiakritisiert)
"""
# Diakritika für groben Vergleich abstreifen
expected_base = strip_diacritics(expected) # "كتب"
actual_base = strip_diacritics(actual) # "كتب"
# Grundähnlichkeit (ohne Berücksichtigung von Diakritika)
base_similarity = string_similarity(expected_base, actual_base) # 1.0 (perfekt)
# Diakritika-Bonus (wenn Kinderversuch Diakritika enthält)
diacritic_bonus = 0.0
if has_diacritics(actual):
diacritic_accuracy = diacritics_match_ratio(expected, actual)
diacritic_bonus = diacritic_accuracy * 0.15 # Bis zu +15% für korrekte Diakritika
# Endpunktzahl
final_score = min(base_similarity + diacritic_bonus, 1.0)
return {
'base_score': base_similarity,
'diacritic_bonus': diacritic_bonus,
'final_score': final_score,
'feedback': 'Super! Aussprache ist perfekt. Übe als nächstes die Diakritika.'
}
Das bedeutet:
- Kind sagt "كتب" (undiakritisiert) → 85-90 % Wertung (korrekte Basis, Diakritika fehlen)
- Kind sagt "كَتَبَ" (voll diakritisiert) → 98%+ Wertung (perfekt)
- Der Fortschritt ist klar: zuerst Basis-Aussprache meistern, dann diakritische Feinheiten hinzufügen
Herausforderungen des RTL-Renderings
Verwaltung der Textausrichtung
// lib/src/screens/lesson_screen.dart
Column(
children: [
Directionality(
textDirection: TextDirection.rtl, // Für arabischen Text
child: Text(
'كَتَبَ',
textAlign: TextAlign.right, // Rechtsbündig für RTL
style: TextStyle(
fontFamily: 'IBMPlexSansArabic',
fontSize: 36,
height: 1.8, // Zusätzliche Zeilenhöhe für Diakritika
),
),
),
// Englische Anweisungen darunter
Directionality(
textDirection: TextDirection.ltr, // Für Englisch
child: Text(
'Pronounce: "he wrote"',
textAlign: TextAlign.left, // Linksbündig für LTR
),
),
],
)
Verbundenes Buchstabenformen
Arabische Buchstaben ändern Form je nach Position:
- Isoliert: "ك" (Kaf)
- Initial: "كَـــ" (Kaf am Wortanfang)
- Medial: "ـــكَـــ" (Kaf in der Mitte)
- Final: "ـــكَ" (Kaf am Ende)
Die Schriftart IBMPlexSansArabic erledigt das Formen automatisch, aber wir benötigen korrekte Unicode-Folgen:
// Richtig: Verwendet Unicode-Verbindungszeichen
String word = 'ك' + '\u0640' + 'ت' + '\u0640' + 'ب'; // Kashida (Erweiterung Zeichen)
// Falsch: Direkte Verkettung
String word = 'ك' + 'ت' + 'ب'; // Möglicherweise nicht korrekt auf allen Geräten geformt
Bidirektionale Textmischung
Wenn Englisch und Arabisch zusammen vorkommen:
RichText(
textDirection: TextDirection.rtl, // Insgesamt RTL
text: TextSpan(
children: [
TextSpan(text: 'means ', style: englishStyle), // LTR
TextSpan(text: 'كتاب', style: arabicStyle), // RTL
TextSpan(text: ' (book)', style: englishStyle), // LTR
],
),
)
Ergebnis: "means كتاب (book)" wird mit korrekter bidirektionaler Flussrichtung angezeigt.
FAQ
F: Warum zwingt man Anfängern Diakritika auf? Macht das nicht alles schwieriger? A: Anfänglich ja. Aber das Lernen mit Diakritika schafft stärkere Buchstaben-Klang-Verbindungen. Studien zeigen, dass das diakritische Lernen eine schnellere Flüssigkeit erzeugt. Nach der Beherrschung der Diakritika ist das Lesen ohne sie ein natürlicher Fortschritt.
F: Was, wenn die Tastatur meines Kindes keine Diakritika unterstützt? A: Die App verlangt nie von Kindern, Diakritika zu tippen. Erkennung und Aussprache basieren auf Sprache. Nur Erwachsene (Lehrer, Inhaltsersteller) müssen Diakritika eingeben und verwenden spezielle arabische Tastaturen.
F: Unterstützt Amal nicht-standardisierte diakritische Kombinationen? A: Wir unterstützen alle Unicode-standardisierten Kombinationen. Seltene oder benutzerdefinierte Kombinationen werden möglicherweise nicht korrekt angezeigt, aber standardisiertes Koran-Arabisch und modernes Arabisch sind vollständig unterstützt.



