diff --git a/ROADMAP.md b/ROADMAP.md index 0134cc895..69827c208 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -138,6 +138,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm |---|---| | 2026-10-13 | Justified vertical page alignment (#1320): a section set to Justified spreads each page's paragraphs and tables from the top margin to the bottom one, as Word does, including the last page and pages ending in a manual page break. DOCX `w:vAlign="both"` opens as Justified (it showed centred) and saves back; `layout.verticalAlign` takes `justify`, and Page Setup has a Vertical alignment box | | 2026-10-13 | macOS shortcuts as in Word for Mac: ⌘⇧S Save As, ⌘⌥E Insert Endnote, ⌘⌥A New Comment, ⌃H Replace, ⌘⌥R collapse the ribbon | +| 2026-10-13 | The status bar flags a proofing language whose Hunspell dictionary isn't installed (Polish, Portuguese): "Polish (no dictionary)", with a tooltip naming the dictionary and where it is looked up (#1167) | | 2026-10-13 | A picture (or shape) set to Behind Text can be dragged over the text it overlaps, whether or not it was selected first, in the body and in a header/footer. The press becomes an object drag only after the pointer moves, so an ordinary click still places the text caret in the overlapping text. The UI regression tests cover In Front of Text too | | 2026-10-13 | Saving to DOCX keeps the watermark: it is written as Word's own text-watermark shape in every header, and a document without headers gains one to hold it (#1290) | | 2026-10-13 | DOCX files with Word's text watermark (Design › Watermark, a VML text shape in the headers) show it on every page on screen and in the PDF (#1290) | diff --git a/crates/proof/src/lib.rs b/crates/proof/src/lib.rs index 655beef1c..17a96bb9b 100644 --- a/crates/proof/src/lib.rs +++ b/crates/proof/src/lib.rs @@ -359,6 +359,28 @@ pub fn has_dictionary(lang: Option<&str>) -> bool { ProofLang::from_tag(lang).is_proofed() } +/// The Hunspell dictionary name (`pl_PL`, `pt_BR`) a proofing language needs but doesn't have +/// installed, for a status-bar hint (#1167). `None` when the language's dictionary is available, +/// or when it needs none (English has a built-in word list; unproofed languages aren't offered +/// one). Reads the dictionary once (it is cached afterwards). +pub fn missing_dictionary(lang: Option<&str>) -> Option<&'static str> { + match ProofLang::from_tag(lang) { + ProofLang::Pl => dictionary_needed(ProofLang::Pl, pl::has_dictionary()), + ProofLang::Pt => dictionary_needed(ProofLang::Pt, pt::has_dictionary()), + _ => None, + } +} + +/// The Hunspell name `lang` needs when `installed` is false; only Polish and Portuguese use one. +fn dictionary_needed(lang: ProofLang, installed: bool) -> Option<&'static str> { + match lang { + _ if installed => None, + ProofLang::Pl => Some("pl_PL"), + ProofLang::Pt => Some("pt_BR"), + _ => None, + } +} + /// Is `word` spelled correctly in the run's proofing language? A language without a dictionary /// can't be checked, so every word counts as correct (no red underlines for it). pub fn is_correct_for(word: &str, lang: Option<&str>) -> bool { @@ -782,6 +804,23 @@ fn starts_consonant_sound(w: &str) -> bool { #[cfg(test)] mod tests { + #[test] + fn missing_dictionary_is_named_only_for_hunspell_languages_without_one() { + assert_eq!(dictionary_needed(ProofLang::Pl, false), Some("pl_PL")); + assert_eq!(dictionary_needed(ProofLang::Pt, false), Some("pt_BR")); + assert_eq!(dictionary_needed(ProofLang::Pl, true), None); + assert_eq!(dictionary_needed(ProofLang::Pt, true), None); + for l in [ProofLang::En, ProofLang::Bg, ProofLang::Other] { + assert_eq!(dictionary_needed(l, false), None); + } + // Installed dictionaries and the built-in English list: no hint. + pl::test_dict::install(); + pt::test_dict::install(); + for tag in [Some("pl-PL"), Some("pt-BR"), Some("en-US"), Some("fr-FR"), None] { + assert_eq!(missing_dictionary(tag), None, "{tag:?}"); + } + } + use super::*; /// #1063: the dictionaries folder is searched before the system locations; the dictionaries diff --git a/crates/ui-egui/src/chrome.rs b/crates/ui-egui/src/chrome.rs index cf187a016..c057992ee 100644 --- a/crates/ui-egui/src/chrome.rs +++ b/crates/ui-egui/src/chrome.rs @@ -448,7 +448,16 @@ pub fn status_bar(app: &mut WordApp, ui: &mut Ui) { } // The language at the caret; a click sets the proofing language (Review › Language). let lang = crate::ribbon::caret_language(app); - let resp = st(ui, &lang).on_hover_text(tl!("Language")); + let missing = crate::ribbon::caret_missing_dictionary(app); + let shown = if missing.is_some() { crate::i18n::fmt(tl!("{language} (no dictionary)"), &[("language", &lang)]) } else { lang.clone() }; + let tip = match missing { + Some(name) => crate::i18n::fmt( + tl!("No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations."), + &[("language", &lang), ("name", name)], + ), + None => tl!("Language").to_string(), + }; + let resp = st(ui, &shown).on_hover_text(tip); egui::Popup::menu(&resp).show(|ui| { ui.set_min_width(200.0); crate::ribbon::language_menu(ui, app); diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index f6eb762ee..d5716a4de 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -458,6 +458,8 @@ Labels Етикети Landscape Пейзаж Language Език + {language} (no dictionary) {language} (няма речник) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Не е инсталиран правописен речник за {language}, затова текстът не се проверява. WordCraft търси речника Hunspell {name} в папката WORDCRAFT_DICTIONARIES и на обичайните места в системата. Lasso Ласо Last Column Последна колона Last commit Последно подаване diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 7dc96cccb..52544718f 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -619,6 +619,8 @@ Labels Štítky Landscape Na šířku Language Jazyk + {language} (no dictionary) {language} (bez slovníku) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Pro jazyk {language} není nainstalován žádný pravopisný slovník, proto se nekontroluje. WordCraft hledá slovník Hunspell {name} ve složce WORDCRAFT_DICTIONARIES a na obvyklých místech v systému. Large\nOperator Velký\noperátor Lasso Laso Last Column Poslední sloupec diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 0ec7b28fe..1d68a971e 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -456,6 +456,8 @@ Labels Etiketten Landscape Querformat Language Sprache + {language} (no dictionary) {language} (kein Wörterbuch) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Für {language} ist kein Rechtschreibwörterbuch installiert, daher wird die Sprache nicht geprüft. WordCraft sucht das Hunspell-Wörterbuch {name} im Ordner WORDCRAFT_DICTIONARIES und an den üblichen Systemorten. Lasso Lasso Last Column Letzte Spalte Last commit Letzter Commit diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 7c38faeee..7949ddca9 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -525,6 +525,8 @@ Labels Etiquetas Landscape Horizontal Language Idioma + {language} (no dictionary) {language} (sin diccionario) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. No hay un diccionario ortográfico instalado para {language}, así que no se revisa. WordCraft busca el diccionario Hunspell {name} en la carpeta WORDCRAFT_DICTIONARIES y en las ubicaciones habituales del sistema. Lasso Lazo Last Column Última columna Last commit Último commit diff --git a/crates/ui-egui/src/i18n/et.tsv b/crates/ui-egui/src/i18n/et.tsv index 31ec87cc6..15398bd9f 100644 --- a/crates/ui-egui/src/i18n/et.tsv +++ b/crates/ui-egui/src/i18n/et.tsv @@ -400,6 +400,8 @@ Labels Sildid Landscape Rõhtpaigutus Language Keel + {language} (no dictionary) {language} (sõnastik puudub) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Keele {language} õigekirjasõnastikku pole paigaldatud, seega seda ei kontrollita. WordCraft otsib Hunspelli sõnastikku {name} kaustast WORDCRAFT_DICTIONARIES ja tavalistest süsteemikohtadest. Lasso Lasso Last Column Viimane veerg Last commit Viimane commit diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index ac2eae730..f01867b9a 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -470,6 +470,8 @@ Labels Étiquettes Landscape Paysage Language Langue + {language} (no dictionary) {language} (pas de dictionnaire) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Aucun dictionnaire orthographique pour {language} n'est installé, la langue n'est donc pas vérifiée. WordCraft cherche le dictionnaire Hunspell {name} dans le dossier WORDCRAFT_DICTIONARIES et aux emplacements système habituels. Lasso Lasso Last Column Dernière colonne Last commit Dernier commit diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 469323e12..2b5553246 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -385,6 +385,8 @@ Labels Címkék Landscape Fekvő Language Nyelv + {language} (no dictionary) {language} (nincs szótár) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. A(z) {language} nyelvhez nincs telepítve helyesírási szótár, ezért nem ellenőrzi. A WordCraft a(z) {name} Hunspell-szótárat a WORDCRAFT_DICTIONARIES mappában és a szokásos rendszerhelyeken keresi. Lasso Lasszó Last Column Utolsó oszlop Last commit Utolsó commit diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 17a17e802..8dc27b47d 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -454,6 +454,8 @@ Labels Etichette Landscape Orizzontale Language Lingua + {language} (no dictionary) {language} (nessun dizionario) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Non è installato alcun dizionario ortografico per {language}, quindi non viene controllata. WordCraft cerca il dizionario Hunspell {name} nella cartella WORDCRAFT_DICTIONARIES e nelle posizioni di sistema abituali. Lasso Lazo Last Column Ultima colonna Last commit Ultimo commit diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index 096eeb508..57c7101e2 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -513,6 +513,8 @@ Labels ラベル Landscape 横 Language 言語 + {language} (no dictionary) {language}(辞書なし) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. {language}のスペルチェック辞書がインストールされていないため、チェックされません。WordCraft は Hunspell 辞書 {name} を WORDCRAFT_DICTIONARIES フォルダーと通常のシステムの場所から探します。 Lasso なげなわ Last Column 最後の列 Last commit 最後のコミット diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index 83e887f0d..9cc35de8d 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -376,6 +376,8 @@ Labels Etykiety Landscape Pozioma Language Język + {language} (no dictionary) {language} (brak słownika) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Nie zainstalowano słownika pisowni dla języka: {language}, więc tekst nie jest sprawdzany. WordCraft szuka słownika Hunspell {name} w folderze WORDCRAFT_DICTIONARIES i w typowych lokalizacjach systemowych. Lasso Lasso Last Column Ostatnia kolumna Last commit Ostatni commit diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 24d150f16..45b6c75d3 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -514,6 +514,8 @@ Labels Etiquetas Landscape Paisagem Language Idioma + {language} (no dictionary) {language} (sem dicionário) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Não há dicionário ortográfico instalado para {language}, então o texto não é verificado. O WordCraft procura o dicionário Hunspell {name} na pasta WORDCRAFT_DICTIONARIES e nos locais habituais do sistema. Lasso Laço Last Column Última coluna Last commit Último commit diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 12a1a3458..2e736fcbb 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -387,6 +387,8 @@ Labels Наклейки Landscape Альбомная Language Язык + {language} (no dictionary) {language} (нет словаря) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Орфографический словарь для языка «{language}» не установлен, поэтому текст не проверяется. WordCraft ищет словарь Hunspell {name} в папке WORDCRAFT_DICTIONARIES и в обычных системных расположениях. Lasso Лассо Last Column Последний столбец Last commit Последний коммит diff --git a/crates/ui-egui/src/i18n/sr-latn.tsv b/crates/ui-egui/src/i18n/sr-latn.tsv index d35caa79e..9bbef566a 100644 --- a/crates/ui-egui/src/i18n/sr-latn.tsv +++ b/crates/ui-egui/src/i18n/sr-latn.tsv @@ -561,6 +561,8 @@ Labels Nalepnice Landscape Položeno Language Jezik + {language} (no dictionary) {language} (nema rečnika) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Pravopisni rečnik za {language} nije instaliran, pa se tekst ne proverava. WordCraft traži Hunspell rečnik {name} u fascikli WORDCRAFT_DICTIONARIES i na uobičajenim sistemskim lokacijama. Lasso Laso Last Column Zadnja kolona Last commit Zadnji commit diff --git a/crates/ui-egui/src/i18n/sr.tsv b/crates/ui-egui/src/i18n/sr.tsv index 4edfc6b4a..1b247b5bc 100644 --- a/crates/ui-egui/src/i18n/sr.tsv +++ b/crates/ui-egui/src/i18n/sr.tsv @@ -565,6 +565,8 @@ Labels Налепнице Landscape Положено Language Језик + {language} (no dictionary) {language} (нема речника) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Правописни речник за {language} није инсталиран, па се текст не проверава. WordCraft тражи Hunspell речник {name} у фасцикли WORDCRAFT_DICTIONARIES и на уобичајеним системским локацијама. Lasso Ласо Last Column Задња колона Last commit Задњи commit diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 40dacff93..2c51a44e1 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -385,6 +385,8 @@ Labels Etiketler Landscape Yatay Language Dil + {language} (no dictionary) {language} (sözlük yok) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. {language} için yüklü bir yazım sözlüğü yok, bu yüzden denetlenmiyor. WordCraft, {name} Hunspell sözlüğünü WORDCRAFT_DICTIONARIES klasöründe ve olağan sistem konumlarında arar. Lasso Kement Last Column Son Sütun Last commit Son commit diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index e869a299a..8c305e2e1 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -528,6 +528,8 @@ Labels Етикетки Landscape Альбомна Language Мова + {language} (no dictionary) {language} (немає словника) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Орфографічний словник для мови «{language}» не встановлено, тому текст не перевіряється. WordCraft шукає словник Hunspell {name} у теці WORDCRAFT_DICTIONARIES та в звичайних системних розташуваннях. Lasso Ласо Last Column Останній стовпець Last commit Останній коміт diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 9aaeddc39..8b3cbf4f2 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -2614,3 +2614,7 @@ Existing File or Web Page Tệp hoặc trang web hiện có Link to: Liên kết tới: Place in This Document Vị trí trong tài liệu này + +# Missing dictionary on the status bar (#1441) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. Chưa cài từ điển chính tả cho {language}, nên ngôn ngữ này không được kiểm tra. WordCraft tìm từ điển Hunspell {name} trong thư mục WORDCRAFT_DICTIONARIES và ở các vị trí thông thường của hệ thống. + {language} (no dictionary) {language} (không có từ điển) diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 2d94a6779..1bc64bfdf 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -525,6 +525,8 @@ Labels 标签 Landscape 横向 Language 语言 + {language} (no dictionary) {language}(无词典) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. 未安装{language}的拼写词典,因此不会检查该语言。WordCraft 会在 WORDCRAFT_DICTIONARIES 文件夹和常见的系统位置查找 Hunspell 词典 {name}。 Lasso 套索 Last Column 最后一列 Last commit 最近提交 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 1248a60a1..483de8d54 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -514,6 +514,8 @@ Labels 標籤 Landscape 橫向 Language 語言 + {language} (no dictionary) {language}(無字典) + No spelling dictionary for {language} is installed, so it isn't checked. WordCraft looks for the Hunspell dictionary {name} in the WORDCRAFT_DICTIONARIES folder and in the usual system locations. 未安裝{language}的拼字字典,因此不會檢查該語言。WordCraft 會在 WORDCRAFT_DICTIONARIES 資料夾和常見的系統位置尋找 Hunspell 字典 {name}。 Lasso 套索 Last Column 最後一欄 Last commit 最近提交 diff --git a/crates/ui-egui/src/ribbon.rs b/crates/ui-egui/src/ribbon.rs index 1b79fe859..7be3ff317 100644 --- a/crates/ui-egui/src/ribbon.rs +++ b/crates/ui-egui/src/ribbon.rs @@ -635,6 +635,11 @@ fn caret_lang_tag(app: &WordApp) -> Option { s.doc.styles.resolve_char(style.as_deref(), &s.typing_props()).lang } +/// The Hunspell dictionary the caret's language needs but doesn't have (`pl_PL`), if any (#1167). +pub(crate) fn caret_missing_dictionary(app: &WordApp) -> Option<&'static str> { + wordcraft_engine::proof::missing_dictionary(caret_lang_tag(app).as_deref()) +} + /// Review › Language (and the status bar's language): set the selection's proofing language, or /// leave it unchecked. The current choice has a check mark; a language outside the short list /// (French, German…) shows checked above it. Set Proofing Language… opens the Language dialog