mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-19 02:10:15 -05:00
i18n: add Croatian (hr) interface translation (#1271)
* i18n: add Croatian (hr) interface translation
Croatian interface catalog (2,505 entries: every key of the reference catalog, built-in style
names, equation gallery, print dialog), registered as `hr` ("Hrvatski"). `hr`, `hr-HR` and
`hr_HR.UTF-8` system locales pick it automatically.
- Count-neutral wording (`Riječi: 21`), since Croatian numerals take three noun forms.
- New `template` catalog context: the "Letter" template can be called "Pismo" while the "Letter"
paper size keeps its name. Other languages fall back to their plain entry, so nothing changes.
- Locale, saved-preference, catalog-coverage and bundled-font tests; `hr` added to the
interface-audit languages; Polish's coverage test lists `hr` with it/hu/bg.
- Written from the meaning of the English labels (clean room, no Word localisation consulted),
proofread by a second model and reviewed by a native speaker.
- ATTRIBUTION row, contributors entry for the author, docs and roadmap.
Croatian spelling and grammar proofing is separate (#1114).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* ATTRIBUTION: name the models and the human review for the Croatian catalog
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* i18n(hr): native-speaker corrections to math terms and messages
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* i18n(hr): envelope names without their size
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* docs: Croatian entry count
Co-Authored-By: Claude Sonnet 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:
11 files changed
+2735
-13
No files matched your search
@@ -77,3 +77,4 @@ Generated-in-code art is original and has no file to list: the UI icon set (`cra
|
||||
| `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 |
|
||||
| `crates/ui-egui/src/i18n/hr.tsv` | Andrej Škvorc (@andrejskvorc) with Claude Code (Sonnet 5.5); proofread with Gemini | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Croatian interface catalog; reviewed and corrected in the running interface, menu by menu, by the native-speaker author, who also checked the Gemini suggestions |
|
||||
@@ -362,6 +362,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-11 | Word's common keyboard shortcuts (#330): 101 → 125 of ~250 |
|
||||
| 2026-10-13 | Swedish (`sv`) interface: 2,504 catalog entries (every key of the reference catalog, the equation gallery, everything the interface audit finds, and 44 newer strings no catalog had yet, among them the native print settings), `sv-SE`/`sv-FI` system locales and a saved language choice; locale, catalog and bundled-font tests; AI-assisted, terminology and the running app reviewed by a native speaker; no Swedish proofing resources |
|
||||
| 2026-10-12 | Bulgarian (`bg`) interface: 2,419 catalog entries (every key of the reference catalog, the equation gallery and everything the interface audit finds), `bg-BG` system locales and a saved language choice; locale, catalog and bundled-font tests; no Bulgarian proofing resources |
|
||||
| 2026-10-13 | Croatian (`hr`) interface: 2,507 catalog entries (every key of the reference catalog, built-in style names and the equation gallery), `hr-*` system locales and a saved language choice; locale, catalog and bundled-font tests; no Croatian proofing yet |
|
||||
| 2026-10-11 | Hungarian (`hu`) interface: all 2,419 catalog entries, built-in style names translated, `hu-HU` system locales and a saved language choice; locale, catalog and bundled-font tests; no Hungarian proofing resources |
|
||||
| 2026-10-11 | Turkish (`tr`) interface: all 1,307 catalog entries, `tr-TR`/`tr-CY` system locales and a saved language choice; command search keeps Turkish dotted and dotless I apart (`italik` finds İtalik); locale, catalog, search and bundled-font tests; no Turkish proofing resources |
|
||||
| 2026-10-11 | Italian (`it`) interface (#594): 2,399 entries, feature names as Italian Word users know them, locale and saved-preference tests, bundled-font checks; no Italian proofing resources |
|
||||
@@ -543,6 +544,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-11 | trivial | Collapsed duplicate rows left by parallel merges |
|
||||
| 2026-10-13 | trivial | Swedish interface (`sv`): progress log and shipped languages |
|
||||
| 2026-10-12 | trivial | Bulgarian interface (`bg`): progress log and shipped languages |
|
||||
| 2026-10-13 | trivial | Croatian interface (`hr`): progress log and shipped languages |
|
||||
| 2026-10-11 | trivial | Hungarian interface (`hu`): progress log and shipped languages |
|
||||
| 2026-10-11 | trivial | Turkish interface (`tr`): progress log and shipped languages |
|
||||
| 2026-10-14 | trivial | Progress log: `.doc` notes, headers and text boxes read their text once (#1319) |
|
||||
|
||||
@@ -123,3 +123,8 @@ real_name = "Robert Lee"
|
||||
real_name = "Erik Holmbom"
|
||||
display_name = "Erik Holmbom"
|
||||
sync_github_name = false
|
||||
|
||||
[people.andrejskvorc]
|
||||
real_name = "Andrej Škvorc"
|
||||
display_name = "Andrej Škvorc"
|
||||
sync_github_name = false
|
||||
@@ -258,7 +258,7 @@ fn template_tile(ui: &mut Ui, app: &mut WordApp, label: &str, template: &str) {
|
||||
ui.painter().image(h.id(), r.shrink(1.0), Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)), egui::Color32::WHITE);
|
||||
}
|
||||
// The caption opens the template too, as in Word.
|
||||
let caption = ui.add(egui::Label::new(egui::RichText::new(tl!(label)).font(regular(12.5))).sense(Sense::click()));
|
||||
let caption = ui.add(egui::Label::new(egui::RichText::new(crate::i18n::tc("template", label)).font(regular(12.5))).sense(Sense::click()));
|
||||
if resp.clicked() || caption.clicked() {
|
||||
let _ = app.run("file.new", json!({"template": template}));
|
||||
app.ui.backstage = false;
|
||||
@@ -280,7 +280,9 @@ fn matching_templates(query: &str) -> Vec<(&'static str, &'static str)> {
|
||||
let q = query.trim().to_lowercase();
|
||||
TEMPLATES
|
||||
.into_iter()
|
||||
.filter(|(label, id)| q.is_empty() || id.contains(&q) || label.to_lowercase().contains(&q) || tl!(label).to_lowercase().contains(&q))
|
||||
.filter(|(label, id)| {
|
||||
q.is_empty() || id.contains(&q) || label.to_lowercase().contains(&q) || crate::i18n::tc("template", label).to_lowercase().contains(&q)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -333,7 +333,7 @@ fn untranslated_interface_text() {
|
||||
complete_catalogs_have_every_string_the_interface_looked_up(pseudo::looked_up());
|
||||
}
|
||||
|
||||
/// Russian, Hungarian, Turkish, Bulgarian, Italian and Swedish cover everything the audit saw
|
||||
/// Russian, Hungarian, Turkish, Bulgarian, Italian, Swedish and Croatian 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>) {
|
||||
@@ -379,7 +379,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"] {
|
||||
for code in ["ru", "hu", "tr", "bg", "it", "sv", "hr"] {
|
||||
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();
|
||||
|
||||
@@ -20,7 +20,10 @@ pub struct Entry {
|
||||
/// The contexts a catalog entry may name, and where each applies.
|
||||
/// - `preview`: sample text inside a rendered preview (the Design tab's style-set tiles), which
|
||||
/// has to fit a small tile; it falls back to the plain entry.
|
||||
pub const CONTEXTS: &[&str] = &["preview"];
|
||||
/// - `template`: the name of a built-in document template (Home and New), which may need other
|
||||
/// wording than the same English word elsewhere (the "Letter" template and the "Letter" paper
|
||||
/// size); it falls back to the plain entry.
|
||||
pub const CONTEXTS: &[&str] = &["preview", "template"];
|
||||
|
||||
/// A parsed catalog. Values are owned for the life of the process (catalogs are built once).
|
||||
#[derive(Debug, Default)]
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -52,7 +52,7 @@ pub struct LangInfo {
|
||||
}
|
||||
|
||||
/// The registry. English first: it is the fallback and the source language.
|
||||
pub static LANGUAGES: [LangInfo; 22] = [
|
||||
pub static LANGUAGES: [LangInfo; 23] = [
|
||||
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 {
|
||||
@@ -156,6 +156,8 @@ pub static LANGUAGES: [LangInfo; 22] = [
|
||||
LangInfo { code: "vi", name: "Tiếng Việt", source: include_str!("vi.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// Swedish; sv, sv-SE, sv-FI and sv_SE.UTF-8 resolve here.
|
||||
LangInfo { code: "sv", name: "Svenska", source: include_str!("sv.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// Croatian; `hr`, `hr-HR` and `hr_HR.UTF-8` resolve here.
|
||||
LangInfo { code: "hr", name: "Hrvatski", source: include_str!("hr.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
];
|
||||
|
||||
impl LangInfo {
|
||||
|
||||
@@ -989,9 +989,7 @@ fn polish_covers_every_key_of_every_other_catalog() {
|
||||
let polish = keys(lang("pl").0.source);
|
||||
// Italian and Hungarian still carry "Style: APA", which the interface no longer shows;
|
||||
// Hungarian and Bulgarian also name the citation styles, and Bulgarian has a few one-line
|
||||
// pieces of gallery labels, which Swedish carries too. Polish matches every other catalog,
|
||||
// including the style names and equation gallery Russian translates.
|
||||
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "it" | "hu" | "bg" | "vi" | "sv")) {
|
||||
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "it" | "hu" | "bg" | "vi" | "sv" | "hr")) {
|
||||
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());
|
||||
@@ -1277,6 +1275,91 @@ fn bundled_interface_fonts_cover_bulgarian_without_system_fallbacks() {
|
||||
assert!(!lang("bg").uses_cjk());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn croatian_locales_and_saved_preference_work_without_changing_the_document() {
|
||||
let hr = lang("hr");
|
||||
for tag in ["hr", "hr-HR", "hr_HR.UTF-8", "HR-hr", "hr-Latn-HR", "hr-BA"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(hr), "{tag}");
|
||||
}
|
||||
assert_eq!(first_supported([UNSUPPORTED, "hr-HR", "en-US"]), Some(hr));
|
||||
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": "HR"})).unwrap();
|
||||
assert_eq!(result["effective"], "hr");
|
||||
assert_eq!(app.ui.language, "hr");
|
||||
assert!(result["available"].as_array().unwrap().iter().any(|l| l["code"] == "hr" && l["name"] == "Hrvatski"));
|
||||
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), hr);
|
||||
assert_eq!(hr.name(), "Hrvatski");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn croatian_covers_the_entire_existing_interface_catalog_and_keeps_count_labels_neutral() {
|
||||
use std::collections::HashSet;
|
||||
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
|
||||
let hr = lang("hr");
|
||||
// Every key of every other catalog, and no catalog errors.
|
||||
for other in Lang::all().filter(|l| *l != Lang::EN && l.code() != "hr") {
|
||||
let mut missing: Vec<String> = keys(other.0.source).difference(&keys(hr.0.source)).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(), "hr lacks {}'s {missing:?}", other.code());
|
||||
}
|
||||
assert!(parse_entries(hr.0.source).1.is_empty());
|
||||
for (source, expected) in [
|
||||
("File", "Datoteka"),
|
||||
("Home", "Početna"),
|
||||
("Insert", "Umetni"),
|
||||
("Review", "Pregled"),
|
||||
("Save", "Spremi"),
|
||||
("Heading 1", "Naslov 1"),
|
||||
("Spelling & Grammar", "Pravopis i gramatika"),
|
||||
("Hyphenation", "Rastavljanje riječi"),
|
||||
("WordCraft", "WordCraft"),
|
||||
("unknown future label", "unknown future label"),
|
||||
] {
|
||||
assert_eq!(tr(hr, source), expected, "{source}");
|
||||
}
|
||||
assert_eq!(fmt(tr(hr, "Page {page} of {pages}"), &[("page", "3"), ("pages", "9")]), "Stranica 3 od 9");
|
||||
// The letter template is "Pismo"; the paper size of the same English name stays "Letter".
|
||||
assert_eq!(trc(hr, "template", "Letter"), "Pismo");
|
||||
assert_eq!(tr(hr, "Letter"), "Letter");
|
||||
// Croatian nouns take three forms after numerals (1, 2–4, 5+), so counts read `Riječi: 21`.
|
||||
for count in [0, 1, 2, 4, 5, 12, 14, 21, 22, 25, 101, 1000] {
|
||||
let words = count.to_string();
|
||||
assert_eq!(fmt(tr(hr, "{words} words"), &[("words", &words)]), format!("Riječi: {count}"));
|
||||
assert_eq!(fmt(tr(hr, "{selected} of {words} words"), &[("selected", "1"), ("words", &words)]), format!("Riječi: 1 od {count}"));
|
||||
}
|
||||
set_current(hr);
|
||||
assert_eq!(location("Review › Proofing"), "Pregled › Jezična provjera");
|
||||
set_current(Lang::EN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_interface_fonts_cover_croatian_without_system_fallbacks() {
|
||||
let db = wordcraft_fonts::FontDb::with_font_dirs(Vec::new());
|
||||
let (entries, errors) = parse_entries(lang("hr").0.source);
|
||||
assert!(errors.is_empty());
|
||||
let chars: std::collections::HashSet<char> = entries
|
||||
.iter()
|
||||
.flat_map(|e| e.translation.chars())
|
||||
// Croatian letters plus its quotes and dashes; symbols come from the English sources.
|
||||
.filter(|c| matches!(c, '„' | '”' | '–'))
|
||||
.chain("ČčĆćĐ𩹮ž".chars())
|
||||
.collect();
|
||||
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("hr").uses_cjk());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn swedish_locales_and_saved_preference_work_without_changing_the_document() {
|
||||
let sv = lang("sv");
|
||||
|
||||
@@ -2656,3 +2656,5 @@
|
||||
This document has no bookmarks. Tài liệu này không có dấu trang.
|
||||
Type a page number, or +2 / -1. Nhập số trang, hoặc +2 / -1.
|
||||
Wait for the print job to finish submitting before closing. Hãy chờ lệnh in được gửi xong rồi mới đóng.
|
||||
# Template names in File › New (#1271)
|
||||
template Letter Thư
|
||||
|
Can't render this file because it contains an unexpected character in line 7 and column 25.
|
@@ -19,8 +19,8 @@ native-speaker review (human).
|
||||
|
||||
## What WordCraft ships (measured)
|
||||
|
||||
- **22 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) and Swedish `sv` (#1219). Catalogs have 2,061–2,504 entries
|
||||
- **23 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) and Croatian `hr` (#1271). Catalogs have 2,061–2,504 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 and Swedish 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.
|
||||
@@ -59,12 +59,13 @@ shared items below.
|
||||
| Korean | ko | 2,463 entries (all catalog keys and preview context) | most; newer panes English | Hangul ✅ (Korean-first embedded/system UI font fallback); macOS Korean IME fixes pending (#163, #164) | no | partial | 3–5 |
|
||||
| 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) |
|
||||
|
||||
Other shipped languages: **15** — 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) and Swedish (`sv`, #1219), all partial.
|
||||
Other shipped languages: **16** — 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) and Croatian (`hr`, #1271), 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
|
||||
speaker. Swedish proofing is not included; terminology: [`localization-sv.md`](localization-sv.md).
|
||||
Croatian (`hr-HR` system locales, `{"value":"hr"}`) has 2,507 entries: every key of the reference catalog, built-in style names and the equation gallery. Counts use count-neutral wording (`Riječi: 21`) because Croatian numerals take three noun forms. The catalog was written and checked by a native speaker; Croatian proofing is a separate change.
|
||||
Estonian uses the existing fonts, follows `et-EE` system locales, and is available in Options or
|
||||
through `ui.language` with `{"value":"et"}`. Its 1,307 entries cover the existing interface catalog.
|
||||
Estonian spelling, grammar, dates and document templates are not added by the interface catalog.
|
||||
@@ -215,6 +216,7 @@ WordCraft keeps 2,54 cm).
|
||||
| 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-12 | minor | Bulgarian interface catalog (2,419 entries), locale selection, saved preference, audit coverage and font checks |
|
||||
| 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 |
|
||||
| 2026-10-11 | minor | Hungarian interface catalog (2,419 entries, built-in style names shown translated; covers everything the interface audit finds), locale selection, saved preference and font coverage checks |
|
||||
| 2026-10-11 | minor | Turkish interface catalog (1,307 entries), locale selection, saved preference, Turkish casing in command search and font coverage checks; catalog sizes re-counted |
|
||||
| 2026-10-11 | trivial | English spelling (#520): our supplement `assets/spelling/en-extra.txt` adds ~220 common modern words the Moby list lacks ("desktop", "download", "email"…) |
|
||||
|
||||
Reference in new issue
Block a user