| |
| |
|
|
| import re |
| from typing import Literal |
|
|
| SUPPORTED_LANGUAGES = ("en", "ur") |
| DEFAULT_LANGUAGE = "ur" |
| URDU_REDIRECT_CODES = frozenset({"hi", "pa"}) |
|
|
| ArabicScriptClassification = Literal["clear_urdu", "needs_clarification", "not_arabic_script"] |
|
|
| |
| URDU_SPECIFIC_CHARS = re.compile(r"[\u067E\u0686\u06AF\u06A9\u0698\u06D2\u06BE]") |
|
|
| |
| ARABIC_SCRIPT = re.compile(r"[\u0600-\u06FF]") |
|
|
| |
| DEVANAGARI = re.compile(r"[\u0900-\u097F]") |
| GURMUKHI = re.compile(r"[\u0A00-\u0A7F]") |
|
|
| |
| URDU_PARTICLES = re.compile( |
| r"\b(آپ|کے|ہے|نہیں|مجھے|کیا|کہاں|کیوں|جناب|شکریہ|ہوں|ہیں|تھا|گا|گی|گے|" |
| r"میں|سے|کو|پر|یہ|وہ|کا|کی|کے|لیے|لئے|کر|رہا|رہی|سکتا|سکتی|ہوگا|ہوگی)\b" |
| ) |
|
|
| |
| URDU_SHARED_PHRASES = [ |
| |
| "السلام علیکم", "السلام عليكم", "وعلیکم السلام", "وعليكم السلام", |
| "ماشاء اللہ", "ماشاء الله", "ان شاء اللہ", "ان شاء الله", |
| "الحمد للہ", "الحمد لله", "سبحان اللہ", "سبحان الله", |
| "جزاک اللہ", "جزاك الله", "بارک اللہ", "بارك الله", |
| "اللہ", "الله", "بسم اللہ", "بسم الله", |
| "شکریہ", "جزاکم", "فی امان اللہ", |
| |
| "assalam u alaikum", "assalamu alaikum", "salam alaikum", |
| "masha allah", "mashallah", "inshallah", "in sha allah", |
| "alhamdulillah", "subhanallah", "jazakallah", "bismillah", |
| ] |
|
|
| |
| ROMAN_URDU_TERMS = [ |
| "aap", "salaam", "shukriya", "khuda", "allah", "janab", "dost", "bhai", |
| "zaroor", "zindagi", "khabar", "dua", "kaise", "hain", "hai", "mujhe", |
| "nahi", "kahan", "kya", "kia", "kiu", "kar", "sakhti", "sakta", "kesse", "kese", |
| ] |
|
|
| ROMAN_URDU_MARKERS = frozenset({ |
| "kia", "karte", "kiu", "kar", "sakhti", "sakta", "hai", |
| "naam", "aap", "meri", "zabaan", "jawaab", "g", "ho", "koshish", |
| "kesse", "kese", "kya", "acha", "theek", "bhai", "shukriya", |
| }) |
|
|
| ROMAN_URDU_PATTERN = re.compile( |
| r"\b(?:kh|gh|sh|ph|q|z)\w*|\b(aap|salaam|janab|kese|kesse|kia)\b", |
| re.IGNORECASE, |
| ) |
|
|
|
|
| def normalize_language(code: str) -> str: |
| """Clamp any input or legacy language code to en or ur.""" |
| lang = (code or DEFAULT_LANGUAGE).lower().strip() |
| if lang in URDU_REDIRECT_CODES or lang == "ur": |
| return "ur" |
| return "en" |
|
|
|
|
| def has_arabic_script(text: str) -> bool: |
| return bool(ARABIC_SCRIPT.search(text)) |
|
|
|
|
| def classify_arabic_script(text: str) -> ArabicScriptClassification: |
| """ |
| Classify Arabic-script input for Urdu lane routing. |
| Returns clear_urdu, needs_clarification, or not_arabic_script. |
| """ |
| if not text or not has_arabic_script(text): |
| return "not_arabic_script" |
|
|
| if URDU_SPECIFIC_CHARS.search(text): |
| return "clear_urdu" |
|
|
| if URDU_PARTICLES.search(text): |
| return "clear_urdu" |
|
|
| text_lower = text.lower() |
| for phrase in URDU_SHARED_PHRASES: |
| if phrase.lower() in text_lower: |
| return "clear_urdu" |
|
|
| return "needs_clarification" |
|
|
|
|
| def detect_roman_urdu(text: str) -> bool: |
| """Return True if Latin-script text looks like Roman Urdu.""" |
| normalized = text.lower().strip() |
| if sum(1 for term in ROMAN_URDU_TERMS if re.search(rf"\b{term}\b", normalized)) >= 2: |
| return True |
| if ROMAN_URDU_PATTERN.search(text): |
| return True |
| words = set(normalized.split()) |
| if words.intersection(ROMAN_URDU_MARKERS): |
| return True |
| return False |
|
|