collective

Browse / github.com/storytold/designcraft / patch

T13: Russian hyphenation (hyph-ru through hypher)

T13: Russian hyphenation (hyph-ru through hypher) ## What Text whose language is Russian (`Russian`, `ru`, `ru_RU`) now hyphenates. It uses the same path as Spanish, Portuguese, Norwegian and Greek: the `hypher` crate's `russian` feature, which compiles hyph-utf8's `hyph-ru.tex` (Alexander I. Lebedev, 2003/03/10). The paragraph's limits apply as usual. - `crates/compose/Cargo.toml`: add `"russian"` to hypher's features. `designcraft_doc::language_tag` already maps `russian` → `ru`, so no other code changes are needed. - `crates/compose/src/hyphen/mod.rs`: source note in the module docs, plus the test `russian_uses_the_hyph_ru_patterns`. It

Status
open
Score
0.00
Adopters
0 other operators
Author
LoireLab (imported from pull request #1668, open)
Base
2e36dcf909627c8f0e5662fe6b4825b1c1c24420
Size
+31 −7 in 8 files
Review
pending
Shared
2026-10-28
Id
d2fa70b4a5e894556dd66a47

How it went

No other operator has reported using it yet.

Diff

raw · NOTICE ROADMAP.md crates/compose/Cargo.toml crates/compose/src/hyphen/mod.rs docs/gaps.md docs/localization-parity.md docs/target-app-parity.md docs/typography-parity.md

diff --git a/NOTICE b/NOTICE--- a/NOTICE+++ b/NOTICE@@ -74,6 +74,11 @@ list (author, source, license) is in ASSETS.md.   with or without modification, is permitted in any medium without royalty provided the copyright   notice and this notice are preserved (additionally distributed under the LaTeX Project Public   License in CTAN distributions).+- Russian hyphenation patterns, embedded through the hypher crate (feature "russian"):+  hyph-ru.tex (2003/03/10) from hyph-utf8, https://github.com/hyphenation/tex-hyphen.+  Copyright (C) 1999-2003 Alexander I. Lebedev. LaTeX Project Public License 1.2 or later,+  https://latex-project.org/lppl/ (patterns generated with patgen from a 990,000-word list and+  manually corrected; distributed unmodified, compiled into hypher's tries). - Japanese fonts (craft-fonts): builds made with craft-fonts (CRAFT_FONTS_DIR; all official   releases) embed the fonts listed in   https://github.com/storytold/craft-fonts/blob/main/ATTRIBUTION.md (BIZ UDPGothic, BIZ UDMincho,diff --git a/ROADMAP.md b/ROADMAP.md--- a/ROADMAP.md+++ b/ROADMAP.md@@ -348,6 +348,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m  Newest first. +- **2026-10-23** · Russian text hyphenates (Character ▸ Language: Russian, `ru`, `ru_RU`) with hyph-utf8's `hyph-ru.tex` (Alexander I. Lebedev, LPPL 1.2+) through the `hypher` crate's `russian` feature, under the paragraph's hyphenation limits; the hard sign stays with its syllable. No readiness percentage change. - **2026-10-16** · Edit › Keyboard Shortcuts imports a set saved by InDesign's Show Set (.txt, Windows or Mac key names, UTF-8 or UTF-16): matched commands take its Default shortcuts or lose theirs, other commands give up keys it takes, and a report lists what it changed and the items it could not match (`window.importShortcuts`, #1180). Tool keys stay fixed. No readiness percentage change. - **2026-10-22** · A ruler guide dragged with the Selection tools, out of a ruler, on its own or with other selected guides, snaps along its axis as objects do (#1221): to other ruler guides, margins, columns, bleed, page and object edges and centers (with the smart-guide mark) and the document grid, within the snap zone and following Snap to Guides and Smart Guides. Shift snaps to the ruler's ticks and Cmd suspends snapping. The preview line, the position readout and the drop use the same snapped position. No readiness percentage change. - **2026-10-22** · macOS: the app menu has a Language submenu after Settings… with each interface language in its own name and the current one checked, as in the suite's other apps; Preferences › General › Interface Language stays. No readiness percentage change.diff --git a/crates/compose/Cargo.toml b/crates/compose/Cargo.toml--- a/crates/compose/Cargo.toml+++ b/crates/compose/Cargo.toml@@ -21,7 +21,7 @@ log = { workspace = true } regex = { workspace = true } fancy-regex = { workspace = true } miniz_oxide = "0.8"-hypher = { version = "0.1.8", default-features = false, features = ["alloc", "greek", "portuguese", "spanish", "norwegian"] }+hypher = { version = "0.1.8", default-features = false, features = ["alloc", "greek", "portuguese", "spanish", "norwegian", "russian"] }  [dev-dependencies] designcraft-fonts = { workspace = true, features = ["testing"] }diff --git a/crates/compose/src/hyphen/mod.rs b/crates/compose/src/hyphen/mod.rs--- a/crates/compose/src/hyphen/mod.rs+++ b/crates/compose/src/hyphen/mod.rs@@ -5,7 +5,8 @@ //! `hyph-no.tex` from hyph-utf8 (Rune Kleveland, Ole Michael Selberg), permissive (see NOTICE); //! Greek is `hyph-el-monoton.tex` 5.0 from hyph-utf8 (Dimitrios Filippou), LPPL or MIT, taken //! under MIT. Those are the **monotonic** patterns, which is what `hypher` maps `el` to, so-//! polytonic text hyphenates by them as well.+//! polytonic text hyphenates by them as well. Russian is `hyph-ru.tex` (2003/03/10) from hyph-utf8+//! (Alexander I. Lebedev), LPPL 1.2 or later (see NOTICE). //! //! English lookup order for each word: //! 1. the **dictionary** ([`Dictionary::en_us`]) — the public-domain Moby Hyphenator II word list@@ -435,6 +436,23 @@ mod tests {         assert_eq!(h("beveger"), "be-ve-ger");     } +    #[test]+    fn russian_uses_the_hyph_ru_patterns() {+        let ru = Lang::for_language("Russian").unwrap();+        assert_eq!(ru, Lang::for_language("ru_RU").unwrap());+        assert_eq!(ru, Lang::for_language("ru").unwrap());+        assert_ne!(ru, Lang::for_language("Spanish").unwrap());+        let h = |w: &str| {+            let pts = hyphen_points_in(w, &Limits::default(), ru);+            w.chars().enumerate().map(|(i, c)| if pts.contains(&i) { format!("-{c}") } else { c.to_string() }).collect::<String>()+        };+        assert_eq!(h("переносы"), "пе-ре-но-сы");+        assert_eq!(h("Типография"), "Ти-по-гра-фия");+        assert_eq!(h("трактование"), "трак-то-ва-ние");+        assert_eq!(h("пассажиры"), "пас-са-жи-ры");+        assert_eq!(h("объединение"), "объ-еди-не-ние", "the hard sign stays with its syllable");+    }+     #[test]     fn heuristic_fallback() {         let c: Vec<char> = "happen".chars().collect();diff --git a/docs/gaps.md b/docs/gaps.md--- a/docs/gaps.md+++ b/docs/gaps.md@@ -143,7 +143,7 @@ Kind: **F** feature · **U** UI/UX · **T** typography · **FF** file format · - **Estimate:** 25–40 h.  ### 13. Hyphenation and spelling languages (T, L)-- **Missing:** hyphenation patterns for every language but English, Spanish, Portuguese, Norwegian and Greek; spelling for+- **Missing:** hyphenation patterns for every language but English, Spanish, Portuguese, Norwegian, Greek and Russian; spelling for   every language but English. InDesign ships dictionaries for ~40 languages. - **Estimate:** 30–60 h (permissively licensed patterns exist for most; spelling word lists need   licence review). **Doc:** [typography-parity.md](typography-parity.md)diff --git a/docs/localization-parity.md b/docs/localization-parity.md--- a/docs/localization-parity.md+++ b/docs/localization-parity.md@@ -64,7 +64,7 @@ eight of the twelve (cs, da, el, en_GB, fi, hu, it, nb, nl, pl, ro, ru, sq, sv, ## Document languages  InDesign 2026 hyphenates and spell-checks ~40 languages (Hunspell and Duden dictionaries).-DesignCraft hyphenates **English, Spanish, Portuguese and Norwegian** and spell-checks **English** only. Text language+DesignCraft hyphenates **English, Spanish, Portuguese, Norwegian, Greek and Russian** and spell-checks **English** only. Text language can be set per paragraph and character (Properties, Character panel) and drives quotes and locale shaping. See [typography-parity.md](typography-parity.md). diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md--- a/docs/target-app-parity.md+++ b/docs/target-app-parity.md@@ -59,7 +59,7 @@ they receive, setting type exactly, and basic editing that never fails. | Dimension | Weight | Ready | Remaining (Opus 5.5 h) | Evidence | Doc | |---|---|---|---|---|---| | Features (depth of each area) | 25% | 55% | 250–400 | 275 catalogue rows exist; many lack options (e.g. Books is 258 lines of engine code, Liquid Layout 329); see the area table | this file |-| Typography and composition fidelity | 15% | 45% | 120–200 | Knuth–Plass composer, keeps, grids, CJK, Arabic all exist; no comparison with InDesign's line breaks; optical kerning falls back to metrics (#181); overset rule differs (#180); hyphenation patterns for English, Spanish, Portuguese, Norwegian and Greek only | [typography-parity.md](typography-parity.md) |+| Typography and composition fidelity | 15% | 45% | 120–200 | Knuth–Plass composer, keeps, grids, CJK, Arabic all exist; no comparison with InDesign's line breaks; optical kerning falls back to metrics (#181); overset rule differs (#180); hyphenation patterns for English, Spanish, Portuguese, Norwegian, Greek and Russian only | [typography-parity.md](typography-parity.md) | | File formats | 20% | 40% | 150–250 (+10–30 for an INDD corpus) | INDD and INDT open through indd-utils, measured on synthetic bytes only (#21); IDML both ways and verified in InDesign 2026, but real-file bugs open (#193, #338, #339, #340); PDF export strong; PDF/X-4 only | [file-format-parity.md](file-format-parity.md) | | UI/UX fidelity | 15% | 45% | 120–180 | Measured InDesign 2026 look; but users report object copy/paste (#351, #348, #185, #164), right-click menus (#238, #187, #160), out-port threading (#352, #194, #165) failing | [ui-parity.md](ui-parity.md) | | Stability | 10% | 45% | 60–100 | Never-crash rules and last-resort guards; startup failures on some GPUs and machines (#334, #273, #220, #192, #167, #166); no CI runs the tests on pull requests | [gaps.md](gaps.md) |@@ -356,7 +356,7 @@ It is evidence of breadth: each item exists. It is not a claim of InDesign-level - Edit ▸ Menus (`window.hideMenuItem`): hide menu items; menus with hidden items end in Show All Menu Items. - View ▸ Separations Preview (`view.separations`): one process plate as ink density, or areas over an ink limit in red (a GCR preview of the rendered view; spot plates and the flattener preview aren't there). - Separations Preview plates now come from each object's own colour (CMYK as authored; RGB and images through the colour settings, images via a cached 17³ table), so pure black shows only on the black plate.-- Language (Character panel ▸ Language, Properties ▸ Character, `type.char {language}`): text in other languages isn't hyphenated or spell-checked with the English dictionaries, typographer's quotes follow the language (German „…“, French and Russian «…», Swiss, Spanish, Dutch, Nordic, Japanese and Traditional Chinese 「…」, Simplified Chinese “…”), the font's localized forms (OpenType `locl`: Turkish i, Bulgarian Cyrillic, Japanese / Chinese / Korean glyph variants) follow it too, and so does the fallback for CJK characters the font lacks (with Draw Missing Glyphs from Fallback Fonts on): Japanese, Simplified Chinese, Traditional Chinese and Korean each try their own installed system fonts (Japanese starts with the craft-fonts Japanese faces, Mincho first, when built with them; Hangul, kana and Bopomofo pick their language's fonts whatever the language). Language names from IDML keep their spelling; locale codes as InDesign writes them for some languages (`de_DE_2006`, `nl_NL_2005`; any `ll`, `ll_CC`, `ll-CC`) are their language and region for all of the above, and Chinese is also recognised in its common spellings ("Simplified Chinese", "Chinese (Traditional)", `zh_CN`, `zh-Hant`). Spanish is hyphenated with Javier Bezos's Liang patterns (`hyph-es.tex` 5.0, MIT), Portuguese with hyph-utf8's `hyph-pt.tex` 1.4 (BSD-3-Clause) and Norwegian with hyph-utf8's `hyph-no.tex` (permissive), all through the `hypher` crate; hyphenation for other languages isn't bundled yet.+- Language (Character panel ▸ Language, Properties ▸ Character, `type.char {language}`): text in other languages isn't hyphenated or spell-checked with the English dictionaries, typographer's quotes follow the language (German „…“, French and Russian «…», Swiss, Spanish, Dutch, Nordic, Japanese and Traditional Chinese 「…」, Simplified Chinese “…”), the font's localized forms (OpenType `locl`: Turkish i, Bulgarian Cyrillic, Japanese / Chinese / Korean glyph variants) follow it too, and so does the fallback for CJK characters the font lacks (with Draw Missing Glyphs from Fallback Fonts on): Japanese, Simplified Chinese, Traditional Chinese and Korean each try their own installed system fonts (Japanese starts with the craft-fonts Japanese faces, Mincho first, when built with them; Hangul, kana and Bopomofo pick their language's fonts whatever the language). Language names from IDML keep their spelling; locale codes as InDesign writes them for some languages (`de_DE_2006`, `nl_NL_2005`; any `ll`, `ll_CC`, `ll-CC`) are their language and region for all of the above, and Chinese is also recognised in its common spellings ("Simplified Chinese", "Chinese (Traditional)", `zh_CN`, `zh-Hant`). Spanish is hyphenated with Javier Bezos's Liang patterns (`hyph-es.tex` 5.0, MIT), Portuguese with hyph-utf8's `hyph-pt.tex` 1.4 (BSD-3-Clause) Norwegian with hyph-utf8's `hyph-no.tex` (permissive) and Russian with hyph-utf8's `hyph-ru.tex` (Lebedev, LPPL 1.2+), all through the `hypher` crate; hyphenation for other languages isn't bundled yet. - Books (`book.new/open/add/remove/list/styleSource/paginate/syncStyles/exportPdf`, Book panel): `.dcbook` files, continuous page numbering, chapter numbers resolved in book order (Automatic, Start Chapter Numbering at, Same as Previous Document; `layout.chapterNumbering`, with a style for Chapter Number variables and cross-references), style sync from a style source, one merged PDF. Section prefixes follow InDesign's rule (up to 8 characters, no + or comma). - Numbering & Section Options window as in InDesign (Start Section, automatic or explicit page numbering up to 99999, prefix, style, marker, Include Prefix; the document's chapter numbering and its book); OK applies both in one undo step (`layout.numberingOptions`). - Book numbering/style updates validate and serialize all targets before changing the first chapter. They write only closed native chapters, checking canonical paths for open aliases; IDML remains a read-only style source and PDF input. Snapshots are staged on disk with at most 4,096 chapter records in memory. Each replacement is atomic; a later write failure explicitly lists completed chapters rather than claiming whole-book rollback. Import/serialization memory limits and advanced book TOC/index work remain separate.diff --git a/docs/typography-parity.md b/docs/typography-parity.md--- a/docs/typography-parity.md+++ b/docs/typography-parity.md@@ -36,7 +36,7 @@ Fidelity: **unmeasured** unless stated. | Single-line Composer | greedy | greedy with the same ranges | ✓ | | | World-Ready composers | Paragraph / Single-line World-Ready | RTL, Arabic and bidi in the main composer | ~ | Indic scripts (Devanagari etc.) shape through harfrust but are untested | | Justification | word/letter spacing, glyph scaling min/desired/max, single-word, last line | all of these | ✓ | a justified line with a tab justifies after the tab (#284); set per paragraph in Type › Justification… and the Paragraph panel menu (#531) |-| Hyphenation | per-language dictionaries (~40), zone, limits, capitalized, last word, across columns | Liang patterns: English (trained from the public-domain Moby list), Spanish (Bezos), Portuguese (hyph-pt), Norwegian (hyph-no) and Greek (hyph-el-monoton); zone, limits, exceptions in the user dictionary | ~ | other languages don't hyphenate (#87 reported "doesn't work") |+| Hyphenation | per-language dictionaries (~40), zone, limits, capitalized, last word, across columns | Liang patterns: English (trained from the public-domain Moby list), Spanish (Bezos), Portuguese (hyph-pt), Norwegian (hyph-no), Greek (hyph-el-monoton) and Russian (hyph-ru); zone, limits, exceptions in the user dictionary | ~ | other languages don't hyphenate (#87 reported "doesn't work") | | Spelling | per-language dictionaries | English (Moby) + document/user dictionary | ~ | | | Kerning | Metrics, Optical, manual, none | Metrics, Optical (outline-based: pairs pulled towards the font's stem gap, `crates/compose/src/optical.rs`), manual, none | ~ | Optical is an approximation of Adobe's algorithm (#181), not a match: imported display text can still break differently | | Tracking, scale, skew, baseline shift | ✓ | ✓ | ✓ | |