Commit Graph
37 Commits
Author SHA1 Message Date
e6df6b1384 i18n: add complete Ukrainian interface translation (#509)
* M14: add complete Ukrainian interface translation

Add the uk registry entry and original catalog, Ukrainian integer plurals,
calendar month inflection, attribution and localization documentation.
Fit Home recommendation cards and the search hint to translated text.
Cover locale detection, persistence, catalogs, bundled glyphs and UI control.

Fixes #503
Related to #348

Co-authored-by: Codex <[email protected]>

* uk: add the recent-files labels, labels that reach tl!() through a variable, and 'Inserted text'; fix 'мають мати'

* uk: Home / End are key-cap names

---------

Co-authored-by: Codex <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-09 12:55:46 -04:00
f626db25cc M14: refine German labels and prevent translated UI text overlap (#515)
* M14: refine German labels and keep translated text within UI bounds

Co-authored-by: Codex <[email protected]>

* Tool names inside notices stay lowercase in English; German keeps its capitalised nouns

---------

Co-authored-by: Codex <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-09 12:39:57 -04:00
Márk BartalosandBrandon Thomas 95120862fc M14: Hungarian interface catalog (hu) (#545)
* M14: Hungarian interface catalog (hu)

Magyar joins the interface languages as a complete catalog, so Preferences and hu locales show commands, dialogs, panels and notices in Hungarian. Wording uses informal "te" and nouns for commands; the strings were written from the meaning of the English labels.

* Small grammar correction

* hu: restore trailing spaces in run-on labels; add the recent-files labels and labels that reach tl!() through a variable

---------

Co-authored-by: Brandon Thomas <[email protected]>
2026-10-09 12:28:06 -04:00
7c358099ff M14: German interface catalog (de) (#471)
* M14: German interface catalog (de)

Deutsch (`de`) joins the interface languages as a complete catalog of
2,035 entries: every command, All tools entry, dialog, panel and notice.
It is selected from Preferences, and Auto picks it for `de`, `de_DE`,
`de_AT`, `de_CH` and other German locales. Wording uses the informal
"du" and the infinitive for commands; translations are clean-room, written
from the meaning of the English labels.

- de.tsv registered in LANGUAGES (plural rule one|other)
- tests: registration and locale mapping, plurals, coverage of every
  command, All tools label and tl! literal, history labels keeping user
  values; the Latin UI faces cover umlauts, ß and German quotes; the
  control-channel language switch includes `de`
- ATTRIBUTION.toml/.md entry (kind = "translation"), docs/localization.md,
  ROADMAP and parity notes

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: register German as the 12th language; translate the reopen-session preference (de, bg)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-09 09:26:15 -04:00
Brandon Thomas 37542ad9db Merge remote-tracking branch 'origin/main' into dmg-background
# Conflicts:
#	ATTRIBUTION.md
2026-10-09 09:21:35 -04:00
DimitarandClaude Opus 5.5 79eadc2aa8 M14: Bulgarian (Български) interface language (#466)
A complete clean-room catalog (2,035 entries: every command, All tools
label and tl! literal), registered as `bg` with one/other plurals so Auto
picks it on Bulgarian systems. Tests mirror the Russian ones (registration,
plurals, persistence, command and literal coverage), and Bulgarian joins
the Latin/Cyrillic font-coverage test.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-09 09:16:16 -04:00
Xus BadiaandClaude Opus 5.5 084f7636ea macOS DMG: branded window background and icon layout
The DMG opened as a plain Finder window. It now shows the app icon's figure on
the PdfCraft colour, with PdfCraft.app and the Applications link side by side.
Same approach as PhotoCraft's and VectorCraft's.

- packaging/macos/dmg/: background.svg (source; text outlined, no paper grain,
  the figure an <image> of assets/app-icon), background.tiff (1x + 2x HiDPI,
  16-colour palette, Deflate, sRGB; ~95 KB) and dmg-layout.DS_Store (Finder
  view settings: window, icon size 128, positions, background).
- generate.py writes the TIFF and the layout on any OS, byte-for-byte
  reproducible, with nothing from the machine that ran it.
- package.sh copies them into the staging folder; the image is still built with
  hdiutil makehybrid. Nothing extra runs in the signing job.
- The volume name drops the version: the layout finds the background through
  an alias that includes the volume name. The DMG file name keeps the version.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-09 07:38:19 +02:00
4995da0653 i18n: add Russian (ru) interface translation (#375)
* i18n: add Russian (ru) interface translation

- Add ru.tsv catalog (~1950 entries, clean-room translations following PhotoCraft terminology: Слой, Образцы, Обработка контуров, Монтажная область, Обводка, Заливка)
- Register ru in LANGUAGES with plural_russian (one/few/many with 11-14 exception)
- Add Russian tests: registration, command/catalogue coverage, UI literals, history/diagnostics, plural forms
- Add ATTRIBUTION.toml entry for ru.tsv
- Update docs/localization.md, ROADMAP.md with Russian language
- All i18n tests pass, cargo fmt and clippy clean

* ru: translate labels added on main since the catalog was written; Russian in the Latin-font coverage test

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* ru: '>' in the JavaScript-off hint, as the other catalogs (Inter has no ▸)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 19:24:51 -04:00
MarekSpodBiedryandBrandon Thomas 2f42c743b9 Issue #157: the Windows portable zip keeps settings, logs and recovery beside pdfcraft.exe (#325)
* Issue #157: the Windows portable zip keeps settings, logs and recovery beside pdfcraft.exe

The portable zip had no portable.txt, and the app had no portable mode: it always wrote %APPDATA%\PdfCraft and %LOCALAPPDATA%\PdfCraft. Now portable.txt (or PdfCraft.portable) beside the executable puts the settings, log files, crash recovery and new digital IDs in PdfCraftData next to it, as PhotoCraft does, and the zip ships portable.txt. An unwritable PdfCraftData falls back to the per-user folders and says so.

* Issue #157: update ATTRIBUTION.toml SHA-256 for the translation catalogs this PR changes

---------

Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 17:29:59 -04:00
05c8ab3b3e M14: Telugu (తెలుగు) interface language (#349)
* M14: Telugu interface font

- The interface takes `Telu` faces from craft-fonts after the CJK and Arabic ones, on the web too
- Test: Telugu text has glyphs in every family and its conjuncts are shaped

Signed-off-by: Chiranjeevi U <[email protected]>

* M14: Telugu interface language

- Complete te catalog: 1,984 entries plus whole-phrase Undo/Redo; te and te_IN locales use it
- Undo and Redo labels use a catalog phrase when the language has one (Telugu puts the verb last)
- Tests, docs, attribution, parity and ROADMAP

Signed-off-by: Chiranjeevi U <[email protected]>

* Add my contributor name (chiranjeevi-max)

Signed-off-by: Chiranjeevi U <[email protected]>

* M14: catalog contexts for labels with two meanings

- tl_ctx! gives the signature pad's Type, the Action Wizard's Start and the comment menu's Edit their own context; Telugu translates them, other languages keep their current translation
- Preferences' All tools goes through the catalog in every language

Signed-off-by: Chiranjeevi U <[email protected]>

* M14: Telugu for the look-alike web address warnings

Signed-off-by: Chiranjeevi U <[email protected]>

* M14: Telugu for the image signature notices

Signed-off-by: Chiranjeevi U <[email protected]>

* Telugu for Open Recent (#323)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Signed-off-by: Chiranjeevi U <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 17:00:25 -04:00
7458f7d47d M14: complete Simplified Chinese About credits and multiline guidance (#311)
Co-authored-by: Codex <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 13:39:40 -04:00
cd8c753527 M14: French interface catalog (#291)
Add Français (fr) as a complete UI catalog and select it for every
French locale. Preferences lists it, and Auto follows fr, fr_FR,
fr_CA and fr_BE. About credits labels now go through the catalog.

Coverage tests check commands, All tools labels and every tl! literal.
The bundled Latin faces cover the catalog.

Co-authored-by: Cursor Agent <[email protected]>
Co-authored-by: iMhack <[email protected]>
2026-10-08 11:16:30 -04:00
Sameh ElhawaryandClaude Opus 5.5 d30bb111db M14: Arabic and Hebrew file names render in the tab strip, recent files and Properties (#285)
A tab named in Arabic showed replacement boxes: no interface font had the
glyphs, and egui joins the letters of a right-to-left word but places the
runs in logical order.

- Fonts: the interface takes `Arab` faces from the craft-fonts build input
  (also on wasm), and on desktop adds one font already installed on the
  machine as the last fallback of every family. It is read at runtime, never
  embedded; PDFCRAFT_SYSTEM_FONTS=0 turns it off and `cargo xtask screenshots`
  sets that. AGENTS.md §1.4 records the rule.
- Order: bidi::visual puts single-line text in display order with a
  left-to-right base, used for the painted tab label and hover text, the
  recent-files name and path, and the Properties File and Location rows.
  Accessibility names keep the logical text.

misc.rtl-ui stays planned: multi-line text, text input and a mirrored layout
are not done.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 10:46:58 -04:00
7f4677dc93 Release: Flatpak bundles, AppImage zsync updates, README Downloads (#275)
* Release: Flatpak bundles (x86_64, aarch64), AppImage zsync updates, README Downloads

- AppImages embed gh-releases-zsync update information and ship a .zsync beside them;
  the Linux job installs zsync and checks both.
- New flatpak job (x86_64 on ubuntu-24.04, aarch64 on ubuntu-24.04-arm) repackages the
  Linux tarball with packaging/linux/flatpak-bundle.sh and the new bundle manifest, then
  smoke-tests it in the sandbox. finish-args shared with the Flathub manifest (packaging-lint
  checks they match): Wayland/X11, dri, CUPS for printing, Documents and Downloads.
- Only the signing jobs and the draft-release job keep `environment: release`, so a branch
  dispatch is a dry run of everything else and can never draft a release.
- README: a Downloads section listing every build; docs/releasing.md updated.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Flatpak: no CUPS socket (the runtime has no lp); document printing as unavailable there

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 09:58:13 -04:00
4db49900c6 Add Spanish (es) interface catalog (#251)
Registers Español in the language list, with a full catalog covering
commands, dialogs, panels and notices, plus tests and docs.


Claude-Session: https://claude.ai/code/session_01A3kqJC1D3PAgT3dHxnqYNy

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-08 07:17:26 -04:00
Gert Pellin - GPE 1d31c230c9 Desktop: write log records to standard error and a rotating log file (#239)
The desktop app installed no logger, so every log::warn!/log::error! in
the workspace was discarded: a failed autosave, a page that would not
render, a render worker that could not start. A launch from a desktop
menu has no terminal either, so there was nothing to attach to a bug
report.

apps/pdfcraft/src/logging.rs (no new dependency besides log):
- standard error plus <settings dir>/logs/pdfcraft.log, next to app.ron
  (Linux $XDG_DATA_HOME/pdfcraft); each launch rotates the previous log
  to pdfcraft.1.log and .2.log, so the log of a run that crashed
  survives the next start; the file is capped at 16 MiB
- records logged before the settings directory is known are buffered
  (bounded) and written once the file is attached
- default levels: info for pdfcraft*, warn for everything else;
  RUST_LOG replaces them with env_logger-style directives
- never panics: an unusable directory or a failed write leaves standard
  error as the only sink

The logger is installed first in main, so the panic hook's report is
recorded too; the start-up messages in main go through it. The file is
opened after argument parsing (--version leaves no file) and after the
PrintCraft folder migration, which a fresh settings folder would block.
Documented in docs/development.md (Logs, environment variables).
2026-10-08 05:48:52 -04:00
932967a30d Restore #196, #202, #203 and the macOS release-runner change, reverted by the i18n chain (#229)
* Release CI: macOS job on macos-15-xlarge

Custom macOS larger runners in a runner group do not pick up jobs; the
built-in M2 Pro label does. Only release.yml uses it, and the
actions_macos_xl budget caps the monthly spend.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 90d60b0c98)

* CI: tell actionlint about the org's macos-release runner label (#202)

Co-authored-by: Claude Opus 5.5 <[email protected]>
(cherry picked from commit ddea3c72e0)

* About: contributor and model credits compiled in (grab bag + table, self-submitted names) (#196)

* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)

Adds About ▸ Contributors and About ▸ Models tabs per the craftrules standard
(standards/contributors.md): contributors/contributors.json is generated by
craftrules/scripts/contributors.py and baked into the binary by crates/ui-egui/build.rs as
static tables; nothing is read at run time. Each contributor line: @username, opt-in
display/real name, PRs, commits, lines +/−/Δ, binary assets +/−, first/last commit.
Sortable by every column; alphabetical ignores case and the leading @.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section

build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: regenerate (verified people.toml entries)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 41e214c318)

* M13: exit cleanly when stdout pipe closes (#203)

Co-authored-by: Brandon Thomas <[email protected]>
(cherry picked from commit 1cf0d319e4)

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Ayan <[email protected]>
2026-10-08 03:33:35 -04:00
ec980d0743 fix(i18n): follow Windows display language for Chinese UI (#216)
* fix(i18n): follow Windows display language for Chinese UI

M14: resolve Auto through the Windows UI culture after locale environment
variables. Reuse Chinese region/script mapping and cover the query and
fallback behavior.

Refs #215

Co-authored-by: Codex <[email protected]>

* Windows Auto language: ask Windows directly instead of starting PowerShell

sys-locale (1Password, MIT OR Apache-2.0) reads GetUserPreferredUILanguages, so
Auto no longer launches a hidden powershell.exe at startup (slow, and the kind of
behaviour endpoint security tools flag). All preferred display languages are
tried in order.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Codex <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-08 01:19:07 -04:00
才倾梦华VandBrandon Thomas 77893e8ab3 M14: complete Simplified Chinese translation catalog (#209)
* M14: complete Simplified Chinese translation catalog

* M14: translate new XFA notices and counts

---------

Co-authored-by: Brandon Thomas <[email protected]>
2026-10-07 23:45:02 -04:00
355de9038e i18n: Simplified Chinese UI language option (#112)
* i18n: Czech interface language

Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.

- i18n: `Language::Cs`; `tr()` picks the language's table with a match
  (English has none), panic-free. The CZECH table (83 entries) covers
  every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
  entries, Preferences dialog), every registered File/Edit/Pages/View/Help
  command shown by `registry_menu`, and every key of the Japanese table.
  Written clean-room from the English meaning, not from any Acrobat
  localisation.
- Tests: Czech covers every registered menu title and label, every
  `.tr("…")` literal found by scanning the crate's sources, and the
  Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
  list ("OK"); ellipses match the source; keys are unique per language;
  `cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
  checks with skrifa (dev-dependency, already in the tree via egui) that
  Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
  and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
  for misc.prefs-language and the ROADMAP log mention Czech.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: add Traditional Chinese (Taiwan) UI localization

Co-Authored-By: Codex <[email protected]>

* M14: translate shortcuts and expose language preferences in Edit menu

Add command-comma and verify language switching through the actual selector.

Co-authored-by: Codex <[email protected]>

* M14: expand Traditional Chinese dialogs, panels and diagnostics

Preserve opaque values in translated templates and keep application diagnostics at the UI boundary. Extend native control and template regression coverage.

Co-authored-by: Codex <[email protected]>

* M14: finish Traditional Chinese signature prompts and history labels

Translate generated action labels without changing filenames or field names. Complete checkbox styles, resolution labels and native picker filters.

Co-authored-by: Codex <[email protected]>

* M14: complete Japanese dialogs, panels, shortcuts and diagnostics

Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.

Co-authored-by: Codex <[email protected]>

* i18n: Simplified Chinese UI language option

Adds Language::Zh alongside en/ja (--language zh, preferences switch,
persisted): full Chinese translation table covering every user-visible
label, generic Hans font fallback plumbing, and a build.rs skip-guard
plus test so Noto CJK is never embedded (AGENTS.md 1.1). Pairs with
storytold/craft-fonts#5 (ChillRoundF Regular, OFL-1.1 Adobe-free
chain), which supplies the Hans glyphs. Also fixes a startup deadlock
from translating inside lazy widget_info closures.

* i18n: add Brazilian Portuguese (pt-br) UI translation

Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Brazilian Portuguese as a TSV catalog

Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Czech as a TSV catalog

Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.

The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: route every UI string through the catalog; Japanese as ja.tsv

Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
  become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
  egui temp-data copy of the language) are gone: the drawing language
  is the per-thread `i18n::current()`, set from the preference at the
  start of each frame. Worker threads (export, OCR, batch actions) take
  the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
  and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
  errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
  OS messages against English templates breaks silently whenever the
  wording changes. Error details are shown as they are, inside the
  translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
  captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
  labels have glyphs with the desktop faces and with the web subset
  (with craft-fonts); history labels; #141's control tests, with the
  error-detail expectation updated.

Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Preferences in the Edit menu, Cmd/Ctrl-comma

Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.

Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Traditional Chinese as zh-hant.tsv

Reduce #140 to its translations: zh_tw.rs becomes
crates/ui-egui/src/i18n/zh-hant.tsv (PrintCraft renamed PdfCraft; the
29 errors.rs diagnostic templates dropped, as for Japanese) and one
registry row, code `zh-hant` (Taiwan vocabulary). Locales zh_TW, zh_HK,
zh_MO and zh-Hant-* resolve to it. #140's own copy of the UI wiring and
its errors.rs diagnostics are not taken: land/141 carries the wiring.
Tests: registration, locale mapping, every command label translated.
The catalog is an attributed asset; docs, ROADMAP and parity list it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Simplified Chinese as zh-hans.tsv

Reduce #112's translations to crates/ui-egui/src/i18n/zh-hans.tsv
(PrintCraft renamed PdfCraft) and one registry row, code `zh-hans`
(#112 used `zh`; `zh`, `zh_CN`, `zh_SG` and `zh-Hans` locales still
resolve to it through the system-language match). #112's own copy of
the UI wiring is superseded by land/141. Tests: registration, locale
mapping, menu coverage. The catalog is an attributed asset; docs,
ROADMAP and parity list it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: CJK font order follows the UI language

From #112: `ui_cjk_fonts(prefer_hans)` orders the craft-fonts CJK faces
for the interface, and `theme::font_definitions_for` installs them. In
Simplified Chinese the `Hans` faces come first; otherwise the Japanese
ones (the previous behaviour). egui draws each character with the first
face that has it, so with Japanese first a Simplified-only character
(欢) would land in another face and sit on a different baseline. The
fonts are reinstalled when the language crosses that line (same family
names, so named fonts stay valid while the new set loads).

Changes from #112: within each group BIZ UDPGothic still leads, so a
serif listed first in the manifest (Shippori Mincho) never becomes the
Chinese-mode UI fallback; the unused `document_chinese_font` is left
out; and the crates/fonts/build.rs special case that skipped
"Noto Sans CJK SC" (and its test assertion and README line) is not
taken. Without CRAFT_FONTS_DIR, or without a `Hans` face, the order
logic yields only what exists: Chinese characters then show replacement
boxes and nothing panics (tests/fonts.rs, the fonts crate test, and the
control test switching ja -> zh-hans -> en).

Also document `--language` on the app's command line.

Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: sakamoto824 <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
2026-10-07 22:17:00 -04:00
ab4c87926a M14: expand Traditional Chinese UI, dialogs and language preferences (#140)
* i18n: Czech interface language

Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.

- i18n: `Language::Cs`; `tr()` picks the language's table with a match
  (English has none), panic-free. The CZECH table (83 entries) covers
  every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
  entries, Preferences dialog), every registered File/Edit/Pages/View/Help
  command shown by `registry_menu`, and every key of the Japanese table.
  Written clean-room from the English meaning, not from any Acrobat
  localisation.
- Tests: Czech covers every registered menu title and label, every
  `.tr("…")` literal found by scanning the crate's sources, and the
  Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
  list ("OK"); ellipses match the source; keys are unique per language;
  `cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
  checks with skrifa (dev-dependency, already in the tree via egui) that
  Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
  and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
  for misc.prefs-language and the ROADMAP log mention Czech.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: add Traditional Chinese (Taiwan) UI localization

Co-Authored-By: Codex <[email protected]>

* M14: translate shortcuts and expose language preferences in Edit menu

Add command-comma and verify language switching through the actual selector.

Co-authored-by: Codex <[email protected]>

* M14: expand Traditional Chinese dialogs, panels and diagnostics

Preserve opaque values in translated templates and keep application diagnostics at the UI boundary. Extend native control and template regression coverage.

Co-authored-by: Codex <[email protected]>

* M14: finish Traditional Chinese signature prompts and history labels

Translate generated action labels without changing filenames or field names. Complete checkbox styles, resolution labels and native picker filters.

Co-authored-by: Codex <[email protected]>

* M14: complete Japanese dialogs, panels, shortcuts and diagnostics

Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.

Co-authored-by: Codex <[email protected]>

* i18n: add Brazilian Portuguese (pt-br) UI translation

Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Brazilian Portuguese as a TSV catalog

Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Czech as a TSV catalog

Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.

The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: route every UI string through the catalog; Japanese as ja.tsv

Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
  become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
  egui temp-data copy of the language) are gone: the drawing language
  is the per-thread `i18n::current()`, set from the preference at the
  start of each frame. Worker threads (export, OCR, batch actions) take
  the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
  and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
  errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
  OS messages against English templates breaks silently whenever the
  wording changes. Error details are shown as they are, inside the
  translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
  captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
  labels have glyphs with the desktop faces and with the web subset
  (with craft-fonts); history labels; #141's control tests, with the
  error-detail expectation updated.

Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Preferences in the Edit menu, Cmd/Ctrl-comma

Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.

Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Traditional Chinese as zh-hant.tsv

Reduce #140 to its translations: zh_tw.rs becomes
crates/ui-egui/src/i18n/zh-hant.tsv (PrintCraft renamed PdfCraft; the
29 errors.rs diagnostic templates dropped, as for Japanese) and one
registry row, code `zh-hant` (Taiwan vocabulary). Locales zh_TW, zh_HK,
zh_MO and zh-Hant-* resolve to it. #140's own copy of the UI wiring and
its errors.rs diagnostics are not taken: land/141 carries the wiring.
Tests: registration, locale mapping, every command label translated.
The catalog is an attributed asset; docs, ROADMAP and parity list it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
2026-10-07 22:16:34 -04:00
a4340d34c8 M14: complete Japanese dialogs, panels, shortcuts and diagnostics (#141)
* i18n: Czech interface language

Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.

- i18n: `Language::Cs`; `tr()` picks the language's table with a match
  (English has none), panic-free. The CZECH table (83 entries) covers
  every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
  entries, Preferences dialog), every registered File/Edit/Pages/View/Help
  command shown by `registry_menu`, and every key of the Japanese table.
  Written clean-room from the English meaning, not from any Acrobat
  localisation.
- Tests: Czech covers every registered menu title and label, every
  `.tr("…")` literal found by scanning the crate's sources, and the
  Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
  list ("OK"); ellipses match the source; keys are unique per language;
  `cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
  checks with skrifa (dev-dependency, already in the tree via egui) that
  Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
  and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
  for misc.prefs-language and the ROADMAP log mention Czech.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: complete Japanese dialogs, panels, shortcuts and diagnostics

Expand Japanese from 49 to 1830 interface entries, expose language preferences in the Edit menu, preserve opaque template and history values, and localize known application diagnostics only at the UI boundary. Add control, persistence, template and desktop/web glyph regressions.

Co-authored-by: Codex <[email protected]>

* i18n: add Brazilian Portuguese (pt-br) UI translation

Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Brazilian Portuguese as a TSV catalog

Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Czech as a TSV catalog

Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.

The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: route every UI string through the catalog; Japanese as ja.tsv

Port #141's wiring to the catalog API from land/106:
- `crate::i18n::tr(ui, s)` becomes `tl!(s)`, `tr_fmt`/`tr_template`
  become `i18n::fmt(tl!(..), ..)`, and `Language::get`/`store` (the
  egui temp-data copy of the language) are gone: the drawing language
  is the per-thread `i18n::current()`, set from the preference at the
  start of each frame. Worker threads (export, OCR, batch actions) take
  the UI's language with them for their summaries.
- ja.rs (1,830 pairs) becomes ja.tsv, merged with the existing entries
  and renamed PrintCraft -> PdfCraft. The 29 diagnostic templates of
  errors.rs are dropped.
- `Language::diagnostic` and errors.rs are dropped: matching engine and
  OS messages against English templates breaks silently whenever the
  wording changes. Error details are shown as they are, inside the
  translated frame ("{label} failed: {e}").
- History labels (`command_label`/`action_label`) move into i18n and keep
  captured file and field names; registry menus prefer `@id` entries.
- Preferences: Auto plus every registered language, relabelled at once.
- Tests: Japanese covers every command and All tools entry; Japanese
  labels have glyphs with the desktop faces and with the web subset
  (with craft-fonts); history labels; #141's control tests, with the
  error-detail expectation updated.

Co-Authored-By: shuiyue-cmyk <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Preferences in the Edit menu, Cmd/Ctrl-comma

Split out of #141: register app.preferences in the Edit menu with the
platform's usual shortcut (Command-comma on macOS, Ctrl-comma
elsewhere), so the interface language can be found and changed with no
document open. Shortcut keys may now be punctuation (egui's key name
","). #141's control test drives the menu item, the language selector
and the shortcut in Japanese and English.

Co-Authored-By: sakamoto824 <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Petr Leo Compel <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Codex <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
Co-authored-by: shuiyue-cmyk <[email protected]>
2026-10-07 22:16:07 -04:00
f0f923b82e i18n: Czech interface language (#68)
* i18n: Czech interface language

Adds Czech (Čeština, code `cs`) next to English and Japanese:
Preferences ▸ Interface language, `ui.set language cs`, `ui.state`
and persisted preferences all accept it.

- i18n: `Language::Cs`; `tr()` picks the language's table with a match
  (English has none), panic-free. The CZECH table (83 entries) covers
  every label passed to `.tr("…")` (main menu, View zoom/theme/side-panel
  entries, Preferences dialog), every registered File/Edit/Pages/View/Help
  command shown by `registry_menu`, and every key of the Japanese table.
  Written clean-room from the English meaning, not from any Acrobat
  localisation.
- Tests: Czech covers every registered menu title and label, every
  `.tr("…")` literal found by scanning the crate's sources, and the
  Japanese keys; nothing is left identical except an explicit KEEP_AS_IS
  list ("OK"); ellipses match the source; keys are unique per language;
  `cs` round-trips through set_option, ui.set/ui.state and persistence.
- theme: the font setup is split into `font_definitions()`, and a test
  checks with skrifa (dev-dependency, already in the tree via egui) that
  Inter Regular/Medium/SemiBold and JetBrains Mono draw all Czech letters
  and every Czech translation, so nothing falls back to Shippori Mincho.
- The `language` error lists `cs`; docs/localization.md, the parity note
  for misc.prefs-language and the ROADMAP log mention Czech.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* i18n: add Brazilian Portuguese (pt-br) UI translation

Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Brazilian Portuguese as a TSV catalog

Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Czech as a TSV catalog

Move #68's Czech table into crates/ui-egui/src/i18n/cs.tsv (PrintCraft
labels renamed PdfCraft, plus Auto) and register it with PhotoCraft's
Czech plural rule (one / few / other). #68's tests become catalog
tests: Czech covers every registered menu title and menu command label,
keeps ellipses, uses no three-dot ellipsis or stray whitespace, and only
leaves "OK" untranslated; the code persists and `cz` is rejected. The
source-scanning `.tr("…")` test is dropped: strings now go through tl!
and the catalog tests check consistency.

The font-coverage test moves to tests/fonts.rs and covers both Latin
catalogs (cs, pt-br) against Inter and JetBrains Mono. It keeps skrifa
as a dev-dependency (the version pdfcraft-fonts already uses): egui's
has_glyphs can't answer it, since a family with only the primary face
also uses that face as its replacement face.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: RicSchonfelder <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
2026-10-07 22:15:39 -04:00
41734376be i18n: add Brazilian Portuguese (pt-br) UI translation (#165)
* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* i18n: add Brazilian Portuguese (pt-br) UI translation

Adds Language::PtBr (code pt-br, endonym Português (Brasil)) with serde rename so it persists as "pt-br", registers it in Language::ALL (Preferences ▸ Interface language and ui.set/ui.state) and translates the same 49 menu/command keys as the Japanese table. Extends the i18n tests (table parity, codes, persistence) and updates docs/localization.md.

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* M14: Brazilian Portuguese as a TSV catalog

Move #165's Portuguese table into crates/ui-egui/src/i18n/pt-br.tsv
(same 49 strings, plus Auto) and register it in LANGUAGES with
PhotoCraft's Portuguese plural rule (0 and 1 singular). Any Portuguese
locale (pt_BR, pt_PT, pt) follows the Brazilian catalog, as in
PhotoCraft. The catalog is an attributed asset (ATTRIBUTION.toml), and
the docs and parity notes list the new code.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Simon Leblanc <[email protected]>
Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
2026-10-07 22:15:26 -04:00
a07243c8ff M14: translation catalogs, same system as PhotoCraft (#106)
* M14: translation catalogs, same system as PhotoCraft

Move the interface translations to PhotoCraft's i18n system: one TSV
catalog per language (crates/ui-egui/src/i18n/ja.tsv), the tl! macro,
entries keyed by command id, context or plural forms, and catalog tests
(format, duplicates, placeholders, command ids).

The 49 existing Japanese strings move over unchanged, plus "Auto". The
language preference now defaults to "auto" and follows the system
language (English when it has no catalog); "en" and "ja" still persist
and unknown values are rejected.

Update docs/localization.md, ROADMAP.md and the misc.prefs-language
parity entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

* M14: strict catalog validation, one-pass fmt, translation assets

Fold in the infrastructure parts of #175:
- `fmt` fills placeholders in one pass, so inserted values (a file name
  containing `{n}`) are never substituted again.
- Catalog validation rejects unknown escapes, unknown `@` contexts,
  placeholder, ellipsis and plural-form mismatches and duplicates. The
  bundled catalogs must have no errors (tests); at run time a bad line is
  still only skipped and logged, so the rest of the catalog loads.
- `.tsv` files count as assets in `cargo xtask assets`, with a
  `translation` kind that may never come from Adobe; ja.tsv gets its
  ATTRIBUTION.toml entry.
- Control-channel test: switching the language keeps documents, their
  dirty state and command ids.

Also make the drawing language thread-local, as in PhotoCraft, so
parallel kittest harnesses can't change each other's language.

Co-Authored-By: 才倾梦华V <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: 才倾梦华V <[email protected]>
2026-10-07 22:14:50 -04:00
Brandon ThomasandClaude Opus 5.5 41e214c318 About: contributor and model credits compiled in (grab bag + table, self-submitted names) (#196)
* About: contributors compiled in from contributors.json (grab bag + table, sortable, name toggle)

Adds About ▸ Contributors and About ▸ Models tabs per the craftrules standard
(standards/contributors.md): contributors/contributors.json is generated by
craftrules/scripts/contributors.py and baked into the binary by crates/ui-egui/build.rs as
static tables; nothing is read at run time. Each contributor line: @username, opt-in
display/real name, PRs, commits, lines +/−/Δ, binary assets +/−, first/last commit.
Sortable by every column; alphabetical ignores case and the leading @.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: self-submitted names in contributors/people.toml; AGENTS.md credit-yourself section

build.rs reads contributors/people.toml next to the generated contributors.json and shows a name only
for entries the generator verified as written by that person (craftrules standards/contributors.md).

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: regenerate (verified people.toml entries)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 22:12:01 -04:00
9e0fcc1380 #143: Windows MSI desktop shortcut checkbox, Start Menu fix and install-complete dialog (#183)
* #143: Windows MSI desktop shortcut checkbox and install-complete dialog

Add native installer dialogs (installer-ui.wxs): a welcome screen with a
"Create a desktop shortcut" checkbox (ticked by default), repair/remove,
progress, and "Setup completed successfully" / failed / cancelled screens
with Finish. Unattended /qn and /qb installs never wait on a dialog and can
skip the desktop shortcut with INSTALLDESKTOPSHORTCUT=0.

Start Menu and desktop shortcuts are now plain links to pdfcraft.exe in
their own components (HKLM key paths, removed on uninstall) instead of
advertised MSI shortcuts.

test-msi.ps1 checks the compiled MSI's shortcut, checkbox and dialog tables
during packaging; the ARM64 install smoke test checks both shortcut
targets, their removal on uninstall, and the INSTALLDESKTOPSHORTCUT=0
opt-out.

Co-authored-by: ChatGPT <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JqiBTPWGWbhQDYNFcxFte6

* #143: run test-msi out of process before signing; add files-in-use dialog

test-msi.ps1 held the MSI open through a Windows Installer COM handle in
package.ps1's own process, so signtool could fail on signed release builds.
Run it in a child process and release the COM objects.

The hand-authored UI had no MsiRMFilesInUse dialog, so an upgrade or repair
while PdfCraft is running could not offer to close it. Add one (OK closes the
programs with MSIRMSHUTDOWN=2, Cancel stops setup) and check for it in
test-msi.ps1.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JqiBTPWGWbhQDYNFcxFte6

---------

Co-authored-by: ChatGPT <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-07 21:38:02 -04:00
Brandon ThomasandClaude Opus 5.5 d3db99818f Rename PrintCraft to PdfCraft (#174)
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now
PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the
PrintCraft settings and crash-recovery folders to the new name, and both apps read settings
saved under the old storage key, so upgrades keep recent files, preferences and unsaved work.
The signing test fixtures keep their PrintCraft subject names (they are binary).

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-07 16:03:57 -04:00
bflatasticandClaude Opus 5.5 032373b2a9 Docs: docs/releasing.md, which release.yml has always pointed to (#100)
release.yml's comments say "See docs/releasing.md", but the workflow came
over from PhotoCraft without its document. It now describes PrintCraft's
pipeline as it is: cutting a release and test runs, every artifact
(including Windows on ARM64), the craft-fonts pin, each platform's
packaging, signing and notarization, the release-environment secrets,
and the packaging checks.

Written from release.yml and the packaging scripts. It says plainly that
the binaries don't embed the commit yet, and packaging/env.sh no longer
points to a build_info.rs that doesn't exist.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-07 09:46:23 +07:00
Brandon ThomasandClaude Opus 5.5 1d67833599 Fonts: use craft-fonts as an optional build input; move the Japanese fonts out
Shippori Mincho (and its OFL file) leaves assets/fonts/: the Japanese fonts now
live in storytold/craft-fonts. printcraft-fonts gets craft-fonts' build.rs recipe:
with CRAFT_FONTS_DIR=<checkout> it embeds the manifest's fonts as CRAFT_FONTS
(wasm32: only BIZ UDPGothic Regular); without it CRAFT_FONTS is empty and the
app builds, tests and runs as before, minus the Japanese face.

- SHIPPORI_MINCHO is now Option<&[u8]> from CRAFT_FONTS; japanese_glyph
  (was shippori_glyph) uses document_japanese_font() (Shippori Mincho, then
  BIZ UDMincho, then any Jpan face) and returns GlyphError::NoFont without one.
- Editing PDF text into Japanese without craft-fonts is a clear EditError that
  leaves the page untouched.
- UI: every Jpan craft font (BIZ UDPGothic first) is the last fallback of
  every egui family, sharing the same static bytes.
- Tests: Japanese glyph/edit tests skip without craft-fonts; new UI tests for
  no-tofu Japanese with craft-fonts and working fonts without it.
- CI: the Linux test job checks out craft-fonts at a pinned SHA and runs the
  tests with CRAFT_FONTS_DIR. Releases build every platform with it
  (CRAFT_FONTS_REQUIRED=1) and ship each font's OFL as OFL-<family>.txt.
- ATTRIBUTION.toml gains [[build_input]] (checked by xtask assets); NOTICE,
  AGENTS.md, CLAUDE.md, README and docs say fonts live in craft-fonts.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 11:36:23 -04:00
c9d6d39071 Add persisted English/Japanese interface language (#47)
* i18n: add persisted English and Japanese interface language

* ROADMAP: the language entry goes at the top of the log, dated

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: midasdf <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-05 17:10:09 -04:00
Brandon ThomasandClaude Opus 5.5 d20eef9d56 Licensing: standard LICENSE files, NOTICE, ArtCraft brand terms
Adopt the shared Crafting Apps licensing standard. LICENSE-MIT names "ArtCraft Team and the
PrintCraft contributors"; LICENSE-APACHE matches the standard byte for byte; NOTICE gets the
standard header and brand paragraph above the existing third-party list. docs/brand/LICENSE-brand.txt
now holds the ArtCraft Team brand terms: the marks may be used only unmodified within PrintCraft,
and forks and modified versions must remove them. The brand entries in ATTRIBUTION.toml, AGENTS.md
§1.2 and the README follow suit, and the README's Licence section becomes the standard
"License and credits" block. xtask inherits the workspace licence.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-04 10:07:05 -04:00
Brandon ThomasandClaude Opus 5.5 2fc7cb4e64 Community links: Discord button in the title bar, ArtCraft community card on Home, About dialog with ArtCraft mark/wordmark and links, Help menu commands (help.discord/app_page/github/website), CLI --version and MCP websiteUrl, README Community section; 4 Lucide icons (attributed); regenerated screenshots with honest brand attribution
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 14:15:05 -04:00
Brandon ThomasandClaude Opus 5.5 bb31b5a1b5 Brand assets: ArtCraft logos attributed as Storyteller-owned (not open source, LicenseRef-Storyteller-Trademark) with a narrow asset-gate exception for docs/brand logos; AGENTS.md §1.2
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-01 14:02:40 -04:00
Brandon ThomasandClaude Opus 5.5 5f5f83cc0c Session 4: M1.6 encryption (crypt crate R2-R6), M4 command registry, combine/extract/split, autosave + crash recovery, asset policy + xtask assets, README screenshots
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 23:12:34 -04:00
Brandon Thomas 5f61bde5eb more work 2026-09-30 11:34:29 -04:00
Brandon Thomas 108fdc108c more progress, roadmap, wip 2026-09-30 11:00:02 -04:00