fix(dictionary): strip Latin romanization debris from Russian translations and sanitize dictionary cache
This commit is contained in:
1 parent
e371cdd4e5
commit
52db766b23
7 files changed
+109
-27
No files matched your search
+58
-3
@@ -223,6 +223,60 @@ async def fetch_free_dictionary_api(word: str, client: Optional[httpx.AsyncClien
|
||||
pass
|
||||
return {"phonetic": None, "audio_url": None}
|
||||
|
||||
def clean_russian_translation(text: str) -> str:
|
||||
"""
|
||||
Cleans up Russian translations by stripping Latin romanization / phonetic debris
|
||||
(e.g. 'át’sjaпорхать át’/', 'krýl’jami/', 'ževáto-koríčnevyj/', '] ]/]')
|
||||
and restoring clean, deduplicated Cyrillic phrases, while preserving grammatical notes.
|
||||
"""
|
||||
if not text:
|
||||
return ""
|
||||
|
||||
# Protect grammatical notes like (прош. вр. от go), (3-е л. ед. ч. от flutter)
|
||||
notes = []
|
||||
def save_note(m):
|
||||
notes.append(m.group(0))
|
||||
return f"«ПРИМЕЧАНИЕ_{len(notes)-1}»"
|
||||
|
||||
s = re.sub(r"\([а-яА-ЯёЁ0-9\s.,-]*\bот\s+[a-zA-Z\x27-]+\)", save_note, text)
|
||||
|
||||
# 1. Clean out brackets junk and stray backslashes
|
||||
s = re.sub(r"\[+[\s\]/\\,;]*\]*", " ", s)
|
||||
s = re.sub(r"[\]\[\\]+", " ", s)
|
||||
|
||||
# 2. Match Latin romanization fragments with accents/slashes/apostrophes
|
||||
latin_rom = r"[a-zA-Z\u00C0-\u024F\u1E00-\u1EFF\x27\u2019/]+"
|
||||
s = re.sub(rf"\s*{latin_rom}\s*", ", ", s)
|
||||
|
||||
# 3. Clean up multiple commas/semicolons
|
||||
s = re.sub(r"[,;\s]*,[,;\s]*", ", ", s)
|
||||
|
||||
# 4. Clean and deduplicate phrases
|
||||
items = []
|
||||
seen = set()
|
||||
for part in s.split(","):
|
||||
p = part.strip(" /\\,;-\x27\u2019")
|
||||
if p.count("(") > p.count(")"):
|
||||
p += ")"
|
||||
elif p.count(")") > p.count("("):
|
||||
p = re.sub(r"\)+$", "", p).strip()
|
||||
p = re.sub(r"\s+", " ", p)
|
||||
for idx, n in enumerate(notes):
|
||||
token = f"«ПРИМЕЧАНИЕ_{idx}»"
|
||||
if token in p:
|
||||
p = p.replace(token, n).strip()
|
||||
if p and re.search(r"[\u0400-\u04FF0-9]", p):
|
||||
p_lower = p.lower()
|
||||
if p_lower not in seen:
|
||||
seen.add(p_lower)
|
||||
items.append(p)
|
||||
|
||||
res = ", ".join(items) if items else text.strip()
|
||||
for idx, n in enumerate(notes):
|
||||
res = res.replace(f"«ПРИМЕЧАНИЕ_{idx}»", n)
|
||||
return res
|
||||
|
||||
|
||||
async def lookup_term(query: str) -> Dict[str, Any]:
|
||||
query_clean = query.strip()
|
||||
if not query_clean:
|
||||
@@ -251,13 +305,14 @@ async def lookup_term(query: str) -> Dict[str, Any]:
|
||||
).fetchone()
|
||||
if off_row:
|
||||
raw_trans = off_row["translation"] or ""
|
||||
tr_list = [t.strip() for t in raw_trans.split(",") if t.strip()]
|
||||
clean_trans = clean_russian_translation(raw_trans)
|
||||
tr_list = [t.strip() for t in clean_trans.split(",") if t.strip()]
|
||||
res = {
|
||||
"query": query_clean,
|
||||
"is_sentence": False,
|
||||
"translation": raw_trans,
|
||||
"translation": clean_trans,
|
||||
"translations_list": tr_list,
|
||||
"translation_ru": raw_trans,
|
||||
"translation_ru": clean_trans,
|
||||
"phonetic": off_row["phonetic"] or "",
|
||||
"audio_file": "",
|
||||
"audio_url": "",
|
||||
|
||||
Reference in new issue
Block a user