""" Penentuan bahasa untuk routing detektor. Sistem ini difokuskan ke Bahasa Indonesia. Teks yang terdeteksi sebagai Inggris dikembalikan sebagai "en" dan tidak diproses lebih lanjut oleh pipeline. Teks tanpa huruf dikembalikan sebagai "unknown". Deteksi menggunakan wordfreq: tiap kata dibandingkan frekuensi Zipf-nya di corpus Inggris vs Indonesia. Bila Inggris mengungguli Indonesia pada ≥65% kata yang punya signal (minimum 3 kata), teks diklasifikasikan sebagai "en". """ from __future__ import annotations import re from dataclasses import dataclass from typing import Literal LanguageCode = Literal["id", "en", "unknown"] _HAS_LETTER = re.compile(r"[A-Za-z]") _MIN_SIGNAL_WORDS = 3 # minimum kata berkontribusi agar deteksi berlaku _EN_DOMINANCE_THRESH = 0.65 # proporsi "en > id" untuk diklasifikasi Inggris @dataclass(frozen=True) class LanguageDetection: """Hasil pendeteksian bahasa. Hanya field language yang dipakai pemanggil.""" language: LanguageCode def detect_language(text: str) -> LanguageDetection: """ Deteksi bahasa teks secara ringan menggunakan wordfreq. Returns: "en" — teks didominasi kata-kata Inggris "id" — teks Indonesia atau campuran (default) "unknown" — teks tidak mengandung huruf """ if not text or not _HAS_LETTER.search(text): return LanguageDetection("unknown") try: from wordfreq import zipf_frequency, tokenize # type: ignore[import] words = [w for w in tokenize(text, "en") if _HAS_LETTER.search(w) and len(w) > 2] if len(words) >= _MIN_SIGNAL_WORDS: en_wins = id_wins = 0 for w in words: ef = zipf_frequency(w, "en") if_ = zipf_frequency(w, "id") if ef > if_: en_wins += 1 elif if_ > ef: id_wins += 1 total = en_wins + id_wins if total >= _MIN_SIGNAL_WORDS and en_wins / total > _EN_DOMINANCE_THRESH: return LanguageDetection("en") except Exception: pass return LanguageDetection("id")