Proofing: status bar flags a language whose dictionary isn't installed (#1167) (#1441)

* Proofing: status bar flags a language whose dictionary isn't installed (#1167)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* vi: missing-dictionary status strings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
This commit is contained in:
Valentin Klein
2026-10-14 19:32:30 -04:00
committed by GitHub
co-authored by Claude Sonnet 5.5 Brandon Thomas
parent aec3f50582
commit bbdcc7c62f
23 changed files with 95 additions and 1 deletions
+1
View File
@@ -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) |
+39
View File
@@ -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
+10 -1
View File
@@ -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);
+2
View File
@@ -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 Последно подаване
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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
1 # Estonian (et) interface catalog. Columns separated by a TAB:
400
401
402
403
404
405
406
407
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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 最後のコミット
1 # Japanese (ja) interface catalog. Same format and clean-room rules as zh-hans.tsv.
513
514
515
516
517
518
519
520
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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 Последний коммит
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 25.
+2
View File
@@ -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
Can't render this file because it contains an unexpected character in line 11 and column 25.
+2
View File
@@ -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
1 # Turkish (tr) interface catalog. Columns, separated by a TAB:
385
386
387
388
389
390
391
392
+2
View File
@@ -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 Останній коміт
Can't render this file because it contains an unexpected character in line 6 and column 31.
+4
View File
@@ -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)
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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 最近提交
Can't render this file because it contains an unexpected character in line 7 and column 25.
+2
View File
@@ -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 最近提交
1 # Traditional Chinese (zh-hant, Taiwan vocabulary) interface catalog. Same format and clean-room
514
515
516
517
518
519
520
521
+5
View File
@@ -635,6 +635,11 @@ fn caret_lang_tag(app: &WordApp) -> Option<String> {
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