Правильное использование арабских диакритиков в Amal: как работают Ташкил, Шадда и Хамза
Amal обрабатывает полную сложность арабских диакритиков: 8 знаков ташкил (фатха, дамма, касра, шадда, сукун, фатхан, дамматан, касратан), 4 варианта алефа (стандартный, мадда, хамза сверху, хамза снизу, васла), 3 варианта хамзы (изолированная, на вау, на йа) и лигатуры лям-алеф. Речевое распознавание, отображение текста и оценка сходства в приложении учитывают диакритизированный арабский («كَتَبَ») по-другому, чем без диакритиков («كتب») — важное различие, которое многие обучающие приложения игнорируют.
Почему диакритики важны для обучения
Проблема неоднозначности
Арабский без диакритиков неоднозначен:
- "كتب" может означать:
- "kataba" (он написал) — прошедшее время
- "kutub" (книги) — множественное число
- "kutiba" (это было написано) — страдательный залог
Все пишутся одинаково без диакритиков. Диакритики снимают неоднозначность.
Этапы обучения
- Начинающий: учится читать с диакритиками (легко — гласные отмечены)
- Средний: практикует чтение с диакритиками до автоматизма
- Продвинутый: постепенно убирает диакритики, чтение усложняется
- Свободное владение: читает без диакритиков свободно (на уровне носителя)
Большинство приложений для изучения арабского пропускают первый этап — они не учат диакритикам или удаляют их. Это формирует плохие привычки. Прогрессия Amal построена научно правильно.
Реализация на уровне Unicode
Диакритические знаки (всего 8):
// lib/src/utils/arabic_extension.dart
class ArabicExtension {
static const Map<String, String> tashkeelMarks = {
'FATHA': '\u064E', // َ (гласная 'a')
'DAMMA': '\u064F', // ُ (гласная 'u')
'KASRA': '\u0650', // ِ (гласная 'i')
'SUKUN': '\u0652', // ْ (без гласной)
'SHADDA': '\u0651', // ّ (удвоенная буква)
'FATHATAN': '\u064B', // ً (танвин 'ан')
'DAMMATAN': '\u064C', // ٌ (танвин 'ун')
'KASRATAN': '\u064D', // ٍ (танвин 'ин')
};
static const Map<String, String> alefVariants = {
'ALEF_STANDARD': 'ا', // ا
'ALEF_WITH_MADDA': 'آ', // آ (удлинённый)
'ALEF_WITH_HAMZA_ABOVE': 'أ', // أ
'ALEF_WITH_HAMZA_BELOW': 'إ', // إ
'ALEF_WASLA': 'ٰ', // ٰ (соединительный алеф)
};
static const Map<String, String> hamzaVariants = {
'HAMZA_ISOLATED': 'ء', // Изолированная хамза
'HAMZA_ON_WAW': 'ؤ', // Хамза на вау (و + хамза)
'HAMZA_ON_YEH': 'ئ', // Хамза на йа (ي + хамза)
};
}
Коранные диакритики и у-смятения (uthmani stops)
Для приложения Thurayya поддерживаются специальные знаки, используемые в Коране:
static const Map<String, String> quranicMarks = {
'STOP_FULL': 'ۖ', // Полная остановка (‖)
'STOP_HALF': 'ۗ', // Полупауза
'STOP_QUA': 'ۙ', // Qua-пауза
'STOP_NECESSARY': 'ۚ', // Обязательная пауза
'TAJWEED_ELONGATION': '', // Индикатор удлинения
};
Распознавание речи с учётом диакритиков
Контекстное смещение с диакритиками
Когда ребёнок учит «كَتَبَ» (он написал), система смещает распознавание речи в сторону именно этого произношения:
# src/services/stt_client.py
def recognize_with_diacritical_context(audio_bytes, expected_text):
# expected_text = "كَتَبَ" (с диакритиками)
# Создаём подсказку для распознавания
speech_context = {
'phrases': [expected_text],
'boost': 20.0 # Сильное смещение на ожидаемый текст
}
# Отправляем в Google Cloud STT
response = google_stt_client.recognize(
audio=audio_bytes,
language_code='ar-SA',
speech_contexts=[speech_context]
)
# Результат: Google STT ориентирован на произношение "kataba"
return response
Оценка сходства с учётом диакритиков
def compare_pronunciations(expected, actual):
"""
expected: "كَتَبَ" (с диакритиками)
actual: "كتب" (попытка ребёнка, возможно без диакритиков)
"""
# Убираем диакритики для грубого сравнения
expected_base = strip_diacritics(expected) # "كتب"
actual_base = strip_diacritics(actual) # "كتب"
# Базовое сходство (без учёта диакритиков)
base_similarity = string_similarity(expected_base, actual_base) # 1.0 (идеально)
# Бонус за правильные диакритики (если есть)
diacritic_bonus = 0.0
if has_diacritics(actual):
diacritic_accuracy = diacritics_match_ratio(expected, actual)
diacritic_bonus = diacritic_accuracy * 0.15 # До +15% за корректные диакритики
# Итоговый балл
final_score = min(base_similarity + diacritic_bonus, 1.0)
return {
'base_score': base_similarity,
'diacritic_bonus': diacritic_bonus,
'final_score': final_score,
'feedback': 'Отлично! Произношение идеальное. Далее практикуйте диакритики.'
}
Это значит:
- Ребёнок сказал "كتب" (без диакритиков) → 85-90% баллов (правильная база, отсутствуют диакритики)
- Ребёнок сказал "كَتَبَ" (полностью с диакритиками) → 98%+ баллов (идеально)
Проблемы отображения текста справа налево
Управление направлением текста
// lib/src/screens/lesson_screen.dart
Column(
children: [
Directionality(
textDirection: TextDirection.rtl, // Для арабского
child: Text(
'كَتَبَ',
textAlign: TextAlign.right, // Выравнивание вправо для RTL
style: TextStyle(
fontFamily: 'IBMPlexSansArabic',
fontSize: 36,
height: 1.8, // Увеличенная высота строк для диакритиков
),
),
),
// Инструкции ниже на английском
Directionality(
textDirection: TextDirection.ltr, // Для английского
child: Text(
'Pronounce: "he wrote"',
textAlign: TextAlign.left, // Выравнивание влево для LTR
),
),
],
)
Формы букв в зависимости от позиции
Арабские буквы меняют форму в зависимости от положения в слове:
- Изолированная: "ك" (Каф)
- Начальная: "كَـــ" (Каф в начале)
- Средняя: "ـــكَـــ" (Каф в середине)
- Конечная: "ـــكَ" (Каф в конце)
// Правильно: используется символ расширения (кашида)
String word = 'ك' + '\u0640' + 'ت' + '\u0640' + 'ب'; // Кашида
// Неправильно: простая конкатенация
String word = 'ك' + 'ت' + 'ب'; // Могут быть ошибки отображения
Смешение направлений текста
Когда английский и арабский идут вместе:
RichText(
textDirection: TextDirection.rtl, // Основное направление — справа налево
text: TextSpan(
children: [
TextSpan(text: 'means ', style: englishStyle), // Слева направо
TextSpan(text: 'كتاب', style: arabicStyle), // Справа налево
TextSpan(text: ' (book)', style: englishStyle), // Слева направо
],
),
)
Будет корректно отображено «means كتاب (book)» с правильным порядком и направлением.
Часто задаваемые вопросы
В: Зачем заставлять новичков использовать диакритики? Разве это не сложнее?
О: Да, сначала это сложнее. Но обучение с диакритиками укрепляет связь между буквами и звуками. Исследования показывают, что это ускоряет овладение языком. После освоения с диакритиками переход к чтению без них — естественный этап.
В: Что делать, если клавиатура ребёнка не поддерживает ввод диакритиков?
О: Приложение не требует от детей вводить диакритики вручную — распознавание и произношение основаны на речи. Только преподаватели и создатели контента вводят диакритики с помощью специализированных арабских клавиатур.
В: Поддерживает ли Amal нестандартные комбинации диакритиков?
О: Мы поддерживаем все стандартизированные Unicode варианты. Редкие или кастомные сочетания могут отображаться некорректно, но стандартный коранный и современный арабский полностью поддерживаются.



