Skip to main content

Moroccan Darija (Arabic) phrase analyzer — classify each word by source language (French/English/Darija), detect semantic entities (money, time, date, phone...) and strip morphological prefixes. Built in Rust for O(1) lookup.

Project description

darija-router

Moroccan Darija language router — O(1) phrase analysis with morphological stripping and semantic tagging. Built in Rust, wrapped for Python.

Classifies Arabic-script Darija words by source language (fr, en, darija), Latin spelling, category, probability, and semantic role.

Install

pip install darija-router

Quick Start

import darija_router

# "Brother, I want to meet you tomorrow at 3 AM in the square,
#  do you want us to buy a new phone for 500 dirhams?"
result = darija_router.analyze(
    "خويا باغي نلقاك غدوة الساعة 3 صباح فالساحة، "
    "واش باغي نشريو شي تيليفون جديد ب 500 درهم؟"
)

Response:

[
  {
    "token": "خويا",
    "index": 0,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "family_relationships" }
    ],
    "stem": null,
    "semantic": null
  },
  {
    "token": "باغي",
    "index": 1,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "نلقاك",
    "index": 2,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "غدوة",
    "index": 3,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "time_weather" }
    ],
    "stem": null,
    "semantic": "DATE"
  },
  {
    "token": "الساعة",
    "index": 4,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "time_weather" }
    ],
    "stem": {
      "matched_stem": "ساعة",
      "stripped_prefix": "ال",
      "stripped_suffix": null,
      "normalized": false
    },
    "semantic": "TIME"
  },
  {
    "token": "3",
    "index": 5,
    "entries": [],
    "stem": null,
    "semantic": "TIME"
  },
  {
    "token": "صباح",
    "index": 6,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "time_weather" }
    ],
    "stem": null,
    "semantic": "TIME"
  },
  {
    "token": "فالساحة",
    "index": 7,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "،",
    "index": 8,
    "entries": [],
    "stem": null,
    "semantic": "PUNCT"
  },
  {
    "token": "واش",
    "index": 9,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "slang_fillers" }
    ],
    "stem": null,
    "semantic": null
  },
  {
    "token": "باغي",
    "index": 10,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "نشريو",
    "index": 11,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "شي",
    "index": 12,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "تيليفون",
    "index": 13,
    "entries": [
      { "lang": "fr", "latin_word": "téléphone", "prob": 100.0, "category": "technology_digital" }
    ],
    "stem": null,
    "semantic": null
  },
  {
    "token": "جديد",
    "index": 14,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "ب",
    "index": 15,
    "entries": [],
    "stem": null,
    "semantic": null
  },
  {
    "token": "500",
    "index": 16,
    "entries": [],
    "stem": null,
    "semantic": "MONEY"
  },
  {
    "token": "درهم",
    "index": 17,
    "entries": [
      { "lang": "darija", "latin_word": null, "prob": 100.0, "category": "administration_official" }
    ],
    "stem": null,
    "semantic": "MONEY"
  },
  {
    "token": "؟",
    "index": 18,
    "entries": [],
    "stem": null,
    "semantic": "PUNCT"
  }
]

Breakdown:

Token Lang Category Semantic Notes
خويا darija family exact match — "my brother"
باغي Darija verb (I want)
نلقاك Darija verb (I meet you)
غدوة darija time DATE exact match — "tomorrow"
الساعة darija time TIME stripped ال → ساعة (hour)
3 TIME context: follows الساعة
صباح darija time TIME exact match — "morning"
فالساحة Darija (in the square)
، PUNCT Arabic comma
واش darija slang exact match — question particle
باغي Darija verb (you want)
نشريو Darija verb (we buy)
شي Darija (a/some)
تيليفون fr tech exact match — téléphone
جديد Darija adjective (new)
ب Darija preposition (for/with)
500 MONEY context: followed by درهم
درهم darija admin MONEY exact match — "dirham"
؟ PUNCT Arabic question mark

Semantic Tags

Each token gets a semantic field with rule-based detection:

