3amia · AI — C'est quoi ?

3amia · AI est un dictionnaire collaboratif des dialectes arabes, enrichi par l'intelligence artificielle. Chaque mot est documenté avec exemples, schèmes et traductions — grâce à la communauté et à l'IA.

3 770

mots

9

dialectes

0

contributions

3amia · AI doit son nom à deux racines arabes : زاد (zaada, «augmenter», «enrichir») et نا (na, «nous»). Littéralement : « Enrichissons ensemble ».

La 3amiya (l'arabe dialectal) est la langue du quotidien pour plus de 400 millions de personnes. Pourtant, elle est rarement documentée de façon structurée. Ce projet cherche à changer ça, un mot à la fois.

Chaque mot peut être accompagné d'une traduction française, d'un exemple d'utilisation, de ses variantes morphologiques et de ses équivalents dans d'autres dialectes.

Chaque contribution est analysée et enrichie automatiquement par l'intelligence artificielle — schème, exemple, traduction, type grammatical — pour garantir la qualité et la richesse de chaque fiche.

Pourquoi ce dictionnaire ?

Plus de 400 millions de personnes parlent l'arabe dialectal au quotidien : tunisien, marocain, algérien, égyptien, levantin… Pourtant, aucune ressource structurée n'existait pour documenter ces langues vivantes de façon ouverte et collaborative.

L'arabe classique (MSA) est bien documenté, mais personne ne l'utilise à la maison. Les dialectes, eux, évoluent, se mélangent, s'inventent — et disparaissent si on ne les note pas. Ce projet est une tentative de changer ça, un mot à la fois.

Ajouter un mot en 30 secondes

  1. 1

    Ouvre le formulaire

    Va sur /ajouter — pas besoin de compte ni d'inscription.

  2. 2

    Remplis les champs

    Le mot en arabe, sa traduction française, le dialecte. Un exemple d'usage si tu l'as.

  3. 3

    Envoie

    La contribution est examinée par l'équipe et publiée sous 24–48h.

Ce que fait (et ne fait pas) l'IA

À chaque contribution, Gemini 2.5 Flash analyse automatiquement le mot soumis. Il propose un schème morphologique et une racine consonantique, les deux piliers de la grammaire arabe.

L'IA ne publie rien toute seule. Ses suggestions arrivent dans l'interface d'administration, où un humain les valide, les corrige si besoin, et décide de la publication. L'IA complète, l'humain valide.

De la soumission à la publication

01

Détection des doublons

La contribution est comparée aux mots déjà en base — insensible aux diacritiques arabes.

02

Vérification de la translittération

Le système Maghreb chiffré (3=ع, 7=ح, 9=ق…) est validé automatiquement.

03

Analyse morphologique IA

Gemini propose le schème et la racine. L'admin les valide ou les corrige.

04

Publication

Une fois validé, le mot est publié et visible dans le dictionnaire sous 24–48h.

Recherche par racine consonantique

Explore la famille morphologique complète d'un mot.

Module QCM

Teste ton vocabulaire dialectal avec des quiz thématiques.

Expansion des dialectes

Algérien, marocain, égyptien… enrichissement en cours.

Audio & prononciation

Enregistrements natifs pour chaque mot.

Application mobile

Accès hors-ligne et notification "mot du jour".

Voir tout l'historique →
v1.25.0Juillet 2026
  • scripts/scan_drive_import.py — pipeline d'import des ~600 captures Derja.Ninja depuis Google Drive vers staging_scan_words.
v1.24.5Juillet 2026
  • Build résilient aux pannes Supabase — une base indisponible (402, 500, réseau, timeout) ne bloque plus le déploiement Vercel. Mécanisme : .catch() gated sur process.env.NEXT_PHASE === 'phase-production-build' — au build, retourne un tableau vide valide + console.warn('[BUILD FALLBACK] ...') ; au runtime ISR, re-throw pour que Next.js serve la page stale mise en cache (comportement inchangé).
  • src/app/page.tsx — helper withBuildFallback<T>() local appliqué à getAllWords() et getRecentPublishedArticles(3) ; homepage s'affiche vide au build si Supabase est down, plutôt que de crasher.
  • src/app/sitemap.ts — même pattern inliné sur getAllWords() ; sitemap réduit au lieu d'une erreur de build.
  • Test validé : build avec NEXT_PUBLIC_SUPABASE_URL=https://fake.supabase.co (fetch réseau impossible) → 41 pages générées, 2 lignes [BUILD FALLBACK], build vert.
v1.24.4Juillet 2026
  • Fix egress Supabase (~95% de réduction) — getAllWords() faisait un select('*') sur les tables dialect_forms et words (3 200+ lignes, toutes colonnes) à chaque render de /mot/[slug] et /articles/[slug], sans aucun cache — cause des 15 GB d'egress (305% du quota).
  • getAllWordLinks() (nouveau, db.ts) — remplace getAllWords() dans les contextes d'auto-linking : ne sélectionne que slug, form_ar, dialect (dialect_forms) + slug, word_ar (words), wrappé par unstable_cache(['autolink-word-index'], { revalidate: 86400 }) → 1 seule requête DB par 24h partagée entre toutes les pages.
  • getRelatedWords(dialectCode, excludeId) (nouveau, db.ts) — requête ciblée (3 mots max, même dialecte, colonnes minimales) pour la section "Autres mots" sur /mot/[slug], qui lisait auparavant toute la table pour filtrer en mémoire.
  • /mot/[slug]/page.tsx — getAllWords() → getAllWordLinks() (wordLinks) + getRelatedWords() (related). La section "Autres mots" conserve son comportement ; LinkedExamplePhrase reçoit le même tableau WordLink[].
  • /articles/[slug]/page.tsx — getAllWords() → getAllWordLinks(). Seul w.slug était utilisé (slugArray) — aucun impact fonctionnel.
  • getAllWords() conservé intact pour la homepage (1 page, ISR 1h) et le sitemap.
v1.24.3Juillet 2026
  • Rate limit desserré sur /api/submit + bypass admin — src/lib/rateLimit.ts : MAX_REQUESTS relevé de 5 → 30 soumissions par heure par IP. src/app/api/submit/route.ts : si la requête porte un header Authorization: Bearer {ADMIN_SECRET}, le rate limit est court-circuité avant tout comptage — un admin peut soumettre sans restriction. Le message d'erreur 429 (Limite atteinte. Réessayez après HH:MM:SS) et le Turnstile restent inchangés pour les utilisateurs anonymes.
v1.24.2Juillet 2026
  • Auto-bascule en mode Arabe à la saisie de caractères arabes — SearchBar.tsx : le handler onChange de l'input détecte la présence d'un caractère arabe (blocs Unicode ؀-ۿ, ݐ-ݿ, ࢠ-ࣿ, ﭐ-﷿, ﹰ-) et passe automatiquement mode à 'arab' si le mode courant n'est pas déjà 'arab'. Bascule à sens unique (pas de retour forcé vers latin). Le nouveau mode est immédiatement utilisé par le debounce d'autocomplétion et propagé via onSearch(q, mode) vers /dictionnaire (le field du résultat page suit).
v1.24.1Juillet 2026
  • Lien de révision si score < 50% sur l'écran de résultat du QCM — QuizPlayerArticle.tsx : en phase résultat, si correctCount / questions.length < 0.5 et que article_slug est renseigné sur le quiz, affiche un encart doré sous le score avec un message d'encouragement (locale quiz.reviewPrompt) et un bouton « Relire l'article » (locale quiz.reviewCta) vers /articles/{article_slug} via next/link. Si score ≥ 50% : comportement inchangé, aucun encart.
  • Locales fr/en — quiz.reviewPrompt et quiz.reviewCta ajoutés.
v1.24.0Juillet 2026
  • Module QCM relié aux articles via article_slug — /qcm/[articleSlug] charge les quiz publiés liés à un article (fr + ar) et affiche un player complet avec toggle de langue, validation par question et correction détaillée à la fin.
  • hasArticleQuiz(articleSlug) dans db.ts — requête count légère pour détecter si un quiz existe pour un article, utilisée par /articles/[slug] (CTA conditionnel).
  • getQuizzesByArticleSlug(articleSlug) dans db.ts — charge tous les quiz publiés pour un article_slug donné (fr + ar) avec leurs questions et réponses imbriquées (order_index).
  • types/index.ts — article_slug?: string | null ajouté à l'interface Quiz.
  • /articles/[slug]/page.tsx — CTA QCM relie maintenant via article_slug (non plus related_quiz_category). hasArticleQuiz() en Promise.all avec getRelatedArticles. Lien vers /qcm/${article.slug}.
  • /qcm/[slug]/page.tsx — double routing : essaie getQuizzesByArticleSlug (article_slug) en parallèle avec getQuizBySlug (slug quiz) ; si des quiz d'article trouvés → QuizPlayerArticle ; sinon si quiz standalone → QuizPlayer (rétrocompat).
  • QuizPlayerArticle.tsx (nouveau) — composant client : toggle FR/العربية (masqué si une seule langue), rendu question par question (radio=single, checkbox=multiple, mention "(plusieurs réponses possibles)" si multiple), validation avec feedback immédiat par réponse (vert/rouge), stockage de toutes les sélections, phase résultat : score X/N + % + correction par question (réponses surlignées vert/rouge + explication), bouton "Recommencer".
  • Locales fr/en — ajout de quiz.multiple et quiz.correctionTitle.
v1.23.3Juillet 2026
  • Fix recherche française accent-insensible sur la page de résultats — taper proteger (sans accent) ne trouvait pas Protéger... ni sécuriser sur la page /dictionnaire (mode "Français/Anglais"). L'autocomplétion fonctionnait déjà (via la RPC search_df_trad qui utilise unaccent()), mais les résultats complets (searchDf/searchMsa) faisaient un ILIKE accent-sensible sur translation_fr brut — 40% des traductions accentuées manquaient.
  • normalizeFr() ajoutée à src/lib/search-utils.ts — reproduit EXACTEMENT la normalisation SQL des colonnes générées translation_fr_norm / translation_en_norm (déjà en base) : str.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/œ/g, 'oe').replace(/æ/g, 'ae').trim(). PAS de mapping phonétique ni autre transformation (distincte de normalizeSearch()).
  • ILIKE parallèle sur colonnes normalisées dans src/lib/db.ts — dfIlike et msaIlike acceptent un 2ᵉ paramètre val (défaut : q). Branches field='fr' de searchDf et searchMsa : 2 ILIKE supplémentaires sur translation_fr_norm + translation_en_norm avec normalizeFr(q), en Promise.all(), colonnes normalisées placées EN TÊTE du merge (Set dédup existant). Jamais de .or() avec variable (règle PostgREST/virgule).
  • scoreWordRelevance() field='fr' — comparaisons sur formes normalisées normalizeFr (au lieu de normalizeSearch) : fFr === fq est EXACT même si les accents diffèrent. Garantit que proteger classe Protéger en 1.0 et sécuriser en 1.0.
  • Autocomplétion route.ts (field='fr') — 2 ILIKE supplémentaires sur translation_fr_norm + translation_en_norm avec normalizeFr(q) en Promise.all() aux côtés de la RPC search_df_trad existante.
  • Tests (npm run test:arabic-search) — 23 assertions (13 arabes v1.23.2 + 10 nouvelles fr) : normalizeFr('Protéger')==='proteger', normalizeFr('sécuriser')==='securiser', scoreWordRelevance('proteger',...,'Protéger','fr')===1.0, exact par sens (0.97), préfixe d'un sens (0.94), exact > contains.