# language_config.py # Single source of truth for supported languages (English + Urdu only). 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 Unicode characters not found in standard Arabic URDU_SPECIFIC_CHARS = re.compile(r"[\u067E\u0686\u06AF\u06A9\u0698\u06D2\u06BE]") # Arabic script range (covers Urdu and loanwords) ARABIC_SCRIPT = re.compile(r"[\u0600-\u06FF]") # Devanagari / Gurmukhi — Hindi and Punjabi fold into Urdu DEVANAGARI = re.compile(r"[\u0900-\u097F]") GURMUKHI = re.compile(r"[\u0A00-\u0A7F]") # Urdu grammar particles in Arabic script URDU_PARTICLES = re.compile( r"\b(آپ|کے|ہے|نہیں|مجھے|کیا|کہاں|کیوں|جناب|شکریہ|ہوں|ہیں|تھا|گا|گی|گے|" r"میں|سے|کو|پر|یہ|وہ|کا|کی|کے|لیے|لئے|کر|رہا|رہی|سکتا|سکتی|ہوگا|ہوگی)\b" ) # Shared Islamic/Urdu phrases (Arabic script + roman variants) URDU_SHARED_PHRASES = [ # Arabic script "السلام علیکم", "السلام عليكم", "وعلیکم السلام", "وعليكم السلام", "ماشاء اللہ", "ماشاء الله", "ان شاء اللہ", "ان شاء الله", "الحمد للہ", "الحمد لله", "سبحان اللہ", "سبحان الله", "جزاک اللہ", "جزاك الله", "بارک اللہ", "بارك الله", "اللہ", "الله", "بسم اللہ", "بسم الله", "شکریہ", "جزاکم", "فی امان اللہ", # Roman variants "assalam u alaikum", "assalamu alaikum", "salam alaikum", "masha allah", "mashallah", "inshallah", "in sha allah", "alhamdulillah", "subhanallah", "jazakallah", "bismillah", ] # Roman Urdu lexical markers 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