Merge origin/main

This commit is contained in:
Federico Olivares committed 2026-10-24 14:34:57 -03:00
commit 03bbefd484
11 files changed
+52 -52

No files matched your search

+5 -5
View File
@@ -31,11 +31,11 @@ const NAMES: &[&str] = &["cs_CZ", "cs-CZ", "cs"];
/// [`install_dictionary`], or an empty one when none is available (Czech spelling is off
/// then; see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.dict.get_or_insert(loaded).clone()
}
@@ -56,7 +56,7 @@ fn load_installed() -> AffixDict {
/// UTF-8), for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
slot.dict = Some(Arc::new(d));
slot.in_memory = true;
Ok(())
@@ -65,7 +65,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
slot.dict = None;
slot.in_memory = false;
}
@@ -75,7 +75,7 @@ pub fn reload_dictionary() {
/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a
/// matching file also happens to exist.
pub fn installed_path() -> Option<std::path::PathBuf> {
if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory {
if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory {
return None;
}
crate::hunspell::find(NAMES).map(|(_, dic)| dic)
+4 -4
View File
@@ -25,11 +25,11 @@ const NAMES: &[&str] = &["hr_HR", "hr-HR", "hr"];
/// [`install_dictionary`], or an empty one when none is available (Croatian spelling is off
/// then; see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.get_or_insert(loaded).clone()
}
@@ -51,14 +51,14 @@ fn load_installed() -> AffixDict {
/// UTF-8), for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the Hunspell `hr_HR` dictionary found in the dictionaries folder or the
+6 -6
View File
@@ -27,7 +27,7 @@ static LOAD_ERRORS: RwLock<Vec<(String, PathBuf, String)>> = RwLock::new(Vec::ne
/// Remember (or, for `Ok`, forget) why the dictionary `key` found at `dic` failed to load, and
/// hand the result back unchanged.
pub fn note_load<T>(key: &str, dic: &Path, result: Result<T, String>) -> Result<T, String> {
let mut errors = LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner());
let mut errors = LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner);
errors.retain(|(k, _, _)| k != key);
if let Err(e) = &result {
errors.push((key.to_string(), dic.to_path_buf(), e.clone()));
@@ -37,19 +37,19 @@ pub fn note_load<T>(key: &str, dic: &Path, result: Result<T, String>) -> Result<
/// Forget the load error of the dictionary `key` (none found, or it is about to be searched for again).
pub fn clear_load_error(key: &str) {
LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).retain(|(k, _, _)| k != key);
LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).retain(|(k, _, _)| k != key);
}
/// The `.dic` file and the reason of the last failed load of the dictionary `key`, if any.
pub fn load_error(key: &str) -> Option<(PathBuf, String)> {
LOAD_ERRORS.read().unwrap_or_else(|e| e.into_inner()).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone()))
LOAD_ERRORS.read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone()))
}
/// Search `dir` before the system locations (a "dictionaries folder" setting); `None` clears it.
/// Takes effect for dictionaries not loaded yet.
pub fn set_dictionary_dir(dir: Option<PathBuf>) {
*EXTRA_DIR.write().unwrap_or_else(|e| e.into_inner()) = dir;
LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).clear(); // they belong to the old search path
*EXTRA_DIR.write().unwrap_or_else(std::sync::PoisonError::into_inner) = dir;
LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).clear(); // they belong to the old search path
}
/// The LibreOffice extension directories a Hunspell dictionary name may live in: LibreOffice's
@@ -67,7 +67,7 @@ fn lo_ext_dirs(name: &str) -> Vec<String> {
/// language is being searched for, adds LibreOffice's extension folders for it (`dict-pt-BR`).
pub fn search_dirs(lo_exts: Option<&[String]>) -> Vec<PathBuf> {
let mut dirs: Vec<PathBuf> = Vec::new();
if let Some(d) = EXTRA_DIR.read().unwrap_or_else(|e| e.into_inner()).clone() {
if let Some(d) = EXTRA_DIR.read().unwrap_or_else(std::sync::PoisonError::into_inner).clone() {
dirs.push(d);
}
if cfg!(target_arch = "wasm32") {
+4 -4
View File
@@ -30,11 +30,11 @@ const CLITICS: &[&str] = &["se", "nya", "ku", "mu", "lah", "kah", "pun"];
/// [`install_dictionary`], or an empty one when none is available (Indonesian spelling is off
/// then; see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.get_or_insert(loaded).clone()
}
@@ -55,14 +55,14 @@ fn load_installed() -> AffixDict {
/// UTF-8), for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the Hunspell `id_ID` dictionary found in the dictionaries folder or the
+1 -1
View File
@@ -276,7 +276,7 @@ fn e_apostrophe(text: &str, ws: &[(usize, usize)], v: &mut Vec<Issue>) {
}
let mut after = text.get(*b..).unwrap_or("").chars();
let Some(ap) = after.next().filter(|&c| is_apostrophe(c)) else { continue };
let ends = after.next().is_none_or(|c| c.is_whitespace());
let ends = after.next().is_none_or(char::is_whitespace);
let quoted = text.get(..*a).and_then(|t| t.chars().next_back()).is_some_and(|c| is_apostrophe(c) || c == '‘');
if ends && !quoted {
v.push(issue(*a, *b + ap.len_utf8(), "«È» si scrive con l'accento, non con l'apostrofo".into(), vec!["È".into()]));
+4 -4
View File
@@ -34,11 +34,11 @@ const NAMES: &[&str] = &["it_IT", "it_CH", "it-IT", "it"];
/// [`install_dictionary`], or an empty one when none is available (Italian spelling is off
/// then; see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.get_or_insert(loaded).clone()
}
@@ -59,14 +59,14 @@ fn load_installed() -> AffixDict {
/// UTF-8), for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the Hunspell `it_IT` dictionary found in the dictionaries folder or the
+10 -10
View File
@@ -130,14 +130,14 @@ fn dictionary_key(w: &str) -> String {
/// Add a word to the user dictionary ("Add to Dictionary"). It applies to every language.
pub fn add_word(w: &str) {
if user_words().write().unwrap_or_else(|e| e.into_inner()).insert(dictionary_key(w)) {
if user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(dictionary_key(w)) {
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
}
}
/// Take a word out of the user dictionary (File › Options › Proofing). Returns whether it was there.
pub fn remove_word(w: &str) -> bool {
let removed = user_words().write().unwrap_or_else(|e| e.into_inner()).remove(&dictionary_key(w));
let removed = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).remove(&dictionary_key(w));
if removed {
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
}
@@ -152,7 +152,7 @@ fn ignored_words() -> &'static RwLock<HashSet<String>> {
/// Ignore a word everywhere until the app closes ("Ignore All"). Unlike [`add_word`] it isn't
/// part of the user dictionary: it is never listed, saved or loaded, as in Word.
pub fn ignore_word(w: &str) {
if ignored_words().write().unwrap_or_else(|e| e.into_inner()).insert(dictionary_key(w)) {
if ignored_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(dictionary_key(w)) {
DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed);
}
}
@@ -220,13 +220,13 @@ pub fn dictionary_generation() -> u64 {
/// the entries are kept ([`dictionary_key`]).
pub(crate) fn in_user_dictionary(lower: &str) -> bool {
let key = composed(lower);
user_words().read().unwrap_or_else(|e| e.into_inner()).contains(&*key)
|| ignored_words().read().unwrap_or_else(|e| e.into_inner()).contains(&*key)
user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(&*key)
|| ignored_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(&*key)
}
/// Words in the user dictionary.
pub fn user_dictionary() -> Vec<String> {
let mut v: Vec<String> = user_words().read().unwrap_or_else(|e| e.into_inner()).iter().cloned().collect();
let mut v: Vec<String> = user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().cloned().collect();
v.sort();
v
}
@@ -274,7 +274,7 @@ fn read_dictionary_file(path: &std::path::Path) -> Vec<String> {
/// never a panic and never an error that stops startup. Returns the words added.
pub fn load_user_dictionary(path: &std::path::Path) -> Vec<String> {
let words = read_dictionary_file(path);
let mut set = user_words().write().unwrap_or_else(|e| e.into_inner());
let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner);
let mut added = Vec::new();
for w in words {
if set.len() >= MAX_CUSTOM_WORDS {
@@ -300,7 +300,7 @@ pub fn save_user_dictionary(path: &std::path::Path, removed: &[String]) -> std::
let removed: HashSet<String> = removed.iter().map(|w| dictionary_key(w)).collect();
let on_disk = read_dictionary_file(path);
{
let mut set = user_words().write().unwrap_or_else(|e| e.into_inner());
let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner);
let mut changed = false;
for w in on_disk {
if set.len() >= MAX_CUSTOM_WORDS {
@@ -342,7 +342,7 @@ const COMMON: &str = "a an the and or but if of to in on at by for with from as
const EXTRA_EN: &str = include_str!("../../../assets/spelling/en-extra.txt");
fn extra_words() -> &'static HashSet<&'static str> {
static E: OnceLock<HashSet<&'static str>> = OnceLock::new();
static E: OnceLock<HashSet<&str>> = OnceLock::new();
E.get_or_init(|| EXTRA_EN.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')).collect())
}
@@ -943,7 +943,7 @@ fn grammar_en(text: &str, capital_first: bool) -> Vec<Issue> {
if gap == " "
&& (w0 == "an" || w0 == "An")
&& w1.chars().next().is_some_and(|c| c.is_alphabetic() && !"aeiouAEIOUhH".contains(c))
&& !w1.chars().all(|c| c.is_uppercase())
&& !w1.chars().all(char::is_uppercase)
{
v.push(Issue {
start: *a0,
+4 -4
View File
@@ -33,11 +33,11 @@ const NAMES: &[&str] = &["pl_PL", "pl-PL", "pl"];
/// [`install_dictionary`], or an empty one when none is available (Polish spelling is off then;
/// see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.get_or_insert(loaded).clone()
}
@@ -58,14 +58,14 @@ fn load_installed() -> AffixDict {
/// for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the installed Polish dictionary, searching the dictionaries folder and
+4 -4
View File
@@ -32,11 +32,11 @@ const NAMES: &[&str] = &["pt_BR", "pt-BR", "pt"];
/// [`install_dictionary`], or an empty one when none is available (Portuguese spelling is off
/// then; see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.get_or_insert(loaded).clone()
}
@@ -57,14 +57,14 @@ fn load_installed() -> AffixDict {
/// UTF-8), for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the installed Portuguese dictionary, searching the dictionaries folder and
+6 -6
View File
@@ -52,11 +52,11 @@ const NAMES: &[&str] = &["ru_RU", "ru-RU", "ru"];
/// [`install_dictionary`], or an empty one when none is available (Russian spelling is off then;
/// see [`has_dictionary`]).
pub fn dictionary() -> Arc<AffixDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
// Another thread (or an install) may have filled it meanwhile: that one wins.
slot.dict.get_or_insert(loaded).clone()
}
@@ -77,7 +77,7 @@ fn load_installed() -> AffixDict {
/// for example one the user picked. On error the current dictionary stays.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = AffixDict::from_hunspell(aff, dic, &[])?;
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
slot.dict = Some(Arc::new(d));
slot.in_memory = true;
Ok(())
@@ -86,7 +86,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
/// Forget the loaded dictionary, so the next check looks for an installed one again (after
/// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed).
pub fn reload_dictionary() {
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
slot.dict = None;
slot.in_memory = false;
}
@@ -96,7 +96,7 @@ pub fn reload_dictionary() {
/// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a
/// matching file also happens to exist.
pub fn installed_path() -> Option<std::path::PathBuf> {
if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory {
if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory {
return None;
}
crate::hunspell::find(NAMES).map(|(_, dic)| dic)
@@ -109,7 +109,7 @@ pub fn has_dictionary() -> bool {
/// Is `c` a letter of the Cyrillic script (the only one the Russian dictionary covers)?
pub(crate) fn is_cyrillic(c: char) -> bool {
matches!(c, '\u{0400}'..='\u{04FF}' | '\u{0500}'..='\u{052F}')
matches!(c, '\u{0400}'..='\u{052F}')
}
/// Particles joined to a word with a hyphen (`кто-то`, `где-нибудь`, `давай-ка`, `всё-таки`,
+4 -4
View File
@@ -30,11 +30,11 @@ const NAMES: &[&str] = &["tr_TR", "tr-TR", "tr"];
/// The Turkish dictionary: the installed Hunspell `tr_TR` (read on first use), one given with
/// [`install_dictionary`], or an empty one when none is available.
pub fn dictionary() -> Arc<TrDict> {
if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() {
if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() {
return d.clone();
}
let loaded = Arc::new(load_installed());
let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner());
let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner);
slot.get_or_insert(loaded).clone()
}
@@ -61,13 +61,13 @@ fn load_installed() -> TrDict {
/// Use this Turkish dictionary from now on.
pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> {
let d = TrDict::from_hunspell(aff, dic)?;
*DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d));
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d));
Ok(())
}
/// Reload the dictionary on next check.
pub fn reload_dictionary() {
*DICT.write().unwrap_or_else(|e| e.into_inner()) = None;
*DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None;
}
/// The `.dic` file of the Hunspell `tr_TR` dictionary found in the dictionaries folder or the