* M14: add Lithuanian interface localization
Register Lithuanian UI and date languages with three integer plural forms
and a 2,572-entry contributor-original catalog. Cover dynamic dialog labels,
contextual calendar and certificate wording, commands, tools, and every key
in the other bundled catalogs. Add real-shell calendar, inspector and
password-dialog regressions; preserve PDF values and document state.
Update localization documentation and asset attribution. Native-speaker/VLKK
terminology review remains outstanding.
Validation: cargo xtask ci passed; cargo-deny was skipped because it is not
installed. Five rendered dialogs and contributor manual testing checked UI.
Co-Authored-By: OpenAI gpt-6.1-sol <noreply@openai.com>
* M14: preserve multilingual localization documentation
Restore the existing language descriptions instead of replacing general
localization guidance with Lithuanian-specific coverage. List every
registered language and control-channel code; keep Lithuanian details
alongside the existing catalog descriptions.
Include the previously omitted Kazakh, Polish, Slovenian, Greek and Turkish
catalogs in the shipped-language table without changing the historical
coverage snapshot or existing assessments. Keep Lithuanian roadmap notes
concise and additive.
Validation: all 22 registered languages appear in documentation; every
existing descriptive paragraph is retained. cargo xtask ci passed, with
cargo-deny skipped because it is not installed.
Co-Authored-By: OpenAI gpt-6.1-sol <noreply@openai.com>
* M14: record completed Lithuanian native-speaker review
The contributor confirms they are a native Lithuanian speaker and have
reviewed the translation. Remove obsolete pending-review labels from the
asset manifest and documentation; regenerate ATTRIBUTION.md. Remove the
redundant generated-message disclaimer from the Lithuanian description,
keeping the existing general localization documentation unchanged.
Validation: cargo xtask ci passed; cargo-deny was skipped because it is
not installed. Catalog content and its SHA-256 are unchanged.
Co-Authored-By: OpenAI gpt-6.1-sol <noreply@openai.com>
* Lithuanian: cover main's Copy Image labels, list lt last, check its glyphs
Adds the six Copy Image rows from #1363, moves lt to the end of LANGUAGES
and DATE_LANGUAGES (after tr), adds lt.tsv to the primary-font coverage
test, writes the JavaScript preferences path with '>' as the other
catalogs do (Inter has no ▸), and refreshes counts and hashes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: OpenAI gpt-6.1-sol <noreply@openai.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A widget whose /P is a page number past the end of the document (here
/P 99 in a one-page file) kept that page, and the Fields panel indexed
the page list with it to label the heading, which panicked. A page the
document doesn't have now gets the existing "Unplaced" heading.
Adds forms::the_fields_panel_lists_a_field_on_a_missing_page_as_unplaced,
which fails before this change.
* Forms: keep tiles and render unbaked field values during page re-render
In complex interactive forms, switching focus away from an edited field
caused its text to disappear for several seconds while background tiles
re-rendered.
- In DocView, retain existing tiles as stale rather than immediately
purging them on page_changed so the canvas remains sharp without flashing.
- Prioritize visible tiles over backdrops in the render queue.
- Track unbaked form fields and paint an immediate egui widget preview
for committed text, checkbox, and radio inputs until fresh raster
tiles arrive.
- Scope page invalidation on form edits to pages containing the edited
or calculated fields.
- Hoist fields lookup in recalculate_with and apply_changes to eliminate
repeated parsing.
- Run JavaScript scripts via catch_unwind on the current thread instead of
spawning a new thread per script invocation.
- Add contributor entry for Piohrun in contributors/people.toml.
- Add test switching_fields_keeps_committed_text_visible_immediately.
* Forms: address review feedback on tile stale tracking, hoist, and diff invalidation
- Revert crates/js to preserve dedicated 1 GiB stack thread for boa scripts.
- In DocView::page_changed, purge non-current-tag tiles and mark only current-tag tiles stale.
- Restore demand queue order in prepare_render_queue.
- Add unbaked overlay entries only on successful edit apply and only for fields whose values changed; fix font zoom calculation on 90°/270° pages.
- Re-read fields(doc) in recalculate_with only when script returns changes.
- Diff form before and after edit in apply_edit, invalidating pages with changed fields, falling back to document_changed for XFA or page-count changes.
- Add tests covering script recalculation side effects across pages, unbaked overlay cleanup on tile delivery/zoom/rejection, and checkbox recalc chaining.
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* fix(forms): refresh the editor after accepted Tab edits
* test(forms): keep values through same-field Tab and Save
* docs: record accepted-value Tab and Save behavior
* docs: log verified Tab save regression
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Preserve the selected document when an earlier inactive tab closes. Clear the reverted document's form drafts and queued edit only after a successful Revert.
Co-authored-by: sanyamsingh001 <314051937+sanyamsingh001@users.noreply.github.com>
Co-authored-by: Codex <codex@openai.com>
The ui-egui integration tests drive the shell by its English labels, and
`i18n::system_lang` returns `Lang::EN` under `cfg!(test)` so they can. That
only covers the unit tests: an integration test links the library as it
ships, where `cfg!(test)` is off, so `PdfCraftApp::new()` leaves `language`
on `auto` and the shell is drawn in the system language. On a Spanish
Windows eleven of the test binaries fail; a French, Russian, Chinese,
Japanese, Portuguese, Czech or Telugu machine does the same. CI never sees
it because its locale is English.
`tests/theme.rs` and `tests/create.rs` already pin the option; the other
119 harnesses now do too, and the comment in `system_lang` says why, so a
test copied from an existing one keeps the line.
Also `i18n::tests::windows_display_language_query_returns_a_locale_tag`
treated the return of `windows_ui_language()` as a single tag. It is the
preferred-language list, one tag per line, as `first_supported` reads it,
so on a Windows with two or more display languages the assertion tripped
over the newline. It now checks the shape of every line.
Co-authored-by: Fernando Areán <soporte@codebit.es>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* Issue #166: Save, Print and Export include the text still being typed in a form field
A field's editor kept its text in a draft until Enter, Tab or clicking away,
and ⌘S (which runs while a field has focus) saved the document first. Typing
also didn't count as unsaved, so closing or quitting didn't ask.
- commit_form_typing(): apply the tab's queued edit, then commit the open
field's draft; if the field refuses the value, keep the editor and text
and stop. Called where the document is read: Save, Save As (and its later
callback), Print, Export, Reduce/Optimize, Sign, Extract, Split, Copy
pages, Flatten, button scripts.
- Uncommitted typing counts as unsaved work for Close, Close All and Quit;
saving from the prompt brings that tab forward first.
- Shortcuts pressed while a form field's editor is open run one frame later,
for that document only, so the field takes the frame's typing and Escape.
- A value refused on Enter/Tab/blur reopens the field with the text.
- Notices show in full screen too.
Co-authored-by: Hal Goff <hal@hg.studio>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Add my contributor name (AutoHenry)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
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 <noreply@anthropic.com>