1+ #Multilingual spell-checking auto for searches only if online lanuage correct avalible.
2+ #Supports: English-French-Spanish-Portuguese-Italian-Dutch-German-Polish-Russian ONLY
3+ from functools import lru_cache
4+ import re
5+ from typing import Any , Optional
6+ from language_tool_python .utils import correct
7+ try :
8+ import language_tool_python as lt
9+ from language_tool_python import utils
10+ LANGUAGE_TOOL_AVAILABLE = True
11+ except Exception :
12+ LANGUAGE_TOOL_AVAILABLE = False
13+ lt = None
14+ utils = None
15+
16+ #Supports: ONLY Ukrainian via SymSpell
17+ # Optional Ukrainian fallback (SymSpell)
18+ try :
19+ from symspellpy import SymSpell , Verbosity
20+ SYM_AVAILABLE = True
21+ except Exception :
22+ SYM_AVAILABLE = False
23+
24+ # Detect Ukrainian letters
25+ UKRAINIAN_CHARS = re .compile (r"[іІїЇєЄґҐ]" )
26+
27+ # Build minimal SymSpell for Ukrainian ONLY if installed
28+ sym_uk = None
29+ if SYM_AVAILABLE :
30+ sym_uk = SymSpell (max_dictionary_edit_distance = 2 , prefix_length = 7 )
31+ # minimal tiny dictionary
32+ base_uk = [
33+ "привіт" , "слово" , "текст" , "книга" ,
34+ "переклад" , "мова" , "будинок" , "вікно"
35+ ]
36+ for w in base_uk :
37+ sym_uk .create_dictionary_entry (w , 5 )
38+
39+ class SpellChecker :
40+ """
41+ Wraps LanguageTool with caching and safe fallbacks.
42+ Supports languages auto with 'multilingual' mode.
43+ """
44+
45+ def __init__ (self ):
46+ if LANGUAGE_TOOL_AVAILABLE :
47+ try :
48+ # Load ONCE → slow the first time, fast after
49+ self .tool = lt .LanguageTool ("multilingual" )
50+ except Exception :
51+ self .tool = None
52+ else :
53+ self .tool = None
54+
55+ @lru_cache (maxsize = 500 )
56+ def correct (self , text : str ) -> str :
57+ """Return corrected text, cached for speed."""
58+ if not text or not self .tool :
59+ return text
60+
61+ try :
62+ matches = self .tool .check (text )
63+ if not matches :
64+ return text
65+ return utils .correct (text , matches ) if utils else text
66+ except Exception :
67+ # If LanguageTool fails → return original text
68+ return text
69+
70+
71+ # GLOBAL instance so admin.py doesn't reload it each time
72+ SPELL_CHECKER = SpellChecker ()
73+
74+
75+ def auto_correct (text : str ) -> str :
76+ """
77+ Public helper function for admin.py
78+ """
79+ return SPELL_CHECKER .correct (text )
0 commit comments