Merge PR #1076: i18n: add Slovenian (sl) interface translation

i18n: registry holds 27 languages (sl after nl, da, ro); audit.rs and the Polish test list sl beside pl and ro; tests: both sides kept. Docs: language counts and lists name ro, sl, nl and da; status entries prepended to main's lines.
This commit is contained in:
aiongg
2026-10-22 01:53:21 +00:00
9 changed files with 2812 additions and 16 deletions
+1
View File
@@ -76,6 +76,7 @@ Generated-in-code art is original and has no file to list: the UI icon set (`cra
| `crates/ui-egui/src/i18n/ru.tsv` | Dmitrii Khlapov with Claude | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Russian interface catalog; reviewed by a native speaker |
| `crates/ui-egui/src/i18n/tr.tsv` | @PbyLoyth with Codex and Claude Code | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Turkish interface catalog |
| `crates/ui-egui/src/i18n/bg.tsv` | Dimitar Klaturov (@bulgariamitko) with Claude Code | Original translation from the English interface labels in this repository; no other product localisation or other catalog used | MIT OR Apache-2.0 | Bulgarian interface catalog |
| `crates/ui-egui/src/i18n/sl.tsv` | Filip Strajnar with Grok Bot | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Slovenian interface catalog |
| `crates/ui-egui/src/i18n/hu.tsv` | @Skaywalker | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Hungarian interface catalog |
| `crates/ui-egui/src/i18n/fr.tsv` | @pechnikov2026-star | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | French interface catalog |
| `crates/ui-egui/src/i18n/sv.tsv` | Erik Holmbom (@holmbom) with Claude Code | Original translation from the English interface labels in this repository; no other product localisation or other catalog used | MIT OR Apache-2.0 | Swedish interface catalog; AI-assisted, terminology and the running app reviewed by a native speaker |
+1 -1
View File
@@ -120,7 +120,7 @@ Every screenshot below is WordCraft itself, rendered offscreen by its own UI tes
| **References** | Table of contents, footnotes and endnotes, citations and bibliography (APA, MLA, Chicago, IEEE), captions, table of figures, cross-references, index, table of authorities |
| **Review** | Spelling and grammar with suggestions (English and Polish, by each run's language), thesaurus, word count, comments in margin balloons or a pane, track changes, accept/reject, compare documents, restrict editing, accessibility checker, document inspector |
| **Mailings** | Mail merge from CSV, merge fields, address block, greeting line, rules, preview, finish to a document; envelopes and labels |
| **View** | Print layout, web layout, draft, read mode, focus, zoom, one/multiple pages, page width, Navigation pane, rulers, gridlines, dark mode; interface in English, 简体中文, 繁體中文, 日本語, Português (Brasil), Español, Українська, Српски / Srpski, Eesti, Türkçe, Русский, Italiano, Deutsch, Polski, Čeština, Magyar, Français, Български, Tiếng Việt, 한국어 or Svenska (follows the system language by default) |
| **View** | Print layout, web layout, draft, read mode, focus, zoom, one/multiple pages, page width, Navigation pane, rulers, gridlines, dark mode; interface in English, 简体中文, 繁體中文, 日本語, Português (Brasil), Español, Українська, Српски / Srpski, Eesti, Türkçe, Русский, Italiano, Deutsch, Polski, Čeština, Magyar, Français, Български, Tiếng Việt, 한국어, Svenska, Hrvatski or Slovenščina (follows the system language by default) |
| **Files** | .docx read/write, legacy 97-2003 .doc import, PDF export, .odt, .rtf, .html, .md, .tex, .txt import/export, page images |
The honest picture, area by area, is in [ROADMAP.md](ROADMAP.md), the
+4 -3
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -340,9 +340,9 @@ fn untranslated_interface_text() {
complete_catalogs_have_every_string_the_interface_looked_up(pseudo::looked_up());
}
/// Russian, Hungarian, Turkish, Bulgarian, Italian, Swedish, Croatian and Polish cover everything the
/// audit saw translated, plus the equation gallery's labels (shown in menus the audit doesn't open
/// one by one). Numbered style names go through a template.
/// Russian, Hungarian, Turkish, Bulgarian, Italian, Swedish, Croatian, Polish and Slovenian cover
/// everything the audit saw translated, plus the equation gallery's labels (shown in menus the
/// audit doesn't open one by one). Numbered style names go through a template.
fn complete_catalogs_have_every_string_the_interface_looked_up(mut keys: std::collections::BTreeSet<String>) {
use wordcraft_engine::math_gallery::{BUILT_INS, STRUCTURES, SYMBOL_SETS};
keys.extend(BUILT_INS.iter().map(|(_, label, _)| label.to_string()));
@@ -388,7 +388,7 @@ fn complete_catalogs_have_every_string_the_interface_looked_up(mut keys: std::co
// translate: its placeholder names aren't words the interface shows.
let words = |s: &str| english_words(&s.split('{').map(|p| p.split_once('}').map_or(p, |(_, rest)| rest)).collect::<String>());
let mut report = String::new();
for code in ["ru", "hu", "tr", "bg", "it", "sv", "hr", "pl"] {
for code in ["ru", "hu", "tr", "bg", "it", "sv", "hr", "pl", "sl"] {
let lang = super::Lang::from_code(code).unwrap_or(super::Lang::EN);
let missing: Vec<&String> =
keys.iter().filter(|s| words(s) && !super::has(lang, s) && !numbered(s) && !same(s) && !script_error(s)).collect();
+3 -1
View File
@@ -52,7 +52,7 @@ pub struct LangInfo {
}
/// The registry. English first: it is the fallback and the source language.
pub static LANGUAGES: [LangInfo; 26] = [
pub static LANGUAGES: [LangInfo; 27] = [
LangInfo { code: "en", name: "English", source: "", prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
// Simplified Chinese; `zh`, `zh-CN`, `zh-SG` and `zh-Hans-*` resolve here (see `candidates`).
LangInfo {
@@ -171,6 +171,8 @@ pub static LANGUAGES: [LangInfo; 26] = [
LangInfo { code: "da", name: "Dansk", source: include_str!("da.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
// Romanian; `ro`, `ro-RO`, `ro_RO.UTF-8` and `ro-MD` resolve here.
LangInfo { code: "ro", name: "Română", source: include_str!("ro.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
// Slovenian; `sl`, `sl-SI` and `sl_SI.UTF-8` resolve here.
LangInfo { code: "sl", name: "Slovenščina", source: include_str!("sl.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
];
impl LangInfo {
File diff suppressed because it is too large Load Diff
+93 -1
View File
@@ -1004,11 +1004,12 @@ fn polish_covers_every_key_of_every_other_catalog() {
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
let polish = keys(lang("pl").0.source);
// Italian and Hungarian still carry "Style: APA", which the interface no longer shows;
// Slovenian carries the union of every catalog's keys.
// Hungarian and Bulgarian also name the citation styles, and Bulgarian has a few one-line
// pieces of gallery labels. Polish matches every other catalog, including the built-in style
// names, citation styles and equation gallery. French carries newer strings (paper sizes,
// bookmarks, printing) the Polish catalog hasn't caught up with yet.
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "it" | "hu" | "bg" | "vi" | "sv" | "hr" | "fr" | "ro")) {
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "it" | "hu" | "bg" | "vi" | "sv" | "hr" | "fr" | "ro" | "sl")) {
let mut missing: Vec<String> = keys(other.0.source).difference(&polish).cloned().collect();
missing.sort();
assert!(missing.is_empty(), "pl lacks {}'s {missing:?}", other.code());
@@ -1645,3 +1646,94 @@ fn bundled_interface_fonts_cover_romanian_without_system_fallbacks() {
}
}
}
#[test]
fn slovenian_locales_and_saved_preference_work_without_changing_the_document() {
let sl = lang("sl");
for tag in ["sl", "sl-SI", "sl_SI.UTF-8", "SL-si", "sl-Latn-SI"] {
assert_eq!(lang_from_tag(tag), Some(sl), "{tag}");
}
assert_eq!(first_supported([UNSUPPORTED, "sl-SI", "en-US"]), Some(sl));
let mut app = crate::WordApp::new(wordcraft_engine::Session::new(wordcraft_doc::Document::new()), Default::default());
let before = serde_json::to_value(&app.session.doc).unwrap();
let result = app.run("ui.language", serde_json::json!({"value": "SL"})).unwrap();
assert_eq!(result["effective"], "sl");
assert_eq!(app.ui.language, "sl");
assert!(result["available"].as_array().unwrap().iter().any(|l| l["code"] == "sl" && l["name"] == "Slovenščina"));
assert_eq!(serde_json::to_value(&app.session.doc).unwrap(), before);
let saved = serde_json::to_string(&app.ui).unwrap();
let restored: crate::UiState = serde_json::from_str(&saved).unwrap();
assert_eq!(Lang::from_pref(&restored.language), sl);
}
#[test]
fn slovenian_covers_every_key_of_every_other_catalog() {
use std::collections::HashSet;
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
let slovenian = keys(lang("sl").0.source);
assert!(parse_entries(lang("sl").0.source).1.is_empty());
for other in Lang::all().filter(|l| *l != Lang::EN && l.code() != "sl") {
let mut missing: Vec<String> = keys(other.0.source).difference(&slovenian).cloned().collect();
missing.sort();
// Italian and Hungarian still carry "Style: APA", which the interface no longer shows.
missing.retain(|k| k != "Style: APA" || !matches!(other.code(), "it" | "hu"));
assert!(missing.is_empty(), "sl lacks {}'s {missing:?}", other.code());
}
let sl = lang("sl");
for (source, expected) in [
("File", "Datoteka"),
("Home", "Osnovno"),
("Insert", "Vstavljanje"),
("Layout", "Postavitev"),
("References", "Sklici"),
("Review", "Pregled"),
("View", "Pogled"),
("Save", "Shrani"),
("Bold", "Krepko"),
("Italic", "Ležeče"),
("Underline", "Podčrtano"),
("Track Changes", "Sledenje spremembam"),
("Insert Citation", "Vstavi citat"),
("Citations", "Citati"),
("unknown future label", "unknown future label"),
] {
assert_eq!(tr(sl, source), expected, "{source}");
}
// The search hint's example must find the command it names.
assert_eq!(tr(sl, "Insert Table"), "Vstavi tabelo");
assert!(tr(sl, "Type a command, e.g. \"insert table\"").contains("vstavi tabelo"));
assert_eq!(fmt(tr(sl, "Page {page} of {pages}"), &[("page", "3"), ("pages", "9")]), "Stran 3 od 9");
// Count-neutral wording is grammatical for every count (Slovenian has singular, dual and plural).
for count in [0, 1, 2, 3, 5, 101, 102] {
let words = count.to_string();
assert_eq!(fmt(tr(sl, "{words} words"), &[("words", &words)]), format!("Besede: {count}"));
assert_eq!(fmt(tr(sl, "{selected} of {words} words"), &[("selected", "1"), ("words", &words)]), format!("Besede: 1 od {count}"));
}
}
#[test]
fn bundled_interface_fonts_cover_slovenian_letters() {
let db = wordcraft_fonts::FontDb::with_font_dirs(Vec::new());
for (family, style) in [("Inter", "Regular"), ("Inter", "Medium"), ("Inter", "SemiBold"), ("JetBrains Mono", "Regular")] {
let face = db.face(family, style);
assert_eq!(face.family, family, "must use the bundled interface face");
for ch in "ČčŠšŽž»«–…".chars() {
assert_ne!(face.glyph_for(ch), 0, "{family} {style} lacks {ch}");
}
}
assert!(!lang("sl").uses_cjk());
}
#[test]
fn slovenian_has_no_keys_outside_the_other_catalogs() {
use std::collections::HashSet;
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
let slovenian = keys(lang("sl").0.source);
let mut union = HashSet::new();
for other in Lang::all().filter(|l| *l != Lang::EN && l.code() != "sl") {
union.extend(keys(other.0.source));
}
let mut extra: Vec<String> = slovenian.difference(&union).cloned().collect();
extra.sort();
assert!(extra.is_empty(), "sl has {} keys no other catalog has: {extra:?}", extra.len());
}
+10 -6
View File
@@ -1,6 +1,6 @@
# Localization parity with Microsoft Word
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** minor (Romanian interface catalog; previously trivial: the File › Home greeting is translated in every catalog; previously trivial: Japanese row: ruby (Phonetic Guide) is supported and HTML export/import keeps it, #1681; previously trivial: Russian sorting keeps ё with е and recognises decomposed ё/й; previously minor: English dialects: en-GB, en-CA, en-AU and the other British-spelling Englishes proof their own spellings and flag the other dialect's, #1281, #1045; previously minor: how to install the Hunspell dictionaries on Windows, macOS and Linux: `docs/spelling-dictionaries.md`; previously minor: Read Aloud speaks each sentence in its own language, #1843; previously minor: Indonesian proofing: id-ID spelling from the installed Hunspell dictionary, dictionary-driven suggestions, generic checks with Indonesian messages, #498; previously trivial: print-area strings translated in every catalog; previously trivial: Italian: the interface audit checks the Italian catalog, `Privacy Settings` wording; previously trivial: Italian grammar: `po'`, `qual è`, `È`, `un`/`un'` rules; more elisions and truncations in spelling; previously trivial: Czech interface catalog completed, 2,447 entries; previously trivial: interface audit runs in CI again: size labels translated, 20 strings in every catalog, Read Aloud error race fixed, #1128; previously trivial: Review › Language reaches every language again — Set Proofing Language… and Set As Default, #860; previously minor: Italian proofing: it-IT spelling from the installed Hunspell dictionary, accent-first suggestions, conservative grammar with Italian messages; previously minor: Portuguese proofing; previously trivial: Turkish interface catalog completed, 2,325 entries, #774; previously minor: Hungarian interface added; previously trivial: sorting and table numbers follow the text's language, #836, #837; previously minor: Polish interface; Polish proofing — spelling, grammar, hyphenation — and a proofing language per run; previously minor: Turkish interface added; previously major: first version; catalogs measured from `crates/ui-egui/src/i18n`, Word's languages from its bundle listing) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-21 · **Change:** trivial (Slovenian interface catalog: every key of every other catalog, 2,614 entries; previously minor: Romanian interface catalog; previously trivial: the File › Home greeting is translated in every catalog; previously trivial: Japanese row: ruby (Phonetic Guide) is supported and HTML export/import keeps it, #1681; previously trivial: Russian sorting keeps ё with е and recognises decomposed ё/й; previously minor: English dialects: en-GB, en-CA, en-AU and the other British-spelling Englishes proof their own spellings and flag the other dialect's, #1281, #1045; previously minor: how to install the Hunspell dictionaries on Windows, macOS and Linux: `docs/spelling-dictionaries.md`; previously minor: Read Aloud speaks each sentence in its own language, #1843; previously minor: Indonesian proofing: id-ID spelling from the installed Hunspell dictionary, dictionary-driven suggestions, generic checks with Indonesian messages, #498; previously trivial: print-area strings translated in every catalog; previously trivial: Italian: the interface audit checks the Italian catalog, `Privacy Settings` wording; previously trivial: Italian grammar: `po'`, `qual è`, `È`, `un`/`un'` rules; more elisions and truncations in spelling; previously trivial: Czech interface catalog completed, 2,447 entries; previously trivial: interface audit runs in CI again: size labels translated, 20 strings in every catalog, Read Aloud error race fixed, #1128; previously trivial: Review › Language reaches every language again — Set Proofing Language… and Set As Default, #860; previously minor: Italian proofing: it-IT spelling from the installed Hunspell dictionary, accent-first suggestions, conservative grammar with Italian messages; previously minor: Portuguese proofing; previously trivial: Turkish interface catalog completed, 2,325 entries, #774; previously minor: Hungarian interface added; previously trivial: sorting and table numbers follow the text's language, #836, #837; previously minor: Polish interface; Polish proofing — spelling, grammar, hyphenation — and a proofing language per run; previously minor: Turkish interface added; previously major: first version; catalogs measured from `crates/ui-egui/src/i18n`, Word's languages from its bundle listing) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
Interface languages, script support and proofing per language. How translation works (catalog
format, adding a language, clean-room rule): `crates/ui-egui/src/i18n/mod.rs`.
@@ -19,9 +19,9 @@ native-speaker review (human).
## What WordCraft ships (measured)
- **24 interface languages**: English plus `zh-hans`, `zh-hant`, `ja`, Korean `ko` (#1216), `uk`, `es`, `pt-br`,
Serbian `sr`/`sr-latn` (#250), Estonian `et`, Turkish `tr`, Russian `ru`, Italian `it` (#594), German `de` (#574), Polish `pl`, Czech `cs`, Hungarian `hu`, French `fr`, Bulgarian `bg`, Vietnamese `vi` (#1434), Swedish `sv` (#1219), Croatian `hr` (#1271) and Romanian `ro`. Catalogs have 2,061–2,674 entries
each; Polish has every key of every other catalog, including the built-in style names and the equation gallery, except the citation style names only Hungarian, Bulgarian, Swedish and Romanian translate so far (a test checks it). A test (`every_tab_and_command_is_translated`) enforces that every ribbon tab, command
- **27 interface languages**: English plus `zh-hans`, `zh-hant`, `ja`, Korean `ko` (#1216), `uk`, `es`, `pt-br`,
Serbian `sr`/`sr-latn` (#250), Estonian `et`, Turkish `tr`, Russian `ru`, Italian `it` (#594), German `de` (#574), Polish `pl`, Czech `cs`, Hungarian `hu`, French `fr`, Bulgarian `bg`, Vietnamese `vi` (#1434), Swedish `sv` (#1219), Croatian `hr` (#1271), Romanian `ro`, Slovenian `sl`, Dutch `nl` and Danish `da` (#2722). Catalogs have 2,061–2,674 entries
each; Polish has every key of every other catalog, including the built-in style names and the equation gallery, except the citation style names only Hungarian, Bulgarian, Swedish, Romanian and Slovenian translate so far (a test checks it). A test (`every_tab_and_command_is_translated`) enforces that every ribbon tab, command
label and ribbon location is translated in every language.
`pl`, `pl-PL` and `pl_PL.UTF-8` system locales pick Polish automatically.
- Of the 675 English strings a scan extracts from `tl!(…)` calls and command labels/locations, each
@@ -60,8 +60,8 @@ shared items below.
| Vietnamese | vi | 2,448 entries; every key of the reference catalogs (#1434); 98% of extracted, ~95% of visible | most | Latin ✅ | no | partial | 0–1 (review) |
| Romanian | ro | 2,674 entries; every key of the other catalogs; AI-assisted draft | most | Latin ✅ (ă â î ș ț in the bundled faces) | no | partial | 0–1 (review) |
Other shipped languages: **17** — Traditional Chinese (`zh-hant`), Ukrainian (`uk`), Serbian
Cyrillic and Latin (`sr`, `sr-latn`, #250), Estonian (`et`), Turkish (`tr`), Russian (`ru`), Italian (`it`, #594), Polish (`pl`), Czech (`cs`), Hungarian (`hu`), French (`fr`), Bulgarian (`bg`), Vietnamese (`vi`, #1434), Swedish (`sv`, #1219), Croatian (`hr`, #1271) and Romanian (`ro`), all partial.
Other shipped languages: **20** — Traditional Chinese (`zh-hant`), Ukrainian (`uk`), Serbian
Cyrillic and Latin (`sr`, `sr-latn`, #250), Estonian (`et`), Turkish (`tr`), Russian (`ru`), Italian (`it`, #594), Polish (`pl`), Czech (`cs`), Hungarian (`hu`), French (`fr`), Bulgarian (`bg`), Vietnamese (`vi`, #1434), Swedish (`sv`, #1219), Croatian (`hr`, #1271), Romanian (`ro`), Slovenian (`sl`), Dutch (`nl`) and Danish (`da`, #2722), all partial.
Swedish (`sv-SE` and `sv-FI` system locales, `{"value":"sv"}`) has 2,504 entries. Counts use
count-neutral wording (`{words} ord`: the noun is the same in the singular and the plural). The
catalog is an AI-assisted draft whose terminology and running app were reviewed by a native
@@ -79,6 +79,9 @@ Bulgarian (`bg-BG` system locales, `{"value":"bg"}`) has 2,419 entries: every ke
catalog, the equation gallery's labels and everything the interface audit finds (the audit checks
Bulgarian as it does Russian). Counts use count-neutral wording (`Думи: 21`). Bulgarian text is
hyphenated by the Bulgarian syllable rules (#826); Bulgarian spelling and grammar are not included.
Slovenian (`sl-SI` system locales, `{"value":"sl"}`) has 2,614 entries: every key of every other
catalog. Counts use count-neutral wording (`Besede: 21`); terminology: [`localization-sl.md`](localization-sl.md).
Slovenian proofing is not included.
Hungarian follows `hu-HU` system locales and `{"value":"hu"}`, with a complete catalog of 2,419 entries: every key of
the Russian catalog, built-in style names shown translated, plus the citation style names. Hungarian proofing is not included; terminology and conventions:
[`localization-hu.md`](localization-hu.md).
@@ -246,6 +249,7 @@ WordCraft keeps 2,54 cm).
| 2026-10-11 | minor | Font list shows installed fonts by their names in the interface language (宋体 for SimSun in Chinese, Japanese and Korean names likewise) and finds them by either name; a Chinese, Japanese or Korean font is stored as `w:eastAsia` too (#505) |
| 2026-10-11 | minor | Chinese/Japanese interface fonts: a test checks every catalog character has a glyph; an installed CJK font follows the embedded faces whenever they miss one; macOS font asset folders searched for PingFang (#486) |
| 2026-10-10 | minor | Russian interface (#300; 1,524 entries, built-in style names shown translated; covers everything the interface audit finds) |
| 2026-10-15 | trivial | Slovenian interface catalog (2,614 entries: every key of every other catalog), locale selection, saved preference and font checks |
| 2026-10-12 | minor | Bulgarian interface catalog (2,419 entries), locale selection, saved preference, audit coverage and font checks |
| 2026-10-19 | minor | Romanian interface catalog (2,674 entries), `ro-*` system locales, saved preference and font coverage checks; no Romanian proofing |
| 2026-10-13 | minor | Croatian interface catalog (2,507 entries, built-in style names shown translated), `hr-*` system locales, saved preference and font coverage checks; the template name "Letter" has its own `template` context so the paper size keeps its name; no Croatian proofing |
+63
View File
@@ -0,0 +1,63 @@
# Slovenian interface
> **Last reviewed:** 2026-10-15 · **Last updated:** 2026-10-15 · **Change:** trivial (catalog completed to every key of every other catalog, 2,614 entries) · **Target:** WordCraft 0.7.0
Choose **File › Options › Interface language › Slovenščina**, or follow a Slovenian system display
language (`sl-SI`, `sl_SI.UTF-8`). The catalog code is `sl`; `ui.language` with `{"value":"sl"}`
selects it explicitly, and `WORDCRAFT_LANGUAGE=sl-SI` does the same for a headless screenshot or a
launch while the preference is `auto`. Document text, command ids, CLI/MCP/control responses and
file paths do not change.
`crates/ui-egui/src/i18n/sl.tsv` has 2,614 entries: every key of every other catalog (built-in
style names, equation gallery labels, paper sizes, watermarks, greetings, citation style names and
native print settings included). It is written from the meaning of the English labels; no proprietary translation
resources were consulted.
## Conventions
- Ribbon tabs, groups, panes and dialog titles are nouns (`Vstavljanje`, `Pisava`, `Podokno slogov`).
- Commands and buttons use the imperative (`Shrani`, `Vstavi tabelo`, `Sprejmi vse spremembe`);
options and toggles use the imperative as well (`Preverjaj črkovanje med tipkanjem`).
- Messages address the user with the polite plural (`Shranite dokument`).
- Only the first word of a label is capitalised.
- Slovenian has singular, dual and plural; the catalog has no plural forms, so counts use
count-neutral wording with a colon (`Besede: 21`, `Razveljavi dejanja: {n}`).
- Placeholders never take a case ending; the wording puts them after a colon instead.
- Quotation marks »…«; decimal comma in prose (`Razmik vrstic 1,5`); paper sizes keep inches as in
the source.
- Text columns and table columns are both `stolpci`, as in common Slovenian usage.
## Terminology
| Source | Slovenian |
|---|---|
| File / Home / Insert / Draw / Design / Layout | Datoteka / Osnovno / Vstavljanje / Risanje / Načrt / Postavitev |
| References / Mailings / Review / View / Help | Sklici / Pošiljanje / Pregled / Pogled / Pomoč |
| Font / Paragraph / Styles | Pisava / Odstavek / Slogi |
| Header / Footer / Heading | Glava / Noga / Naslov |
| Footnote / Endnote / Caption | Sprotna opomba / Končna opomba / Napis |
| Table of Contents / Index | Kazalo vsebine / Stvarno kazalo |
| Citation / Citation Style / Bibliography | Citat / Slog citiranja / Bibliografija |
| Track Changes / Accept / Reject | Sledenje spremembam / Sprejmi / Zavrni |
| Comment / Markup | Komentar / Oznake |
| Mail Merge / Merge Field | Spajanje dokumentov / Polje spajanja |
| Section / Section Break | Odsek / Prelom odseka |
| Undo / Redo / Repeat | Razveljavi / Uveljavi znova / Ponovi |
| Ribbon / Pane / Quick Access Toolbar | Trak / Podokno / Orodna vrstica za hitri dostop |
| Bold / Italic / Underline / Strikethrough | Krepko / Ležeče / Podčrtano / Prečrtano |
| Hyphenation / Proofing | Deljenje besed / Preverjanje |
| Character Spacing / Tracking | Razmik med znaki |
| Watermark | Vodni žig |
| Grayscale | Odtenki sive |
| Printer / Print | Tiskalnik / Natisni |
| Reading Mode | Način branja |
| Full Screen | Celozaslonski način |
| Recover | Obnovi |
| Text box / Content control | Polje z besedilom / Kontrolnik vsebine |
## Verification and remaining scope
Tests in `crates/ui-egui/src/i18n/tests.rs` check locale selection, the saved preference, that the
catalog covers every key of every other catalog and has no keys outside them, key terms, the search
hint example and the bundled fonts' coverage of č, š, ž. Slovenian spelling, grammar and hyphenation
are not included. Native speaker review is welcome.