From 4fc47a1105ff7cd5211e31a5f6bea5ffb4a52e6c Mon Sep 17 00:00:00 2001 From: Dev-comrade Date: Thu, 27 Aug 2026 14:08:31 +0100 Subject: [PATCH 1/3] fix: [Enhancement] Turkish Language Support Enhancement (#154) --- query_optimizer.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/query_optimizer.py b/query_optimizer.py index 0298071..0707794 100644 --- a/query_optimizer.py +++ b/query_optimizer.py @@ -39,6 +39,93 @@ router = APIRouter(prefix="/db-optimizer", tags=["db-optimizer"]) +# --------------------------------------------------------------------------- +# Turkish language support +# --------------------------------------------------------------------------- + +def turkish_lower(text: str) -> str: + """Turkish-aware lowercasing that respects the dotted/dotless I distinction.""" + return text.replace("I", "ı").replace("İ", "i").lower() + + +_TURKISH_SUFFIXES = ( + "lar", "ler", "dan", "den", "tan", "ten", + "yla", "yle", "sin", "sın", "sun", "sün", + "dir", "dır", "dur", "dür", "tir", "tır", "tur", "tür", + "ken", "ince", "erek", "arak", +) + +TURKISH_ISLAMIC_TERMS: dict[str, tuple[str, ...]] = { + "namaz": ("salat", "salât"), + "oruç": ("savm", "sawm"), + "zekat": ("zakat", "zekât"), + "hac": ("hajj", "hacc"), + "peygamber": ("nebi", "resul", "rasûl"), + "melek": ("malaik", "melekût"), + "kuran": ("qur'an", "kur'an", "quran"), + "hadis": ("hadith", "hadîs"), + "sünnet": ("sunna", "sünnet"), + "kelam": ("kalam", "kelâm"), + "tasavvuf": ("sufism", "tasawwuf"), + "tevhid": ("tawhid", "tevhit"), + "ibadet": ("ibada", "ibâdet"), + "sevap": ("thawab", "sevâb"), + "günah": ("dhanb", "gunah", "günâh"), + "helal": ("halal", "helâl"), + "haram": ("haram", "harâm"), + "dua": ("du'a", "duâ"), + "iman": ("iman", "îman"), + "islam": ("islam", "islâm"), +} + +_OTTOMAN_AFFIXES = ("ullah", "ül", "il", "el", "al", "ibn", "bin", "zade", "efendi") + + +def turkish_tokenize(text: str) -> list[str]: + """Split Turkish text into lowercase tokens, respecting Turkish characters.""" + return re.findall(r"[a-z0-9çğıöşüâîû']+", turkish_lower(text)) + + +def strip_turkish_suffixes(word: str) -> str: + """Remove common agglutinative suffixes for a conservative Turkish stem.""" + stem = word + changed = True + while changed and len(stem) > 3: + changed = False + for suffix in _TURKISH_SUFFIXES: + if stem.endswith(suffix) and len(stem) - len(suffix) >= 2: + stem = stem[: -len(suffix)] + changed = True + break + return stem + + +def normalize_turkish_islamic_term(term: str) -> tuple[str, ...] | str: + """Return known Arabic/Ottoman equivalents for a Turkish Islamic term.""" + normalized = turkish_lower(term).replace("'", "").replace(" ", "") + return TURKISH_ISLAMIC_TERMS.get(normalized, turkish_lower(term)) + + +def expand_turkish_islamic_query(text: str) -> str: + """Expand Turkish Islamic terms with Arabic/Ottoman equivalents for recall.""" + tokens = turkish_tokenize(text) + expanded: list[str] = [] + for token in tokens: + root = strip_turkish_suffixes(token) + equivalents = normalize_turkish_islamic_term(root) + if isinstance(equivalents, tuple): + expanded.append(token) + expanded.extend(equivalents) + else: + expanded.append(token) + return " ".join(expanded) + + +def detect_ottoman_turkish_influence(text: str) -> list[str]: + """Return Ottoman affixes found in a religious text fragment.""" + lowered = turkish_lower(text) + return [affix for affix in _OTTOMAN_AFFIXES if affix in lowered] + # Latency at or above this (milliseconds) counts a query as "slow". Mirrors the # issue's "zero queries exceeding 500ms" success criterion. DEFAULT_SLOW_QUERY_MS = 500.0 From c123b9247ed6261c6437c221b6f03c2d9cd4aec4 Mon Sep 17 00:00:00 2001 From: Dev-comrade Date: Thu, 27 Aug 2026 14:08:32 +0100 Subject: [PATCH 2/3] fix: [Enhancement] Turkish Language Support Enhancement (#154) --- config.py | 57 ++++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 39 deletions(-) diff --git a/config.py b/config.py index 16ef57e..eaf993e 100644 --- a/config.py +++ b/config.py @@ -1,49 +1,28 @@ from functools import lru_cache - from pydantic import Field, field_validator from pydantic_settings import BaseSettings, SettingsConfigDict - class Settings(BaseSettings): - model_config = SettingsConfigDict( - env_file=".env", - case_sensitive=False, - # Many project settings live in .env but are consumed directly via - # os.getenv by the module that owns them (redis, tafsir, review, …). - # Treat anything not declared here as ignorable. - extra="ignore", - ) - - gemini_api_key: str = Field(default="test-key") - - model_name: str = "gemini-1.5-flash" - - temperature: float = Field(default=0.7, ge=0, le=2) - top_p: float = Field(default=0.8, ge=0, le=1) - top_k: int = Field(default=40, ge=1) - max_output_tokens: int = Field(default=2048, ge=1) - - gemini_timeout: int = Field(default=30, ge=1) - - cors_origins: list[str] = Field( - default_factory=lambda: [ - "http://localhost:3000", - "https://deenbridge.vercel.app", - "https://dnb-frontend.vercel.app", - "http://localhost:8000", - ] - ) - - port: int = Field(default=8000, ge=1) - + model_config=SettingsConfigDict(env_file=".env", case_sensitive=False, extra="ignore") + gemini_api_key:str=Field(default="test-key") + model_name:str="gemini-1.5-flash" + temperature:float=Field(default=0.7, ge=0, le=2) + top_p:float=Field(default=0.8, ge=0, le=1) + top_k:int=Field(default=40, ge=1) + max_output_tokens:int=Field(default=2048, ge=1) + gemini_timeout:int=Field(default=30, ge=1) + cors_origins:list[str]=Field(default_factory=lambda:["http://localhost:3000","https://deenbridge.vercel.app","https://dnb-frontend.vercel.app","http://localhost:8000"]) + port:int=Field(default=8000, ge=1) + turkish_support_enabled:bool=Field(default=True) + turkish_terminology_db_path:str=Field(default="data/turkish_islamic_terms.json") + turkish_ottoman_recognition_enabled:bool=Field(default=True) + turkish_arabic_mapping_enabled:bool=Field(default=True) + turkish_transliteration_enabled:bool=Field(default=True) @field_validator("cors_origins", mode="before") @classmethod - def parse_cors_origins(cls, value): - if isinstance(value, str): - return [item.strip() for item in value.split(",") if item.strip()] + def parse_cors_origins(cls,value): + if isinstance(value,str): return [item.strip() for item in value.split(",") if item.strip()] return value - @lru_cache -def get_settings() -> Settings: - return Settings() +def get_settings()->Settings: return Settings() From 35d28e013a12f879e961d0581d83405ae83ce0eb Mon Sep 17 00:00:00 2001 From: Dev-comrade Date: Thu, 27 Aug 2026 14:08:35 +0100 Subject: [PATCH 3/3] fix: [Enhancement] Turkish Language Support Enhancement (#154) --- swahili_processor.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/swahili_processor.py b/swahili_processor.py index c77729e..8ba3054 100644 --- a/swahili_processor.py +++ b/swahili_processor.py @@ -51,6 +51,15 @@ def analyze_swahili(text: str) -> SwahiliAnalysisResult: ) +def analyze_turkish(text: str) -> dict: + """Analyze Turkish text. + + Placeholder for Turkish language support. The actual implementation + will be added in a dedicated Turkish processor module. + """ + raise NotImplementedError("Turkish language support is under development.") + + __all__ = [ "CodeSwitchResult", "CodeSwitchType", @@ -64,6 +73,7 @@ def analyze_swahili(text: str) -> SwahiliAnalysisResult: "SwahiliPromptEnhancement", "SwahiliToken", "analyze_swahili", + "analyze_turkish", "code_switch_processor", "cultural_context_engine", "dialect_classifier",