Tag Detection Example
PUNCT Punctuation characters ؟ ، . !
CARDINAL Digits or Arabic number words 50 عشرين مية
DECIMAL Decimal numbers 3.5 ١٢.٥
MONEY Cardinal + currency word 50 درهم → both tokens tagged
MEASURE Cardinal + unit word 2 كيلو → both tokens tagged
TIME الساعة + cardinal, or time words الساعة 3 صباح مساء
DATE Date words or cardinal + month غدوة 15 مارس
ORDINAL Arabic ordinal words تاني تالت أول
FRACTION Arabic fraction words نص ربع تلت
PERCENT % suffix or بالمئة 20%
PHONE Phone number patterns +212661234567 0612345678
EMAIL Contains @ and . user@gmail.com
URL Starts with http or www. http://google.com
ADDRESS Address keyword + following word زنقة الحسن

Single Word Lookup

darija_router.lookup("بون")
{
  "token": "بون",
  "index": 0,
  "entries": [
    { "lang": "fr", "latin_word": "bon", "prob": 20.01, "category": "adjectives_expressions" },
    { "lang": "fr", "latin_word": "bonne", "prob": 13.33, "category": "adjectives_expressions" },
    { "lang": "fr", "latin_word": "bon", "prob": 33.33, "category": "money_commerce" },
    { "lang": "fr", "latin_word": "pont", "prob": 33.33, "category": "transportation_vehicles" }
  ],
  "stem": null,
  "semantic": null
}

API Reference

darija_router.analyze(phrase: str) -> list[dict]

Tokenizes a phrase and classifies each token. Returns a list of result objects:

Field Type Description
token str The original token
index int Position in the phrase (0-based)
entries list[dict] Classification results (empty if not found)
stem dict or null Morphological info if a prefix/suffix was stripped
semantic str or null Semantic tag (PUNCT, CARDINAL, MONEY, TIME, DATE, etc.)

darija_router.lookup(word: str) -> dict

Looks up a single word. Same result format as one element from analyze().

darija_router.__version__

Package version string.

How It Works

  1. Embedded lexicon — 1,595 Arabic-script keys compiled into the binary via include_str!(). Zero file I/O, zero startup cost.

  2. O(1) HashMap lookup — exact match against a HashMap<String, Vec<Entry>>.

  3. Morphological fallback — when an exact match fails, the engine strips prefixes and suffixes:

    Prefixes: ال و ف ب ل م ك

    Suffixes: هم ها ش ك ي

    Normalization: ةه

    Tries: exact → normalize → single strip → double strip. Minimum stem length of 2 prevents over-stripping.

  4. Semantic tagger — rule-based second pass detects 14 semantic categories via regex patterns and context-aware grouping (e.g. cardinal + currency word → MONEY).

  5. 17 thematic categories — transportation, technology, food, health, clothing, home, education, sports, work, money, adjectives, family, colors, time, nature, administration, slang.

Build from Source

git clone https://github.com/LaamiriOuail/darija-router.git
cd darija-router
pip install maturin
maturin develop --release

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

darija_router-0.2.0-cp312-cp312-win_amd64.whl (205.5 kB view details)

Uploaded CPython 3.12Windows x86-64

darija_router-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (279.3 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

File details

Details for the file darija_router-0.2.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for darija_router-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 634e97cfc0f18f6e1e383dde50b5624b5ee38e914ed7fec56211edab867c9ac2
MD5 61cbc1ff2a4a8bbf27953ab2c2f9bc1d
BLAKE2b-256 b8e638c26274b78f218e80bdbc5e028ed53d7c0947aab52ce2fd7601d0540bfc

See more details on using hashes here.

File details

Details for the file darija_router-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for darija_router-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0f92dc7ad9021660ddf8e3a0ce289acdb0a2127f22478cdb1f7b8cefeead6a52
MD5 b9e42f479d83a9fd6225417c1db5b83c
BLAKE2b-256 b2831afcf412f4582c4a416029ff22507f5d38eb1798d4b261173a886e2b3d69

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page