From 9d8577754652d0fcd98822e3e2c2defeb8e12df7 Mon Sep 17 00:00:00 2001 From: Shao Wenbin Date: Tue, 6 Oct 2026 03:15:57 +0800 Subject: [PATCH] UI: add Chinese and Arabic localization with RTL-safe interface text Extend interface language selection with Chinese and Arabic translations across menus, dialogs, panels, tooltips, and common application controls. Keep English fallback for untranslated strings, return borrowed translation text, and validate translation key uniqueness and language switching. Bundle redistributable Noto CJK and Arabic fonts with OFL license files and ASSETS.md attribution so native and WASM builds have portable glyph coverage. Register Arabic regular and semibold families while retaining existing font fallbacks for proportional and monospace controls. Render Arabic labels using Unicode bidirectional runs and contextual shaping. Wrap logical text at grapheme boundaries before ordering each visual line, mirror neutral punctuation, preserve logical source text for accessibility, and handle truncation, empty lines, and mixed Latin text and numbers. Keep ASCII labels on the normal rendering path. Disable selection on shaped RTL labels because egui's default label cursor mapping assumes LTR text. Adapt welcome controls, menu ordering, popup alignment, and new-document rows for RTL layout. Bound popup geometry and avoid unsupported RTL grid behavior; keep numeric inputs LTR. Isolate user-provided document names from Latin application and zoom metadata. Interface language changes leave document binding, paragraph direction, editable text, and engine state unchanged. Add regressions for contextual Arabic joining, bidirectional punctuation, mixed document names, logical wrapping, truncation, language switching, and finite widget geometry. Update the roadmap with localization coverage. Apply equivalent chunk-iteration and PDF Option/borrow simplifications needed by the current Rust toolchain's strict Clippy checks. Validation: - cargo xtask ci: fmt, Clippy, native tests, assets, and layers passed; native tests total 517 passed and 2 ignored. - UI regression suite: 26 passed. - Headless UI screenshots verified Arabic welcome/new-document creation, menus, mixed-script document names, and switching back to Chinese/English. - Default WASM gate is blocked by this host's missing precompiled wasm32 standard library. All 15 WASM crates pass using the installed Rust sources: RUSTC_BOOTSTRAP=1 CARGO_UNSTABLE_BUILD_STD=std,panic_abort target/debug/xtask wasm. --- Cargo.lock | 3 + Cargo.toml | 2 + ROADMAP.md | 2 +- crates/ui-egui/Cargo.toml | 3 + crates/ui-egui/src/about.rs | 40 +- crates/ui-egui/src/chrome.rs | 185 ++- crates/ui-egui/src/dialogs.rs | 632 ++++--- crates/ui-egui/src/dock.rs | 33 +- crates/ui-egui/src/i18n.rs | 1911 ++++++++++++++++++++-- crates/ui-egui/src/i18n/ar.rs | 276 ++++ crates/ui-egui/src/icons.rs | 8 +- crates/ui-egui/src/lib.rs | 13 +- crates/ui-egui/src/menus.rs | 91 +- crates/ui-egui/src/panels/conditions.rs | 16 +- crates/ui-egui/src/panels/glyphs.rs | 2 +- crates/ui-egui/src/panels/interactive.rs | 109 +- crates/ui-egui/src/panels/layers.rs | 8 +- crates/ui-egui/src/panels/library.rs | 48 +- crates/ui-egui/src/panels/notes.rs | 5 +- crates/ui-egui/src/panels/pages.rs | 19 +- crates/ui-egui/src/panels/properties.rs | 160 +- crates/ui-egui/src/panels/styles.rs | 11 +- crates/ui-egui/src/panels/swatches.rs | 52 +- crates/ui-egui/src/panels/table.rs | 25 +- crates/ui-egui/src/rtl.rs | 315 ++++ crates/ui-egui/src/story_editor.rs | 5 +- crates/ui-egui/src/taskbar.rs | 15 +- crates/ui-egui/src/theme.rs | 44 +- crates/ui-egui/src/toolbar.rs | 28 +- crates/ui-egui/src/widgets.rs | 14 +- 30 files changed, 3372 insertions(+), 703 deletions(-) create mode 100644 crates/ui-egui/src/i18n/ar.rs create mode 100644 crates/ui-egui/src/rtl.rs diff --git a/Cargo.lock b/Cargo.lock index e6ed044..e5ae303 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1111,6 +1111,9 @@ dependencies = [ "regex", "serde", "serde_json", + "unicode-bidi", + "unicode-bidi-mirroring", + "unicode-segmentation", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 894f4bd..b78f952 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,6 +39,8 @@ log = "0.4" proptest = "1" rayon = "1" unicode-bidi = "0.3" +unicode-bidi-mirroring = "0.4" +unicode-segmentation = "1" regex = { version = "1", default-features = false, features = ["std", "unicode", "perf"] } # text / rendering / formats diff --git a/ROADMAP.md b/ROADMAP.md index 00020ad..ec17b71 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -97,7 +97,7 @@ DesignCraft aims at full Adobe InDesign parity — and to be better: faster, ope - Transparency flattener (`file.exportPdf {flatten: high|medium|low|ppi}`, Edit ▸ Transparency Flattener Presets): each object involving transparency becomes an opaque image of its area over what's beneath it, so everything else stays vector (spreads with transparent parent items are rasterised whole). - Video and sound (place .mp4/.mov/.webm/.mp3/.wav…, `media.options/get`, Media panel): media frames show a poster or placeholder on screen, in print and in PDF, and export as HTML5 `