Spaces:
Running
Running
import re | |
from collections import Counter | |
import logging | |
logger = logging.getLogger(__name__) | |
class LanguageDetector: | |
""" | |
Metin dilini algılayan sınıf. | |
İstatistiksel yöntemlerle metinlerin dilini tespit eder. | |
""" | |
def __init__(self): | |
"""Dil algılama sınıfını başlatır""" | |
# Dil tanıma için tipik karakter ve kelime varlıkları | |
self.language_profiles = { | |
'tr': { | |
'chars': 'abcçdefgğhıijklmnoöprsştuüvyz', | |
'unique_chars': 'çğıöşü', | |
'common_words': [ | |
've', 'bir', 'bu', 'da', 'de', 'için', 'ile', 'ben', 'sen', 'o', | |
'biz', 'siz', 'ama', 'ki', 'ya', 'çok', 'daha', 'en', 'ne', 'kadar', | |
'var', 'yok', 'mı', 'mi', 'mu', 'mü', 'gibi', 'olarak', 'çünkü', | |
'sonra', 'önce', 'nasıl', 'neden', 'evet', 'hayır', 'ise', 'veya' | |
] | |
}, | |
'en': { | |
'chars': 'abcdefghijklmnopqrstuvwxyz', | |
'unique_chars': 'qwxz', | |
'common_words': [ | |
'the', 'and', 'a', 'to', 'of', 'in', 'is', 'you', 'that', 'it', | |
'he', 'was', 'for', 'on', 'are', 'as', 'with', 'his', 'they', | |
'at', 'be', 'this', 'have', 'from', 'or', 'one', 'had', 'by', | |
'but', 'not', 'what', 'all', 'were', 'we', 'when', 'your', 'can', | |
'there', 'if', 'more', 'an', 'who' | |
] | |
}, | |
'de': { | |
'chars': 'abcdefghijklmnopqrstuvwxyzäöüß', | |
'unique_chars': 'äöüß', | |
'common_words': [ | |
'der', 'die', 'das', 'und', 'in', 'zu', 'den', 'mit', 'auf', 'für', | |
'ist', 'im', 'dem', 'nicht', 'ein', 'eine', 'als', 'auch', 'es', | |
'von', 'sich', 'oder', 'so', 'zum', 'bei', 'eines', 'nur', 'am', | |
'werden', 'noch', 'wie', 'einer', 'aber', 'aus', 'wenn', 'doch' | |
] | |
}, | |
'fr': { | |
'chars': 'abcdefghijklmnopqrstuvwxyzàâçéèêëîïôùûü', | |
'unique_chars': 'àâçéèêëîïôùûü', | |
'common_words': [ | |
'le', 'la', 'les', 'de', 'des', 'un', 'une', 'et', 'est', 'en', | |
'du', 'dans', 'qui', 'que', 'pour', 'pas', 'sur', 'ce', 'vous', | |
'avec', 'au', 'il', 'je', 'sont', 'mais', 'nous', 'si', 'plus', | |
'leur', 'par', 'ont', 'ou', 'comme', 'elle', 'tout', 'même' | |
] | |
}, | |
'es': { | |
'chars': 'abcdefghijklmnopqrstuvwxyzáéíóúüñ', | |
'unique_chars': 'áéíóúüñ', | |
'common_words': [ | |
'el', 'la', 'los', 'las', 'de', 'del', 'un', 'una', 'unos', 'unas', | |
'y', 'e', 'o', 'u', 'que', 'en', 'a', 'con', 'por', 'para', 'es', | |
'son', 'al', 'lo', 'su', 'sus', 'se', 'mi', 'me', 'te', 'nos', | |
'como', 'pero', 'más', 'este', 'esta', 'esto' | |
] | |
} | |
} | |
# Desteklenen diller | |
self.supported_languages = { | |
'tr': 'Türkçe', | |
'en': 'İngilizce', | |
'de': 'Almanca', | |
'fr': 'Fransızca', | |
'es': 'İspanyolca', | |
'unknown': 'Bilinmeyen' | |
} | |
logger.info("Dil algılama modülü başlatıldı") | |
def _clean_text(self, text): | |
""" | |
Metni temizler | |
Args: | |
text: Temizlenecek metin | |
Returns: | |
str: Temizlenmiş metin | |
""" | |
if not text: | |
return "" | |
# Küçük harfe çevir | |
text = text.lower() | |
# Sayıları ve özel karakterleri kaldır (dil karakterleri hariç) | |
text = re.sub(r'[0-9]', '', text) | |
text = re.sub(r'[^\w\s\u00C0-\u00FF\u0100-\u017F\u0400-\u04FF]', '', text) | |
return text | |
def _get_words(self, text): | |
""" | |
Metinden kelimeleri çıkarır | |
Args: | |
text: Kelimesi çıkarılacak metin | |
Returns: | |
list: Kelimeler listesi | |
""" | |
words = re.findall(r'\b\w+\b', text.lower()) | |
return words | |
def _calculate_character_score(self, text, language): | |
""" | |
Metindeki karakterlerin dile uygunluğunu hesaplar | |
Args: | |
text: Değerlendirilecek metin | |
language: Dil kodu | |
Returns: | |
float: Karakter skoru (0-1 arası) | |
""" | |
if not text: | |
return 0.0 | |
profile = self.language_profiles.get(language, {}) | |
chars = profile.get('chars', '') | |
unique_chars = profile.get('unique_chars', '') | |
# Metin içindeki karakterleri say | |
char_count = Counter(text.lower()) | |
# Dildeki karakterlerin metinde bulunma oranı | |
total_chars = sum(char_count.values()) | |
if total_chars == 0: | |
return 0.0 | |
matched_chars = sum(char_count.get(char, 0) for char in chars) | |
char_ratio = matched_chars / total_chars | |
# Dile özgü karakterlerin varlığını kontrol et | |
unique_char_present = any(char in text.lower() for char in unique_chars) | |
unique_bonus = 0.2 if unique_char_present else 0.0 | |
return min(1.0, char_ratio + unique_bonus) | |
def _calculate_word_score(self, words, language): | |
""" | |
Kelimelerin dile uygunluğunu hesaplar | |
Args: | |
words: Değerlendirilecek kelimeler listesi | |
language: Dil kodu | |
Returns: | |
float: Kelime skoru (0-1 arası) | |
""" | |
if not words: | |
return 0.0 | |
common_words = self.language_profiles.get(language, {}).get('common_words', []) | |
# Yaygın kelimelerin metinde bulunma sayısı | |
matched_words = sum(1 for word in words if word in common_words) | |
# Yaygın kelime oranı | |
word_ratio = matched_words / min(len(words), 100) # En fazla 100 kelime değerlendir | |
return word_ratio | |
def detect_language(self, text): | |
""" | |
Metnin dilini tespit eder | |
Args: | |
text: Dili tespit edilecek metin | |
Returns: | |
dict: { | |
'language_code': dil kodu (tr, en, vb), | |
'language_name': dil adı, | |
'confidence': güven skoru (0-1 arası), | |
'scores': dil bazında skorlar | |
} | |
""" | |
if not text or len(text.strip()) < 5: | |
return { | |
'language_code': 'unknown', | |
'language_name': self.supported_languages.get('unknown'), | |
'confidence': 0.0, | |
'scores': {} | |
} | |
try: | |
clean_text = self._clean_text(text) | |
words = self._get_words(clean_text) | |
scores = {} | |
# Her dil için skor hesapla | |
for lang_code in self.language_profiles.keys(): | |
char_score = self._calculate_character_score(clean_text, lang_code) | |
word_score = self._calculate_word_score(words, lang_code) | |
# Ağırlıklı toplam (karakter:0.4, kelime:0.6) | |
total_score = (char_score * 0.4) + (word_score * 0.6) | |
scores[lang_code] = total_score | |
# En yüksek skorlu dili bul | |
if not scores: | |
detected_lang = 'unknown' | |
confidence = 0.0 | |
else: | |
detected_lang = max(scores, key=scores.get) | |
confidence = scores[detected_lang] | |
# Eğer güven skoru çok düşükse "bilinmeyen" olarak işaretle | |
if confidence < 0.15: | |
detected_lang = 'unknown' | |
confidence = 0.0 | |
return { | |
'language_code': detected_lang, | |
'language_name': self.supported_languages.get(detected_lang, self.supported_languages.get('unknown')), | |
'confidence': confidence, | |
'scores': scores | |
} | |
except Exception as e: | |
logger.error(f"Dil algılama hatası: {str(e)}") | |
return { | |
'language_code': 'unknown', | |
'language_name': self.supported_languages.get('unknown'), | |
'confidence': 0.0, | |
'scores': {} | |
} | |
def detect_languages_batch(self, texts): | |
""" | |
Birden çok metnin dilini tespit eder | |
Args: | |
texts: Dilleri tespit edilecek metinler listesi | |
Returns: | |
list: Her metin için dil tespiti sonuçları | |
""" | |
results = [] | |
for text in texts: | |
result = self.detect_language(text) | |
results.append(result) | |
return results |