à but non lucratif · maintenu par une personne · ouvre aux contributions
Environ douze millions de personnes écrivent le derja tunisien chaque jour — dans des messages, des commentaires, au milieu de phrases en français — et il n'en existe presque aucune trace correcte. OpenDerja_TN est une plateforme où les Tunisiens écrivent, corrigent et confirment leur propre derja régional. Il en sort un corpus citable, un lexique et un traducteur bâti directement dessus. Le texte d'abord ; la voix par conception dans une phase ultérieure.
Une grand-mère du nord-ouest emploie un mot que personne d'autre n'utilise. Quand elle arrête, il disparaît — personne ne l'a écrit. Cela arrive sans cesse, et personne ne s'en occupe.
Ce que c'est
La plateforme fonctionne sur du texte dès le premier jour. Le modèle de consentement et le schéma pour la voix existent dès la première migration — pas ajoutés des années plus tard, quand on ne peut plus les recueillir rétroactivement.
La couverture par région est un chiffre suivi, publié et pour lequel on recrute — pas un espoir. Ce qui est en ligne penche vers Tunis ; la sollicitation ciblée est le contrepoids.
Les corpus académiques s'arrêtent le jour où l'article paraît. Celui-ci est fait pour continuer de grandir, et chaque contribution confirmée améliore les outils le jour même.
Utilise les conventions orthographiques existantes CODA-TUN et NOTA au lieu d'en inventer une autre.
Le corpus est exposé comme un outil qu'on a une raison d'ouvrir — un traducteur, un lexique, une vue comparative — pas seulement un fichier qu'on a une raison de citer.
Pourquoi l'utiliser
Le corpus est la fondation ; voici ce pour quoi on vient vraiment.
Derja → arabe standard / français / anglais dans n'importe quelle graphie, et — ce que personne d'autre ne propose — arabe standard / français / anglais → derja avec un sélecteur de région. « Dis-le en derja du sud » est impossible avec les outils existants.
Un jeu de données versionné, sous licence ouverte, étiqueté par région, avec des statistiques de couverture honnêtes, un DOI et des paliers de licence par source. Il rend ce que les Tunisiens ont réellement écrit, ou rien — d'où sa citabilité.
Des données ouvertes à télécharger ou interroger : paires parallèles, phrases étiquetées par région, un lexique avec variantes régionales et étymologies. Pas de clé d'API, pas de coût, rien dans le chemin de requête qui puisse tomber en panne.
Une seule case : un mot, une phrase, un paragraphe. La région en quatre boutons, le consentement en une case, sans compte. Trois secondes et c'est dans le registre.
Ce qui le distingue
Ce n'est pas le premier corpus tunisien (Tunisiya, TARIC, TSAC et d'autres existent), pas la première standardisation de l'arabe tunisien (CODA-TUN l'a faite), pas la première plateforme de crowdsourcing de dialecte arabe. Ce qu'aucune plateforme existante ne réunit au même endroit : le texte maintenant et la voix par conception ensuite ; la confirmation par la communauté au lieu de la parole d'une seule autorité ; la région et l'époque étiquetées ensemble, l'ancien derja à côté des quatre régions d'aujourd'hui ; un traducteur qui marche, pas juste un fichier ; des données ouvertes ; maintenu en continu comme un seul service ouvert.
| Région | Couvre |
|---|---|
| nord-ouest | Le Kef, Jendouba, Siliana, Kasserine, les hauteurs de l'ouest |
| nord | Tunis, Bizerte, Nabeul, l'Ariana, la Manouba, Ben Arous |
| sahel | Sousse, Monastir, Mahdia, Sfax, le centre côtier |
| sud | Gabès, Médenine, Tataouine, Tozeur, Kébili, Douz, Gafsa |
| Axe | Valeurs | Note |
|---|---|---|
| portée | pan-tunisien · régional | S'il est marqué du tout, pas à quel point il est répandu |
| région | un ensemble : nord-ouest · nord · sahel · sud | Une ou plusieurs. Vide si pan-tunisien — le dialecte est un continuum, donc la région est un ensemble, jamais une valeur unique. |
| époque | contemporain · historique | L'« ancien derja » est ici, pas dans la région |
| milieu | urbain · rural · inconnu | Traverse les régions, ne les suit pas |
| registre | neutre · formel · vulgaire · archaïque | Le vulgaire est filtré par défaut avec une bascule d'activation honnête, jamais retiré des exports |
« Nord-ouest + rural + historique » est une requête réelle — et c'est exactement le matériau que personne n'a collecté, ce qui est l'essentiel de la raison d'être du projet.
La boucle centrale
Tout le système est construit autour de cette boucle — que le texte soit saisi par un contributeur ou récupéré d'une source publique par un scraper.
Quelqu'un le contribue, ou un scraper le tire d'une source ouverte à base de dumps (Wikipédia, Common Crawl filtré sur .tn, Tatoeba, forums tunisiens sous leurs propres CGU).
Est-ce vraiment du derja ? Trop court ou trop long ? Est-ce un quasi-doublon de ce qui est déjà dans le corpus (MinHash/LSH) ?
S'il paraît nouveau et valide. Un doublon déclenche « on a déjà celui-ci — votre région le dit-elle autrement ? » au lieu d'un rejet silencieux.
Le relire, étiqueter sa région, le confirmer, le traduire, relier ses mots au lexique.
Rien de ce qu'une personne écrit n'est automatiquement « vrai ». Une étiquette ou une traduction reste une proposition jusqu'à l'accord de plusieurs personnes indépendantes.
Assez d'accord → cela devient la réponse de confiance. Désaccord → un relecteur routé par région tranche. Seule la réponse validée est montrée publiquement.
Le traducteur
La recherche de mot et d'expression passe par le lexique : correspondance exacte, puis normalisée, puis similarité par trigrammes pour les fautes de frappe. Les phrases sont retrouvées par similarité de trigrammes sur les éléments de corpus attestés, avec leurs traductions humaines.
Vers le derja avec un sélecteur de région : c'est la démo qui fait partager le lien.
Chaque annotation acceptée l'améliore immédiatement — pas de réentraînement, pas d'instantané à promouvoir, pas de risque de régression. Un traducteur par recherche ne peut que s'améliorer.
Pas d'attestation, pas de devinette. Il montre ce qu'il a trouvé, les voisins approximatifs les plus proches, ce qui manque par région (« attesté au nord et au sahel. Aucune attestation du sud. ») et une invite en un clic pour exactement ce manque.
Un compteur en direct : ce traducteur connaît N mots et M phrases sur quatre régions, en hausse depuis le mois dernier. Le premier jour ce nombre est gênant de petitesse, et il reste visible quand même.
C'est une recherche dans un corpus, pas de la traduction automatique. Il rend ce que les Tunisiens ont réellement écrit, ou rien. C'est un produit plus faible qu'un modèle fluide et plus honnête — et c'est cette honnêteté qui permet à un chercheur de le citer. Tout ce qui est généré appartient à une phase ultérieure, toujours étiqueté, jamais mêlé aux résultats attestés.
Architecture
Ce découpage permet de comprendre, tester et changer chaque pièce séparément.
| Plan | Langage | Ce qu'il fait |
|---|---|---|
| control-plane/ | TypeScript | backend (API NestJS), worker (tâches de fond), scrapers. Presque toute la logique — et cela reste du TypeScript en permanence ; les problèmes difficiles ici sont les règles, pas la vitesse brute. |
| data-plane/ | Rust | Travail intensif en CPU dont on a mesuré le besoin. Aujourd'hui : détection de quasi-doublons. Le reste est un stub tant que le profilage ne dit pas autre chose — une pièce n'est réécrite en Rust qu'une fois prouvée goulot d'étranglement. |
| intelligence-plane/ | Python (FastAPI) | Inférence et entraînement ML, conditionnés par phase. Un simple stub de health-check pour l'instant — rien dans le chemin de requête ne l'attend, volontairement. |
| frontend/ | TypeScript (Next.js) | La seule pièce qu'un visiteur touche. Ne parle jamais directement à la base — toujours via l'API backend, pour qu'il y ait exactement un endroit où les règles sont appliquées. |
Vue complète avec schémas, pour développeurs et non-développeurs : docs/ARCHITECTURE.md. Chaque endpoint avec ses formes de requête/réponse : docs/API_REFERENCE.md.
Où en sont les choses
Le projet tient un registre honnête de ce qui a été mené de bout en bout, de ce qui est construit-mais-non-vérifié, et de ce qui n'existe pas encore. En bref :
Auth (mot de passe, OAuth, 2FA, sessions de contributeur anonyme), le moteur de tâches, le consensus, l'outillage admin, un pipeline de scraping, un service Rust de déduplication. Vraie couverture unitaire. Le prochain jalon est de l'exécuter sur un déploiement réel — un vrai travail, pas une formalité.
Chaque page de la spec existe comme un stub qui compile et renvoie 200, pas comme une page qui marche. Sept composants d'annotation partagés n'existent pas encore. docs/API_REFERENCE.md a déjà chaque endpoint.
Le plan Rust fait un seul travail mesuré. Le plan Python est un stub de health-check. Chacun le reste jusqu'à une raison mesurée — pas un minuteur de phase.
Si vous prenez une PR ici en attendant un produit fini, vous serez déçu. Si vous attendez un backend réel qui marche avec des trous évidents à combler côté frontend — c'est exact.
Contribuer
Le travail à plus forte valeur aujourd'hui. Transformer des stubs de routes en vraies pages contre une API documentée, et construire les composants d'annotation partagés.
Corrections chirurgicales — bugs, couverture de tests manquante, combler un trou documenté (voir db/DATABASE_NOTES.md).
Pas encore — le flux de contribution doit être en ligne et relu d'abord. S'ouvre quand le frontend aura rattrapé.
Toujours utile, aucun seuil d'expérience.
Une règle valable pour tout le projet
Aucun commentaire de code, nulle part, sans exception. Si vous pensez sincèrement qu'un commentaire est nécessaire, dites-le dans la description de la PR et laissez le mainteneur décider de la formulation. Une PR qui ajoute des commentaires se verra demander de les retirer.
Vous planifiez quelque chose de conséquent ? Ouvrez d'abord une issue — il est moins coûteux de réorienter un plan qu'une PR finie. Les délais de revue dépendent de la disponibilité d'une personne ; une réponse lente n'est pas un signe que votre contribution n'est pas voulue.
Démarrer
git clone https://github.com/firaslamouchi21/Open_Derja_Tn.git && cd Open_Derja_Tn pnpm install && cp .env.example .env # postgres, pgbouncer, redis, stubs pnpm infra:up # pnpm --filter @open-derja/db run migrate:deploy # :3000 pnpm --filter @open-derja/backend run start:dev # :3001 pnpm --filter @open-derja/frontend run dev Remplacez chaque valeur change-me dans .env — surtout AUTH_SECRET (openssl rand -base64 32). La CI est désactivée en attendant le lancement public : lancez les suites de tests localement (pnpm test:unit, cargo test) avant d'ouvrir une PR.
Licence
Apache 2.0 — tout le dépôt. Permissif à dessein : l'adoption compte plus que le contrôle.
Sous licence séparée, et le choix reste à faire entre share-alike et non commercial. Il ne s'agit pas de revenus — il n'y en a pas — mais d'empêcher quelqu'un de murer ce que des contributeurs ont bâti gratuitement et de le leur revendre.
À la soumission, une case explicite : ce matériau peut entrer dans un jeu de données sous licence ouverte, usage commercial compris — couvrant l'enregistrement annoté, pas seulement le texte brut. Une clause voix distincte l'accompagne dès le premier jour, des années avant que l'enregistrement existe, car elle ne peut pas être recueillie rétroactivement.
Contact
Envie de contribuer, une question sur l'architecture, ou vous travaillez sur le TAL tunisien et voulez comparer — cela arrive directement dans la boîte de Firas et vous recevrez un accusé de réception automatique.