Files
pdfcraft/crates/ui-egui/Cargo.toml
T
9ce6d89f46 i18n: interface translations from craft-i18n (#6055)
* build(i18n): embed the craft-i18n catalogs from a pinned checkout

- `craft-i18n.rev` pins storytold/craft-i18n at e45ddf7 (the PdfCraft cutover sync of
  pdfcraft@ecdd1e6); `.gitattributes` keeps it LF.
- The `craft-i18n` crate (craft-libs 787a7a0, PdfCraft's existing pin) is a direct dependency
  of the UI crate; it was already in the tree through craft-ui.
- `crates/ui-egui/build.rs` writes `CRAFT_I18N` from `CRAFT_I18N_DIR`: one (locale, common.tsv,
  pdfcraft.tsv) entry per locale with a `pdfcraft.tsv`, paths written with `{:?}` and never
  canonicalized. Unset it is empty (English only); `CRAFT_I18N_REQUIRED=1` makes a missing or
  invalid checkout an error.
- Both flatpak manifests name the craft-i18n commit and `CRAFT_I18N_DIR`; a test keeps both
  commits equal to the trimmed pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(i18n): look strings up through craft-i18n behind a thin Lang wrapper

`i18n.rs` keeps PdfCraft's API (tr, tr_ctx, tr_id, trn, key_name, fmt,
Lang, LANGUAGES, detection) and hands lookups to the craft-i18n crate:
`get` for key names, `trn_plain` for plurals (no isolates, no digit
grouping), PdfCraft's own `fmt` (no FSI isolates). `@id` rows and the
"Undo {action}" template are read only where PdfCraft had them, so menus
and history labels read exactly as before.

Detection is unchanged (LC_ALL/LC_MESSAGES/LANG, macOS defaults,
sys_locale); the crate's match_tag would drop nb for no/nn, so PdfCraft's
own tag mapping stays, with one parity test per path.

Completeness tests become reports; tests that need catalogs skip with a
note when the build has none. Font coverage tests read the embedded
catalogs (shared and PdfCraft rows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(i18n): remove the in-repo catalogs; craft-i18n holds them

The 34 `crates/ui-egui/src/i18n/*.tsv` catalogs were migrated into
craft-i18n at pdfcraft@ecdd1e6 and are now embedded from the pinned
checkout. ATTRIBUTION.toml drops their 34 entries for one craft-i18n
`[[build_input]]` (craft-i18n's ATTRIBUTION.md credits the translators);
AGENTS.md and docs/localization.md describe the new system and how to
add a language.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(i18n): skip catalog tests without craft-i18n; drop the catalog hash exemption

Tests that switch to a non-English language skip with a note when the
build embeds no catalogs (CRAFT_I18N_DIR unset), so the English-only
build tests green. `skip_without_catalogs` moves to the integration
test support module.

With no catalogs left in the repository, `cargo xtask assets` no longer
exempts `crates/ui-egui/src/i18n/*.tsv` from hashing: every `[[asset]]`
carries a sha256 again, and a `.tsv` added back would need one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* build(i18n): watch the locales directory before reading it

A CRAFT_I18N_DIR that doesn't exist yet now reruns the build script once it appears (review).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* build(i18n): pin craft-i18n dfbe955, the merge of storytold/craft-i18n#129

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(i18n): skip an @id row that changes the label's placeholders or ellipsis

craft-i18n checks placeholders and the trailing ellipsis on every row whose
source is English text, but not on @id rows, whose source is the command id.
The in-repo catalog test used to fail on such a row; since the cutover it only
prints it, while tr_id and menu_label still showed it. Both now use PdfCraft's
own @id row only when it keeps the label's shape (same_shape, the rule
craft-i18n applies elsewhere), and otherwise show the label's translation, as
bundled_catalogs_are_consistent says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(i18n): reject an @id row with an open brace; list unused @id rows in the gaps report

same_shape skipped a `{` with no `}`, so an @id row such as "Öffnen {name…"
for "Open…" was still shown. It now counts as a changed shape.

bundled_catalogs_are_consistent printed the @id rows PdfCraft doesn't use, but
CI captures test output, so nobody saw them. translation_gaps_report, which
`cargo xtask i18n-report` runs with --nocapture, now lists them
(unused_id_rows).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(i18n): reject an @id row with a `}` that closes no placeholder

same_shape counted only the `}` that close a `{`, so "Öffnen name}…" for
"Open…" or "{name}} öffnen" for "Open {name}" still passed. A row whose `}`
count differs from its placeholders now counts as a changed shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(i18n): no braces in the assert messages of the brace test

assert! reads its message as a format string, so "a `}` without its `{`"
did not compile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
2026-11-04 00:47:17 +01:00

111 lines
5.2 KiB
TOML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[package]
name = "pdfcraft-ui-egui"
description = "The egui shell of PdfCraft"
version.workspace = true
edition.workspace = true
license.workspace = true
rust-version = "1.95"
[lints]
workspace = true
[dependencies]
craft-ui = { workspace = true }
# The menus: native on macOS, an egui bar elsewhere, from one definition (menus.rs).
craft-menu = { workspace = true }
craft-keymap = { workspace = true }
# Interface translations over the embedded craft-i18n catalogs (`build.rs`, `src/i18n.rs`).
craft-i18n = { workspace = true }
# Quit from the menus asks the window to close, so the unsaved-changes check runs; on macOS a window
# close also quits through `terminate:` (the Touch Bar crash, #1136).
craft-quit = { workspace = true, features = ["egui"] }
pdfcraft-fonts = { workspace = true }
pdfcraft-engine = { workspace = true }
pdfcraft-cos = { workspace = true }
pdfcraft-content = { workspace = true }
pdfcraft-render = { workspace = true }
pdfcraft-model = { workspace = true }
pdfcraft-platform = { workspace = true }
egui = { workspace = true, features = ["bytemuck", "default_fonts", "monochrome_emoji_fonts"] }
egui_extras = { workspace = true }
eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "persistence", "links", "clipboard"] }
serde = { workspace = true }
serde_json = { workspace = true }
log = { workspace = true }
# UTC/calendar display (combine modified-time stamp, the form date picker) goes through chrono
# (no hand-rolled calendar code); std-only, so it stays wasm-safe.
chrono = { workspace = true }
# Monotonic deadlines for work that runs in `logic` with no UI pass (native and web).
web-time = { workspace = true }
# Hands rendered rasters to egui as its pixels, without copying; already in the tree through egui and wgpu.
bytemuck = { version = "1", features = ["extern_crate_alloc"] }
rfd = { workspace = true }
png = "0.18"
base64 = "0.23"
# Unicode bidi paragraph segmentation for right-to-left comment wrapping; egui 0.37's epaint owns
# display reordering. Already in the tree through egui’s epaint.
unicode-bidi = "0.3"
# Checks that an installed fallback font parses and has the glyphs, and reads the vertical metrics
# that put fallback faces on the interface's baseline (#1676); the same skrifa egui uses.
skrifa = "0.44"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
craft-update = { workspace = true }
# Control-channel tokens.
getrandom = "0.4"
# Create ▸ Clipboard (images; already in the tree through egui-winit).
arboard = { version = "3.6", default-features = false, features = ["image-data"] }
# Waits for native file pickers off the UI thread (already in the tree through wgpu).
pollster = "1.0"
[target.'cfg(all(unix, not(target_os = "macos"), not(target_arch = "wasm32")))'.dependencies]
# Discover configured font directories without linking libfontconfig or running a subprocess.
fontconfig-parser = "0.5.8"
[target.'cfg(target_os = "macos")'.dependencies]
# Safe AppKit calls for drag coordinates and repairing an existing per-file PDFCraft binding.
# The Objective-C wrappers and block support are already in the tree through arboard and rfd.
objc2 = "0.6"
objc2-app-kit = { version = "0.3", default-features = false, features = ["std", "NSEvent", "NSScreen", "NSWorkspace", "block2"] }
objc2-foundation = { version = "0.3", default-features = false, features = ["std", "NSArray", "NSGeometry", "NSBundle", "NSURL", "NSString", "NSError"] }
block2 = "0.6"
plist = "1.10"
# A plain fsync where a volume refuses the full flush `sync_all` asks for (SMB, FUSE); already in
# the tree through pdfcraft-cli.
rustix = { version = "1", features = ["fs"] }
[target.'cfg(windows)'.dependencies]
# Auto interface language: the Windows display language, without starting a process.
sys-locale = "0.3"
# Region ▸ Measurement system for the default Units, read from the registry without starting reg.exe;
# where the pointer is while files are dragged over the window (winit doesn't say).
winsafe = { version = "0.0.29", default-features = false, features = ["advapi", "user"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
rfd = { workspace = true, features = ["file-handle-inner"] }
wasm-bindgen-futures = "0.4"
wasm-bindgen = "0.2"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["Window", "Document", "Element", "HtmlElement", "HtmlAnchorElement", "Blob", "BlobPropertyBag", "Url", "HtmlIFrameElement", "HtmlImageElement", "HtmlCollection", "Node", "EventTarget", "Navigator"] }
[dev-dependencies]
craft-update = { workspace = true }
pdfcraft-xfa = { workspace = true }
egui_kittest = { workspace = true, features = ["eframe", "wgpu"] }
# Tests draw PdfCraft text without a system provider: the bundled and monochrome emoji faces must
# be enabled on the test graph itself (a dependency's dev-features do not propagate).
egui = { workspace = true, features = ["default_fonts", "monochrome_emoji_fonts"] }
image = { version = "0.25", default-features = false, features = ["png"] }
# Glyph-coverage test of the interface fonts; the same skrifa pdfcraft-fonts already uses.
skrifa = "0.44"
proptest = { workspace = true }
[build-dependencies]
serde_json = { workspace = true }
toml = "1"
[target.'cfg(target_os = "macos")'.dev-dependencies]
# Only synthetic attribute fixtures use xattr; product reads/writes use rustix.
xattr = "1.6"