mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 15:57:49 +00:00
#6613: guard web Gujarati selection and address local review
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ gate: all six core workflows (path drawing and editing, paint and style, type, l
|
||||
production, file exchange) work end to end on macOS with save and reopen, and only the last is partial, without
|
||||
blocking it ([Alpha gate](docs/roadmap.md#alpha-gate)).
|
||||
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face. Scores and estimates unchanged.
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face; web selection stays unavailable until a Gujarati interface face is bundled. Scores and estimates unchanged.
|
||||
|
||||
## Headline numbers
|
||||
|
||||
|
||||
@@ -491,16 +491,10 @@ pub(crate) fn text_within<'a>(bytes: &'a [u8], unpacked: &std::sync::atomic::Ato
|
||||
match craft_svg::svgz::inflate(bytes, most) {
|
||||
Ok(raw) => {
|
||||
unpacked.fetch_add(raw.len() as u64, Ordering::Relaxed);
|
||||
craft_svg::svgz::decode(&raw)
|
||||
.map(|t| std::borrow::Cow::Owned(t.into_owned()))
|
||||
.map_err(|_| not_utf8())
|
||||
}
|
||||
Err(craft_svg::svgz::Error::TooLarge(_)) => {
|
||||
Err(SvgError::TooBig(format!("the SVGZ file unpacks to more than {} MB", most >> 20)))
|
||||
}
|
||||
Err(craft_svg::svgz::Error::Corrupt(e)) => {
|
||||
Err(SvgError::Parse(format!("not a valid SVGZ file: {e}")))
|
||||
craft_svg::svgz::decode(&raw).map(|t| std::borrow::Cow::Owned(t.into_owned())).map_err(|_| not_utf8())
|
||||
}
|
||||
Err(craft_svg::svgz::Error::TooLarge(_)) => Err(SvgError::TooBig(format!("the SVGZ file unpacks to more than {} MB", most >> 20))),
|
||||
Err(craft_svg::svgz::Error::Corrupt(e)) => Err(SvgError::Parse(format!("not a valid SVGZ file: {e}"))),
|
||||
Err(craft_svg::svgz::Error::Encoding) => Err(not_utf8()),
|
||||
Err(e) => Err(SvgError::Parse(e.to_string())),
|
||||
}
|
||||
|
||||
@@ -111,7 +111,8 @@ pub static LANGUAGES: [LangInfo; 29] = [
|
||||
},
|
||||
// Gujarati: menus and dialogs, with partial status/error message coverage and loanwords
|
||||
// transliterated into Gujarati script; zero/one singular plurals. Gujarati text is drawn with an installed system font
|
||||
// (Gujarati Sangam MN, Nirmala UI, Shruti) or a craft-fonts face tagged `Gujr`; every `gu-*` locale resolves here.
|
||||
// (Gujarati Sangam MN, Nirmala UI, Shruti) or a craft-fonts face tagged `Gujr`. Web selection
|
||||
// requires a bundled Gujarati interface face; otherwise `gu-*` locales use the fallback.
|
||||
LangInfo {
|
||||
code: "gu",
|
||||
name: "ગુજરાતી",
|
||||
@@ -366,6 +367,19 @@ pub static LANGUAGES: [LangInfo; 29] = [
|
||||
];
|
||||
|
||||
impl LangInfo {
|
||||
fn available(&self) -> bool {
|
||||
self.available_with_fonts(
|
||||
cfg!(target_arch = "wasm32"),
|
||||
cfg!(feature = "interface-fonts") && vectorcraft_text::CRAFT_FONTS.iter().any(|f| f.scripts.contains(&"Gujr")),
|
||||
)
|
||||
}
|
||||
|
||||
fn available_with_fonts(&self, web: bool, gujarati_font: bool) -> bool {
|
||||
// Browsers cannot use the native installed-font fallback. Do not offer a language
|
||||
// whose text would be missing-glyph boxes, including when restoring a preference.
|
||||
self.code != "gu" || !web || gujarati_font
|
||||
}
|
||||
|
||||
fn catalog(&self) -> &Catalog {
|
||||
self.catalog.get_or_init(|| Catalog::parse(self.source))
|
||||
}
|
||||
@@ -398,7 +412,7 @@ impl Lang {
|
||||
|
||||
/// A language by its exact code.
|
||||
pub fn from_code(code: &str) -> Option<Lang> {
|
||||
LANGUAGES.iter().find(|l| l.code.eq_ignore_ascii_case(code)).map(Lang)
|
||||
LANGUAGES.iter().find(|l| l.code.eq_ignore_ascii_case(code) && l.available()).map(Lang)
|
||||
}
|
||||
|
||||
/// Resolve the `interfaceLanguage` preference: a language code, or `auto` (and anything
|
||||
@@ -407,12 +421,12 @@ impl Lang {
|
||||
Lang::from_code(pref).unwrap_or_else(system_lang)
|
||||
}
|
||||
|
||||
/// Every registered language.
|
||||
/// Every language available in this build.
|
||||
pub fn all() -> impl Iterator<Item = Lang> {
|
||||
LANGUAGES.iter().map(Lang)
|
||||
LANGUAGES.iter().filter(|l| l.available()).map(Lang)
|
||||
}
|
||||
|
||||
/// Every registered language in the order a picker lists them: English first (the source
|
||||
/// Every available language in the order a picker lists them: English first (the source
|
||||
/// language and the fallback), then the rest by their own name with accents folded, so
|
||||
/// Čeština sits under C rather than after Z. Names in other scripts follow the Latin ones in
|
||||
/// code point order: Greek, Cyrillic, Arabic, then the CJK languages.
|
||||
|
||||
@@ -5,9 +5,12 @@ const ZH: fn() -> Lang = || Lang::from_code("zh-hant").expect("zh-hant registere
|
||||
|
||||
#[test]
|
||||
fn gujarati_resolves_locales_and_takes_the_singular_for_zero_and_one() {
|
||||
let gu = Lang::from_code("gu").expect("gu registered");
|
||||
// The catalog is present even when this web build cannot display it.
|
||||
let gu = Lang(LANGUAGES.iter().find(|l| l.code == "gu").expect("gu registered"));
|
||||
let selectable = gu.0.available().then_some(gu);
|
||||
assert_eq!(Lang::from_code("gu"), selectable);
|
||||
for tag in ["gu", "gu-IN", "gu_IN.UTF-8", "GU-in", "gu-Gujr-IN"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(gu), "{tag}");
|
||||
assert_eq!(lang_from_tag(tag), selectable, "{tag}");
|
||||
}
|
||||
assert_eq!(gu.name(), "ગુજરાતી");
|
||||
assert_eq!([0, 1, 2, 21].map(gu.0.plural), [0, 0, 1, 1]);
|
||||
@@ -220,6 +223,17 @@ fn tags_map_to_languages() {
|
||||
assert_eq!(lang_from_tag("_"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn gujarati_web_selection_requires_a_bundled_interface_font() {
|
||||
let gu = LANGUAGES.iter().find(|l| l.code == "gu").expect("Gujarati catalog");
|
||||
assert!(gu.available_with_fonts(false, false), "native installed-font fallback");
|
||||
assert!(!gu.available_with_fonts(true, false), "web must not offer missing glyphs");
|
||||
assert!(gu.available_with_fonts(true, true));
|
||||
assert!(LANGUAGES[0].available_with_fonts(true, false), "English fallback");
|
||||
assert_eq!(Lang::from_code("gu").is_some(), gu.available());
|
||||
assert_eq!(Lang::for_picker().iter().any(|l| l.code() == "gu"), gu.available());
|
||||
}
|
||||
|
||||
/// The Bosnian, Georgian, Ukrainian, Hungarian, Korean, Vietnamese, Swedish and Catalan tags of
|
||||
/// [`tags_map_to_languages`].
|
||||
fn other_tags_map_to_languages() {
|
||||
|
||||
@@ -22,7 +22,7 @@ English) in-app help, and the docs are English.
|
||||
(`bflatastic`), with community contributors adding or correcting (German by `dwetscher`, Japanese and Traditional
|
||||
Chinese by `imachus`). Georgian and the original Gujarati catalog are recorded as reviewed by native speakers; new Gujarati additions still need proofreading.
|
||||
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face. Scores and estimates unchanged.
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face; web selection stays unavailable until a Gujarati interface face is bundled. Scores and estimates unchanged.
|
||||
|
||||
## The twelve key languages
|
||||
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
> **PDF import status (2026-11-14, #6957):** Outlined Indic glyphs retain their full stroke properties; translucent glyphs stay separate, and a soft mask attaches to each glyph separately. Scores and estimates unchanged.
|
||||
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face. Scores and estimates unchanged.
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face; web selection stays unavailable until a Gujarati interface face is bundled. Scores and estimates unchanged.
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
> **PDF import status (2026-11-14, #6957):** Outlined Indic glyphs retain their full stroke properties; translucent glyphs stay separate, and a soft mask attaches to each glyph separately. Scores and estimates unchanged.
|
||||
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face. Scores and estimates unchanged.
|
||||
> **Gujarati status (2026-11-14, #6613):** 4,673 catalog rows: the original 4,286 retain their contributor review; 387 additions are drafts awaiting native proofreading. Status/error messages remain partial, and the pinned CI/release fonts and web startup list contain no Gujarati face; web selection stays unavailable until a Gujarati interface face is bundled. Scores and estimates unchanged.
|
||||
|
||||
## Feature submission evidence
|
||||
|
||||
@@ -886,7 +886,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- A toolbar made with New Toolbar docks in a lane along the window's left or right edge when its title bar is dropped on that edge, or with Dock to Left and Dock to Right in the title bar's context menu. Toolbars docked at one edge stack from the top, each with its share of the lane's height, and the lane is as wide as its widest toolbar; a lane too short for its stack wraps it into more columns, up to half the window's width, and past that the toolbars show only their title bars, which the mouse wheel scrolls through when even they do not fit. Dragging the title bar out of the lane, or Float Toolbar, floats it again, and Escape during the drag puts it back. Hiding and renaming keep its place, and the workspace keeps it. New toolbars still start floating. The lanes and the stacking are VectorCraft's own rules (#1759; `window.toolbar.dock`, `window.toolbar.float`; `toolbars_dock_and_float_by_their_commands`, `docked_toolbars_stack_in_lanes_along_the_window_edges`, `a_title_bar_dropped_on_an_edge_docks_the_toolbar`).
|
||||
- Window › Toolbars › Keep Tools Beside the Canvas, a VectorCraft layout option that is off by default, docks the Tools panel between left-side panels and the canvas instead of at the window's left edge; the canvas's left edge then also docks a floating Tools panel, and workspaces keep the setting. Scores are unchanged (`window.toolsBesideCanvas`; `docked_tools_keep_the_window_edge_unless_kept_beside_the_canvas`, `tools_redock_at_the_targets_of_the_chosen_placement`).
|
||||
- Hindi (2026-11-06): Hindi (`hi`): 7,877-row machine-assisted catalog, zero/one singular plurals, desktop font fallback and optional Devanagari craft-fonts fallback; all 55 translation tests pass; native review and a web font remain; scores and estimates unchanged. [Terminology and limitations](localization-hi.md).
|
||||
- Gujarati (2026-11-14, #6613): `gu` has 4,672 catalog rows, zero/one singular plurals, installed desktop font fallback and support for optional `Gujr` craft-font faces. The original 4,286 rows retain contributor review; 386 new rows are drafts pending native proofreading. Status/error messages remain partial; the pinned fonts and web startup list have no Gujarati face. Current-head validation is recorded in the PR; scores and estimates unchanged.
|
||||
- Gujarati (2026-11-14, #6613): `gu` has 4,673 catalog rows, zero/one singular plurals, installed desktop font fallback and support for optional `Gujr` craft-font faces. The original 4,286 rows retain contributor review; 387 new rows are drafts pending native proofreading. Status/error messages remain partial; the pinned fonts and web startup list have no Gujarati face, so web selection remains unavailable until one is bundled. Current-head validation is recorded in the PR; scores and estimates unchanged.
|
||||
- Hindi wording (2026-11-13): rows outside the plug-in messages keep their English's meaning, quantities and clauses, and use the catalog's save, swatch, crop, resolution, path and type terms; a test checks those terms and the point unit in every row; native review remains; scores and estimates unchanged.
|
||||
- Hindi terms (2026-11-13): every row that names a variable (data merge, variable fonts and widths, environment variables) says वेरिएबल, and joining paths, anchor points, point type and lines says जोड़ें instead of शामिल हों, which stays for joining the community; a test checks both terms in every row; scores and estimates unchanged.
|
||||
- Hindi English words (2026-11-13): 264 rows no longer keep English words in their sentences, repeat a parameter's name in Hindi or garble them, among them "unknown align", which now names the alignment; lists of accepted values such as `(left|right|top|bottom)` stay as their English writes them; two tests check every row; native review remains; scores and estimates unchanged.
|
||||
|
||||
Reference in New Issue
Block a user