mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-24 10:08:00 -06:00
Merge r2 track t12: i18n, i18n: new language catalogues
# Conflicts: # ATTRIBUTION.toml
This commit is contained in:
+9
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
Every asset PdfCraft includes, bundles or uses to build its published material, with its author, source and licence. The policy is in [AGENTS.md](AGENTS.md) §1. The machine-readable list, with SHA-256 hashes, is [ATTRIBUTION.toml](ATTRIBUTION.toml). Licence texts are kept beside the assets and summarised in [NOTICE](NOTICE).
|
||||
|
||||
## In this repository (276)
|
||||
## In this repository (283)
|
||||
|
||||
| Asset | Title | Author | Licence | Source | Used for |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -13,9 +13,10 @@ Every asset PdfCraft includes, bundles or uses to build its published material,
|
||||
| `crates/ui-egui/src/i18n/zh-hant.tsv` | Traditional Chinese (Taiwan) interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Traditional Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/cs.tsv` | Czech interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Czech UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/pt-br.tsv` | Brazilian Portuguese interface translation catalog | André Cardoso (andrecards), PdfCraft contributors | MIT OR Apache-2.0 | Clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources: the ~1,826-entry gist posted in issue #288 (https://gist.github.com/andrecards/ac388c25fba17312ce83207f8b7b467e), completed and reviewed by PdfCraft contributors | Brazilian Portuguese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/es.tsv` | Spanish interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/es.tsv` | Spanish interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources; the 2026-10-20 coverage additions are AI-assisted and not separately native-reviewed | Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/fr.tsv` | French interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | French UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/de.tsv` | German interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/lo.tsv` | Lao interface translation catalog | @bounkirdni-2025 | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft English UI labels, no proprietary localisation resources | Lao UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/te.tsv` | Telugu interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Telugu UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/it.tsv` | Italian interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Italian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/pl.tsv` | Polish interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Polish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
@@ -26,8 +27,11 @@ Every asset PdfCraft includes, bundles or uses to build its published material,
|
||||
| `crates/ui-egui/src/i18n/ja.tsv` | Japanese interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Japanese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/uk.tsv` | Ukrainian interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Ukrainian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/ar.tsv` | Arabic interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/ckb.tsv` | Central Kurdish (Sorani) interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Central Kurdish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/tr.tsv` | Turkish interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Turkish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/lt.tsv` | Lithuanian interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels and user-facing messages; original catalog reviewed by a native Lithuanian-speaking contributor; 2026-10-15 coverage additions are AI-assisted and not separately native-reviewed | Lithuanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/ro.tsv` | Romanian interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels and user-facing messages; AI-assisted and not yet reviewed line by line by a native Romanian speaker | Romanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/fi.tsv` | Finnish interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: AI-assisted (Claude Code) clean-room translations of PdfCraft's English UI labels and user-facing messages; not yet proofread by a native Finnish speaker | Finnish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `assets/icons/accessibility.svg` | Lucide icon "accessibility" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/accessibility.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
| `assets/icons/align-left.svg` | Lucide icon "align-left" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/align-left.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
| `assets/icons/align-center.svg` | Lucide icon "align-center" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/align-center.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
@@ -284,6 +288,9 @@ Every asset PdfCraft includes, bundles or uses to build its published material,
|
||||
| `assets/icons/subscript.svg` | Lucide icon "subscript" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/subscript.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
| `assets/icons/pilcrow.svg` | Lucide icon "pilcrow" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/pilcrow.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
| `assets/icons/move-horizontal.svg` | Lucide icon "move-horizontal" | Lucide Contributors (portions Cole Bemis, Feather) | ISC | https://github.com/lucide-icons/lucide (npm lucide-static 1.49.0, icons/move-horizontal.svg) | UI icon, embedded via crates/ui-egui/src/icon_data.rs |
|
||||
| `crates/ui-egui/src/i18n/sq.tsv` | Albanian interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Albanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/th.tsv` | Thai interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources | Thai UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
| `crates/ui-egui/src/i18n/ca.tsv` | Catalan interface translation catalog | PdfCraft contributors | MIT OR Apache-2.0 | Contributor-original: clean-room translations of PdfCraft's English UI labels, written from their meaning; no proprietary localisation resources | Catalan UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs |
|
||||
|
||||
## Compiled in through dependencies (6)
|
||||
|
||||
|
||||
+78
-1
@@ -69,7 +69,7 @@ sha256 = "60a49a50f21d711deb636a8dd415c1963094d9b36dc1b36d48f906e3364e3c92"
|
||||
path = "crates/ui-egui/src/i18n/es.tsv"
|
||||
title = "Spanish interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources; the 2026-10-20 coverage additions are AI-assisted and not separately native-reviewed"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
@@ -98,6 +98,17 @@ kind = "translation"
|
||||
usage = "German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "59f25c35ea03cd767c8b98a1f908183b2d51d48baad7b70b86c0a702e344ed26"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/lo.tsv"
|
||||
title = "Lao interface translation catalog"
|
||||
author = "@bounkirdni-2025"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft English UI labels, no proprietary localisation resources"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Lao UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "e01dc586811c5eeedc57b502e457971bc1916506e88a902d05014fcf4f65b180"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/te.tsv"
|
||||
title = "Telugu interface translation catalog"
|
||||
@@ -208,6 +219,17 @@ kind = "translation"
|
||||
usage = "Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "998ff7c8ace4315a31c623cd416745a61efd4aad18e73253cae0e92f8147d897"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ckb.tsv"
|
||||
title = "Central Kurdish (Sorani) interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Central Kurdish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "2479d8f164612c4e8d3944df9a6b2ae345be0b26ee87511b17a4a56bc41988d3"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/tr.tsv"
|
||||
title = "Turkish interface translation catalog"
|
||||
@@ -230,6 +252,28 @@ kind = "translation"
|
||||
usage = "Lithuanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "c3f85494bc13d6a9a82429e074b79d28ef71f97eb4e40edc3dd4b8fa4bd223c6"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ro.tsv"
|
||||
title = "Romanian interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels and user-facing messages; AI-assisted and not yet reviewed line by line by a native Romanian speaker"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Romanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "19d949a60f8ade450b8e1ef594aa5f6a6c0e95f7dc6538b338680d38ac599b42"
|
||||
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/fi.tsv"
|
||||
title = "Finnish interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: AI-assisted (Claude Code) clean-room translations of PdfCraft's English UI labels and user-facing messages; not yet proofread by a native Finnish speaker"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Finnish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "15f86d82e5ac6f65f8cf3ca50ba2b4116cc7f5c8e70f9ad5d9e48ed4a9082eb0"
|
||||
|
||||
[[asset]]
|
||||
path = "assets/icons/accessibility.svg"
|
||||
@@ -3420,3 +3464,36 @@ licence_file = "assets/icons/LICENSE-lucide.txt"
|
||||
kind = "icon"
|
||||
usage = "UI icon, embedded via crates/ui-egui/src/icon_data.rs"
|
||||
sha256 = "864ab2f19254e6ac7240bc6a98323197332e8f714d4d3f94831f41309e5ef2f7"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/sq.tsv"
|
||||
title = "Albanian interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Albanian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "c7318e459d44360a1efbc11aa5590b16e4d4e4b4da6111ec543a85b3b748ec17"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/th.tsv"
|
||||
title = "Thai interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, no proprietary localisation resources"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Thai UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "a9e20f819001357ea548b3d05ea0a6484a228c3079effdf7d33f437f6207f11f"
|
||||
|
||||
[[asset]]
|
||||
path = "crates/ui-egui/src/i18n/ca.tsv"
|
||||
title = "Catalan interface translation catalog"
|
||||
author = "PdfCraft contributors"
|
||||
source = "Contributor-original: clean-room translations of PdfCraft's English UI labels, written from their meaning; no proprietary localisation resources"
|
||||
licence = "MIT OR Apache-2.0"
|
||||
licence_file = "LICENSE-MIT"
|
||||
kind = "translation"
|
||||
usage = "Catalan UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs"
|
||||
sha256 = "d370a02b9cdfa693f96fa3a318ff8973c2ceec1b088b6e7879e38a7c03e4ec59"
|
||||
|
||||
+16
-6
@@ -25,6 +25,7 @@
|
||||
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** minor (M6: preserve XML/XFDF attribute whitespace; estimates unchanged) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-14 · **Change:** minor (M1: raw-deflate fallback preserves decoding-limit errors; estimates unchanged) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-16 | **Last updated:** 2026-10-16 | **Change:** minor (M10 #1201 partial: lossless image Decode; estimates unchanged) | **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-15 · **Last updated:** 2026-10-16 · **Change:** minor (M14: Czech catalog completed and reviewed; estimates unchanged) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-14 · **Change:** minor (M14: the Italian catalog has every entry the other catalogs had and the code looks up; estimates unchanged) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-14 · **Last updated:** 2026-10-14 · **Change:** minor (M3 #2080 candidate: explicit search jumps join per-tab history; rail and control-channel Back/Forward; estimates unchanged)
|
||||
> **Last reviewed:** 2026-10-13 · **Last updated:** 2026-10-13 · **Change:** minor (M4 #1910: Organize Pages opens on the current page; estimates unchanged) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
@@ -146,18 +147,18 @@ What's strong and missing in each: [target-app-parity.md](docs/target-app-parity
|
||||
|
||||
## Languages
|
||||
|
||||
Twelve key languages (historical % snapshot vs 2,143 keys, except Vietnamese vs the current
|
||||
union). Detail and script notes: [localization-parity.md](docs/localization-parity.md).
|
||||
Twelve key languages (historical % snapshot vs 2,143 keys, except Vietnamese, Brazilian
|
||||
Portuguese and Spanish vs the current union). Detail and script notes: [localization-parity.md](docs/localization-parity.md).
|
||||
|
||||
| Language | Code | Strings | Status |
|
||||
|---|---|---|---|
|
||||
| English | `en` | 100% | full |
|
||||
| Simplified Chinese | `zh-hans` | 97.4% | partial (no Hans UI face in releases, #826) |
|
||||
| Spanish | `es` | 95.5% | partial |
|
||||
| Spanish | `es` | 100% of current union | partial (dialogs / tooltips; no help) |
|
||||
| Hindi | `hi` | 0% | none |
|
||||
| Arabic | `ar` | 100% | partial (layout not mirrored) |
|
||||
| French | `fr` | 99.3% | partial |
|
||||
| Portuguese (Brazil) | `pt-br` | 99.4% | partial |
|
||||
| Portuguese (Brazil) | `pt-br` | 100% of current union | partial |
|
||||
| Indonesian | `id` | 0% | none |
|
||||
| Japanese | `ja` | 99.1% | partial |
|
||||
| German | `de` | 99.3% | partial |
|
||||
@@ -165,8 +166,8 @@ union). Detail and script notes: [localization-parity.md](docs/localization-pari
|
||||
| Vietnamese | `vi` | 100% of current union | partial (dialogs / tooltips; no help) |
|
||||
|
||||
Also shipped: Traditional Chinese, Russian, Bulgarian, Telugu, Hungarian, Ukrainian, Italian,
|
||||
Kazakh, Polish, Slovenian, Greek, Turkish, Lithuanian and Czech (menus only): **14 more catalogs**
|
||||
(23 interface languages including English).
|
||||
Kazakh, Polish, Slovenian, Greek, Turkish, Lithuanian, Romanian and Czech: **15 more catalogs**
|
||||
(24 interface languages including English).
|
||||
|
||||
## Upcoming
|
||||
|
||||
@@ -192,6 +193,7 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md
|
||||
- **2026-10-16 (M3, close prompt keyboard):** The "Save changes?" prompt opens with Save chosen (Enter saves, as before) and the arrow keys and Tab / Shift+Tab move the choice to Cancel or Don't save, shown with a focus ring; Enter or Space press the chosen button and Escape still cancels. Before, Enter always saved whatever was Tab-focused. Estimates unchanged.
|
||||
- **2026-10-21 (M3, #3808):** Page thumbnails in the Inspector can be resized independently from the document and Organize, with a slider, buttons and `thumbnail-zoom` control option. Selection, page following and reload are covered by regressions. Estimates unchanged.
|
||||
- **2026-10-22 (M2, #3107 / PR #3438):** Inline-image parsing falls back to the existing EI heuristic when missing declared samples, headers or terminators exceed the content-window budget, instead of waiting for an impossible allocation. Exact-length parsing for available samples and ordinary large streamed images is retained. Estimates unchanged.
|
||||
- **2026-10-21 (M14, Brazilian Portuguese):** Completed the `pt-br` catalog against the current 2,674-key union, including signature validation and accessibility messages; no build or compilation run. Localization remains partial because help and unpredictable engine/OS error details are not translated.
|
||||
- **2026-10-20 (M6, calculation order page):** Prepare a form ▸ Calculation order, a page of its own, lists the calculated fields in the order they calculate with their formulas and values, moved with Up/Down arrows (as Acrobat's Set Field Calculation Order), Alt+↑/↓ or by dragging. A card says what is wrong with the order and holds Fix order; a loop has a card of its own that opens one of its formulas. On the page, each calculated field shows its step, and arrows show what the field in focus reads and what reads it. Estimates unchanged.
|
||||
- **2026-10-20 (M6, calculation order):** The order a form's fields calculate in (`/CO`) is read, checked, fixed and set headlessly with `form_calculation_order`: it says which fields read one calculated later (they show stale values), which read each other in a loop, and which the PDF's order leaves out; Fix order moves only what must move, in one undo step, and the form recalculates. Editing a formula no longer moves its field to the end of the order, and a field the order lists twice calculates once. Estimates unchanged.
|
||||
- **2026-10-20 (M2, #3574):** Forms without Resources use page Properties for ActualText and layer visibility. Synthetic tests cover boundaries, nested/shared forms, and save/reopen. Estimates unchanged.
|
||||
@@ -246,6 +248,8 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md
|
||||
- **2026-10-19 (M7, tracked text):** Editable paragraphs and object labels distinguish repeated glyph tracking from word gaps in TJ arrays and separately positioned glyphs. Synthetic regressions cover character spacing, horizontal scaling, rotated baselines, larger word gaps, and rows of one-glyph words or cells (inferred tracking is capped at half an em, so `a b c` and digit or Y/N columns keep their spaces). Estimates unchanged.
|
||||
- **2026-10-16 (M5, #2669, item 5):** The Comments panel groups replies by name and counts all page roots once per frame. Estimates unchanged.
|
||||
- **2026-10-16 (M7, #2140):** Header & footer (and Bates numbering, which uses the same dialog) can shrink the page content so the header and footer don't cover it: the original content is scaled evenly into the band they leave free, centred across, also on rotated pages; Remove and Update take the scaling away, and margins that leave no room are refused. Dialog checkbox with a preview of the band, `shrink` on `doc_header_footer`, all catalogs. Annotations and added text and images are not moved yet. Estimates unchanged.
|
||||
- **2026-10-20 (M14, Spanish catalog gaps):** `es.tsv` gains the 143 `(context, English)` keys the other catalogs carried and it was missing, so Spanish covers the whole bundled key union like Lithuanian and Vietnamese: calendar months and weekdays, the `certificate` context, X.509 key usages, signature-revision and digital-ID lines, password validation, eight plural messages, the combine-from-folder strings, the rendering and stale-file notices and the shortcut-spelled tooltips. Counts in `localization-parity.md` re-measured against the current union (`vi` restated against it for the same reason). Status stays `partial`: no translated help, and OS details stay outside the catalog. Estimates unchanged.
|
||||
- **2026-10-16 (M14, localization):** Czech goes from menus-and-dialogs to the whole surface: 2,674 entries after adding the ~220 keys the other catalogs had -- the sentences the engine words (signature details, accessibility findings and report, PDF/A problems, pages to print, history labels), the date picker's weekday heads, the certificate viewer's fields and shared buttons. "Tag" is *tag* throughout (the Tags panel said *značky*, which is also a redaction mark), and "{n} tags" no longer reads "1 značek". Two new catalog tests. Estimates unchanged.
|
||||
- **2026-10-15 (M2, gap 12):** `cargo xtask text-oracle` scores reading order as well as word F1: the longest common subsequence of the two word sequences over the longer one. F1 is a bag of words and cannot see order at all -- measuring #2431, a change that moves text and nothing else, it called 26 of the 29 files whose output changed identical, where the order score separated 18 improvements from 6 regressions. Reports, does not gate; a disagreement with Poppler, not a verdict. Estimates unchanged.
|
||||
- **2026-10-15 (M2, #2305 follow-up):** WinAnsiEncoding 0xA0 and 0xAD and MacRomanEncoding 0xCA extract as the ordinary space and hyphen Annex D.2 names them, in the vendored hayro tables (patch 30) as well as `crates/fonts`, so search, copy and redaction see characters that were hidden behind U+00A0 and U+00AD. Across the pdf.js corpus the soft hyphens we extract fall 117 to 13 and the non-breaking spaces 30 to 26; the rest come from `/ToUnicode`. An explicit `/Differences` name keeps its glyph list value, as pdftotext does. Estimates unchanged.
|
||||
- **2026-10-15 (M12, XFA, #2574):** A `pageArea` with no `<occur>` repeats without limit instead of taking a subform's default of one use, so a later page area with `occur max="1"` is no longer drawn (with a copy of its fields) over every body page. A page area's `occur min` is honoured too: one the body never reached gets the pages it still needs after the body (the once-only closing page of a form, with its button, comes last). Acrobat Pro also puts that page last, and when printing keeps it but leaves it blank (`relevant="-print"` on the page area), which PdfCraft does not do yet; both re-observed on a synthetic fixture, see the 2026-10-19 line. Synthetic regression tests. Estimates unchanged.
|
||||
@@ -267,6 +271,7 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md
|
||||
- **2026-10-12 (gap 6, #1319, #1305, #1324):** Editing an XFA form keeps a radio item's stored text when it contains a space, so a later layout still selects it. Replace Pages on a split selection replaces those pages and leaves the gap; editing the dialog range still replaces the span. Marking a figure decorative rewrites only that figure's content stream, so a header, added text and unknown stream entries stay. Estimates unchanged.
|
||||
- **2026-10-15 (M14, gap 24):** `misc.localization` and `misc.installers` move from planned to partial. Localization: 22 catalogs ship, but Chinese shows tofu in releases, Telugu has no release font and Arabic is not mirrored. Installers: macOS and Windows releases are signed, Linux packages are not. The Acrobat menu diff itself remains open. Estimates unchanged.
|
||||
- **2026-10-15 (M14, PNG export):** Export ▸ Image as PNG, `pdfcraft-cli render` and the `page_render` automation/MCP tool write an opaque page as RGB at deflate level 3 instead of RGBA at the default level 6: the files stay the same size and are written 3–5× faster (a 300-dpi scan drawn at 220 dpi: 805 → 167 ms; a text page at 220 dpi: 70 → 40 ms; an annual-report page at 150 dpi: 179 → 64 ms). A page with translucent pixels is still written as RGBA. The automation tools use the engine's encoder instead of a copy of it. Estimates unchanged.
|
||||
- **2026-10-15 (G14, Romanian localization):** Added Romanian (`ro`, Română) as an interface and date language with a 2,673-entry catalog covering every bundled key, and a CLDR plural rule (`plural_ro`: one / few / other, "20 de pagini"). Locale tags `ro` / `ro-RO` / `ro_RO.UTF-8` / `ro-MD` resolve, so Auto picks it on Romanian Windows. Coverage and plural tests added. Status `partial` like the other catalogs (no translated help).
|
||||
- **2026-10-13 (G14, Vietnamese localization):** Added Vietnamese (`vi`, Tiếng Việt) as an interface and date language with a 2,591-entry catalog (`plural_none`) covering 100% of the current localizable key union (plus `theme`/`Appearance`). Locale tags `vi` / `vi-VN` / `vi_VN.UTF-8` resolve; calendar months use numeric `Tháng 1`…`12` / `tháng 1`…`12`. Native-speaker community review recorded. The twelve-language localization mean moves from ≈59% to ≈68%; weighted readiness ≈49% → ≈50%. Status stays `partial`: engine/OS details, document contents, filenames, CLI/MCP and external help stay outside the catalog by design.
|
||||
|
||||
- **2026-10-13 (M3, typed zoom):** The right rail's zoom percentage is an editable field: type 150, 150% or 62.5 % and press Enter, Escape discards, and nonsense keeps the current zoom. The control channel's zoom option shares its parser, which now refuses zero, negative and non-finite values.
|
||||
@@ -313,6 +318,9 @@ Ranked; detail and the full milestone table in [docs/roadmap.md](docs/roadmap.md
|
||||
- **2026-10-14 (M10, #1818):** Properties… reads a CUPS printer's driver options off the GUI thread, the dialog saying so meanwhile, and `lpoptions` is given ten seconds before it is killed and the PPD's defaults stand; a read that dies leaves the panel with nothing rather than a frozen window. The bounded wait is tested with a stand-in command that never answers.
|
||||
- **2026-10-14 (M10 #2156 candidate):** Print paper selection survives Cancel and settings restoration; canonical names avoid preset-index dependence. Other print preferences and estimates unchanged.
|
||||
|
||||
- **2026-10-15 (community, M14, Polish signature panel):** A Polish signature panel listed its details in English: the catalog lacked every signature wording, the changes after signing they name and 34 UI literals. All 101 are translated; `polish_covers_ui_literals` and `polish_says_what_a_signature_says` keep them so. Estimates unchanged.
|
||||
- **2026-10-14 (M14, Finnish localization):** Added Finnish as another interface and date language, with a 2,674-entry catalog covering every key of the other bundled catalogs and two-form plurals (partitive after numbers other than 1). Calendar dates use partitive month names (`14. lokakuuta 2026`). Coverage tests check commands/tools, scanned UI literals and bundled catalog keys. AI-assisted; native proofreading pending.
|
||||
- **2026-10-14 (M14, Catalan localization):** Added Catalan as another interface and date language, with a 2,592-entry clean-room catalog, one/other plurals and coverage tests for commands, tools, UI literals and every key in the other catalogs. A native Catalan speaker (the contributor) has reviewed the translation. Estimates unchanged.
|
||||
- **2026-10-13 (M3, native-opening candidate):** Chosen tools survive preparation, conversion and password retries; startup intake waits for pending preparation. Regression tests cover completion, cancellation and document identity. Estimates unchanged.
|
||||
- **2026-10-13 (community, M3, #531 touchpad momentum):** On Wayland a two-finger swipe keeps gliding after the fingers lift and slows to a stop, measured from the gesture's last 0.1 s and decaying with a 0.35 s time constant through the #759 1:1 path. Any wheel input, click, key, zoom or edge ends it (fingers resting on the touchpad don't yet: the vendored winit binds no Wayland hold gestures); single-page paging, macOS (which sends its own momentum), the web, and Animation effects Off never glide. Unit tests for the physics and two headless view tests. Estimates unchanged.
|
||||
- **2026-10-13 (M3, native-open admission):** Later prepared replies stay queued while a modal or native picker owns the foreground. Picker completion, cancellation and abandonment wake retained opens. Regressions cover recipient ownership, exactly-once admission, source/history preservation and one-shot repaint requests. Estimates unchanged.
|
||||
@@ -616,6 +624,7 @@ Newest first: the date, what moved, and the new overall estimate.
|
||||
| 2026-10-15 | minor | M6: Plain AcroForm XML imports retain all direct text around comments and processing instructions, including CDATA and character references. Estimates unchanged. |
|
||||
| 2026-10-13 | minor | M6: XML/XFDF attribute whitespace survives form and comment export/import; estimates unchanged |
|
||||
| 2026-10-14 | minor | M1: raw-deflate fallback preserves decoding-limit errors in strict and tolerant decoding; synthetic filter and COS stream regressions. Estimates unchanged. |
|
||||
| 2026-10-16 | minor | M14: Czech catalog completed (2,674 entries) and "tag" terminology unified. Estimates unchanged. |
|
||||
| 2026-10-13 | minor | M9: separate page validation overlays preserve signature artwork, and snapshot tabs reuse instead of multiplying; baked captions remain unchanged (#79 open); estimates unchanged |
|
||||
| 2026-10-16 | minor | M10 #1201 partial: lossless image export applies component Decode pairs and Indexed mapping. Estimates unchanged. |
|
||||
| 2026-10-15 | minor | M6: CSV export and spreadsheet merging quote tabs, and import distinguishes quoted tabs from TSV delimiters without changing field identities. Estimates unchanged. |
|
||||
@@ -650,3 +659,4 @@ Newest first: the date, what moved, and the new overall estimate.
|
||||
|
||||
- **2026-10-21 (M4, #3865):** A new bookmark records where the reader is: the top-left of the selected text, or the top of the window, as `/XYZ left top null` (zoom kept), instead of the page top (`Edit::AddBookmark` takes `left` and `top`; `bookmark_add` takes `top` and `left`; `PageInfo::xyz_for_view`).
|
||||
- **2026-10-18 (renderer, hayro patches 19/35):** A mesh shading (types 4–7) is sampled over its own triangles instead of the whole path: a BricsCAD plan with 310 one-triangle `sh` fills took 2 s per 1024 px tile at every zoom (and hit the 20 s watchdog on a busy machine); now about 70 ms, so zooming into dense topology drawings stays fluid. Estimates unchanged.
|
||||
- **2026-10-12 (i18n):** Albanian (`sq`, Shqip) added: 2,343-entry catalog, month and weekday names, Preferences entry; not yet reviewed by a native speaker.
|
||||
|
||||
@@ -57,7 +57,7 @@ pub struct HeaderFooter {
|
||||
/// Left, centre and right header text, then left, centre and right footer text. Tokens:
|
||||
/// `<<1>>` page number, `<<n>>` page count, `<<1 of n>>`, `<<1/n>>`, `<<Page 1>>`,
|
||||
/// `<<Page 1 of n>>`, dates `<<m/d/yyyy>>`, `<<mm/dd/yyyy>>`, `<<d/m/yyyy>>`, `<<yyyy-mm-dd>>`,
|
||||
/// `<<m/d/yy>>`, `<<mmmm d, yyyy>>`, and Bates numbers `<<Bates Number#6#1#PRE#SUF>>`
|
||||
/// `<<yyyy/mm/dd>>`, `<<yyyy/m/d>>`, `<<m/d/yy>>`, `<<mmmm d, yyyy>>`, and Bates numbers `<<Bates Number#6#1#PRE#SUF>>`
|
||||
/// (digits, start, prefix, suffix).
|
||||
pub text: [String; 6],
|
||||
/// The standard face the text is drawn in (#3754): Helvetica (the default), Times or Courier.
|
||||
@@ -298,6 +298,8 @@ pub fn expand(template: &str, page_number: u32, count: usize, bates: u64, cx: &C
|
||||
"d/m/yyyy" => format!("{d}/{m}/{y}"),
|
||||
"dd/mm/yyyy" => format!("{d:02}/{m:02}/{y}"),
|
||||
"yyyy-mm-dd" => format!("{y}-{m:02}-{d:02}"),
|
||||
"yyyy/mm/dd" => format!("{y}/{m:02}/{d:02}"),
|
||||
"yyyy/m/d" => format!("{y}/{m}/{d}"),
|
||||
"mmmm d, yyyy" => format!("{} {d}, {y}", MONTHS[(m.clamp(1, 12) - 1) as usize]),
|
||||
t if t.starts_with("Bates Number") => {
|
||||
// Bates Number#digits#start#prefix#suffix (start is applied by the caller).
|
||||
|
||||
@@ -81,6 +81,7 @@ fn tokens_expand() {
|
||||
assert_eq!(expand("Page <<1>> of <<n>>", 3, 10, 0, &c), "Page 3 of 10");
|
||||
assert_eq!(expand("<<1 of n>> · <<Page 1>> · <<1/n>>", 2, 5, 0, &c), "2 of 5 · Page 2 · 2/5");
|
||||
assert_eq!(expand("<<m/d/yyyy>> <<yyyy-mm-dd>> <<mmmm d, yyyy>>", 1, 1, 0, &c), "10/1/2026 2026-10-01 October 1, 2026");
|
||||
assert_eq!(expand("<<yyyy/mm/dd>> <<yyyy/m/d>>", 1, 1, 0, &c), "2026/10/01 2026/10/1");
|
||||
assert_eq!(expand("<<Bates Number#6#100#ABC#-X>>", 1, 1, 104, &c), "ABC000104-X");
|
||||
assert_eq!(expand("keep <<unknown>> and <<unclosed", 1, 1, 0, &c), "keep <<unknown>> and <<unclosed");
|
||||
assert_eq!(bates_start("x <<Bates Number#6#100#A#B>>"), Some(100));
|
||||
|
||||
+160
-2
@@ -13,7 +13,7 @@ use crate::Session;
|
||||
pub const DEFAULT_DATE_FORMAT: &str = "m/d/yyyy";
|
||||
|
||||
/// Ready-made formats for Preferences ▸ Date format. Any other valid pattern works too.
|
||||
pub const DATE_FORMATS: [&str; 12] = [
|
||||
pub const DATE_FORMATS: [&str; 14] = [
|
||||
"m/d/yyyy",
|
||||
"mm/dd/yyyy",
|
||||
"d/m/yyyy",
|
||||
@@ -21,6 +21,9 @@ pub const DATE_FORMATS: [&str; 12] = [
|
||||
"dd.mm.yyyy",
|
||||
"yyyy-mm-dd",
|
||||
"yyyy.mm.dd.",
|
||||
// Year first with slashes, as Taiwan, Japan and China write it (Windows' zh-TW short date).
|
||||
"yyyy/mm/dd",
|
||||
"yyyy/m/d",
|
||||
"d mmm yyyy",
|
||||
"d mmmm yyyy",
|
||||
"mmm d, yyyy",
|
||||
@@ -54,9 +57,13 @@ const ZH_DAYS: [&str; 7] = ["星期日", "星期一", "星期二", "星期三",
|
||||
const AR_MONTHS: [&str; 12] = ["يناير", "فبراير", "مارس", "أبريل", "مايو", "يونيو", "يوليو", "أغسطس", "سبتمبر", "أكتوبر", "نوفمبر", "ديسمبر"];
|
||||
const AR_DAYS: [&str; 7] = ["الأحد", "الاثنين", "الثلاثاء", "الأربعاء", "الخميس", "الجمعة", "السبت"];
|
||||
|
||||
const CKB_MONTHS: [&str; 12] =
|
||||
["کانوونی دووەم", "شوبات", "ئازار", "نیسان", "ئایار", "حوزەیران", "تەممووز", "ئاب", "ئەیلوول", "تشرینی یەکەم", "تشرینی دووەم", "کانوونی یەکەم"];
|
||||
const CKB_DAYS: [&str; 7] = ["یەکشەممە", "دووشەممە", "سێشەممە", "چوارشەممە", "پێنجشەممە", "هەینی", "شەممە"];
|
||||
|
||||
/// The languages month and weekday names can be written in (Preferences ▸ Date format ▸ Language):
|
||||
/// the interface languages, in the same order and with the same names.
|
||||
pub static DATE_LANGUAGES: [DateLanguage; 23] = [
|
||||
pub static DATE_LANGUAGES: [DateLanguage; 30] = [
|
||||
DateLanguage {
|
||||
code: "en",
|
||||
name: "English",
|
||||
@@ -250,6 +257,16 @@ pub static DATE_LANGUAGES: [DateLanguage; 23] = [
|
||||
days: AR_DAYS,
|
||||
days_short: AR_DAYS,
|
||||
},
|
||||
// Central Kurdish (Sorani) has no shorter written forms of its month and weekday names either.
|
||||
DateLanguage {
|
||||
code: "ckb",
|
||||
name: "کوردیی ناوەندی",
|
||||
months: CKB_MONTHS,
|
||||
months_with_day: None,
|
||||
months_short: CKB_MONTHS,
|
||||
days: CKB_DAYS,
|
||||
days_short: CKB_DAYS,
|
||||
},
|
||||
DateLanguage {
|
||||
code: "pl",
|
||||
name: "Polski",
|
||||
@@ -398,6 +415,115 @@ pub static DATE_LANGUAGES: [DateLanguage; 23] = [
|
||||
days: ["Chủ Nhật", "Thứ Hai", "Thứ Ba", "Thứ Tư", "Thứ Năm", "Thứ Sáu", "Thứ Bảy"],
|
||||
days_short: ["CN", "T2", "T3", "T4", "T5", "T6", "T7"],
|
||||
},
|
||||
DateLanguage {
|
||||
code: "fi",
|
||||
name: "Suomi",
|
||||
months: [
|
||||
"tammikuu",
|
||||
"helmikuu",
|
||||
"maaliskuu",
|
||||
"huhtikuu",
|
||||
"toukokuu",
|
||||
"kesäkuu",
|
||||
"heinäkuu",
|
||||
"elokuu",
|
||||
"syyskuu",
|
||||
"lokakuu",
|
||||
"marraskuu",
|
||||
"joulukuu",
|
||||
],
|
||||
// After a day number the month takes the partitive: `14. lokakuuta 2026`.
|
||||
months_with_day: Some([
|
||||
"tammikuuta",
|
||||
"helmikuuta",
|
||||
"maaliskuuta",
|
||||
"huhtikuuta",
|
||||
"toukokuuta",
|
||||
"kesäkuuta",
|
||||
"heinäkuuta",
|
||||
"elokuuta",
|
||||
"syyskuuta",
|
||||
"lokakuuta",
|
||||
"marraskuuta",
|
||||
"joulukuuta",
|
||||
]),
|
||||
months_short: ["tammi", "helmi", "maalis", "huhti", "touko", "kesä", "heinä", "elo", "syys", "loka", "marras", "joulu"],
|
||||
days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"],
|
||||
days_short: ["su", "ma", "ti", "ke", "to", "pe", "la"],
|
||||
},
|
||||
DateLanguage {
|
||||
code: "sq",
|
||||
name: "Shqip",
|
||||
months: ["janar", "shkurt", "mars", "prill", "maj", "qershor", "korrik", "gusht", "shtator", "tetor", "nëntor", "dhjetor"],
|
||||
months_with_day: None,
|
||||
months_short: ["jan", "shk", "mar", "pri", "maj", "qer", "korr", "gush", "sht", "tet", "nën", "dhj"],
|
||||
days: ["e diel", "e hënë", "e martë", "e mërkurë", "e enjte", "e premte", "e shtunë"],
|
||||
days_short: ["die", "hën", "mar", "mër", "enj", "pre", "sht"],
|
||||
},
|
||||
DateLanguage {
|
||||
code: "th",
|
||||
name: "ไทย",
|
||||
months: ["มกราคม", "กุมภาพันธ์", "มีนาคม", "เมษายน", "พฤษภาคม", "มิถุนายน", "กรกฎาคม", "สิงหาคม", "กันยายน", "ตุลาคม", "พฤศจิกายน", "ธันวาคม"],
|
||||
months_with_day: None,
|
||||
months_short: ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."],
|
||||
days: ["วันอาทิตย์", "วันจันทร์", "วันอังคาร", "วันพุธ", "วันพฤหัสบดี", "วันศุกร์", "วันเสาร์"],
|
||||
days_short: ["อา.", "จ.", "อ.", "พ.", "พฤ.", "ศ.", "ส."],
|
||||
},
|
||||
DateLanguage {
|
||||
code: "ca",
|
||||
name: "Català",
|
||||
months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"],
|
||||
// After a day the month carries its own preposition, elided before a vowel: `7 d'abril`.
|
||||
months_with_day: Some([
|
||||
"de gener",
|
||||
"de febrer",
|
||||
"de març",
|
||||
"d'abril",
|
||||
"de maig",
|
||||
"de juny",
|
||||
"de juliol",
|
||||
"d'agost",
|
||||
"de setembre",
|
||||
"d'octubre",
|
||||
"de novembre",
|
||||
"de desembre",
|
||||
]),
|
||||
months_short: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."],
|
||||
days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"],
|
||||
days_short: ["dg.", "dl.", "dt.", "dx.", "dj.", "dv.", "ds."],
|
||||
},
|
||||
// Romanian: month and weekday names are lowercase, also standing alone (`noiembrie 2023`).
|
||||
DateLanguage {
|
||||
code: "ro",
|
||||
name: "Română",
|
||||
months: [
|
||||
"ianuarie",
|
||||
"februarie",
|
||||
"martie",
|
||||
"aprilie",
|
||||
"mai",
|
||||
"iunie",
|
||||
"iulie",
|
||||
"august",
|
||||
"septembrie",
|
||||
"octombrie",
|
||||
"noiembrie",
|
||||
"decembrie",
|
||||
],
|
||||
months_with_day: None,
|
||||
months_short: ["ian.", "feb.", "mar.", "apr.", "mai", "iun.", "iul.", "aug.", "sept.", "oct.", "nov.", "dec."],
|
||||
days: ["duminică", "luni", "marți", "miercuri", "joi", "vineri", "sâmbătă"],
|
||||
days_short: ["dum.", "lun.", "mar.", "mie.", "joi", "vin.", "sâm."],
|
||||
},
|
||||
DateLanguage {
|
||||
code: "lo",
|
||||
name: "ພາສາລາວ",
|
||||
months: ["ມັງກອນ", "ກຸມພາ", "ມີນາ", "ເມສາ", "ພຶດສະພາ", "ມິຖຸນາ", "ກໍລະກົດ", "ສິງຫາ", "ກັນຍາ", "ຕຸລາ", "ພະຈິກ", "ທັນວາ"],
|
||||
months_with_day: None,
|
||||
months_short: ["ມ.ກ.", "ກ.ພ.", "ມ.ນ.", "ມ.ສ.", "ພ.ພ.", "ມິ.ຖ.", "ກ.ລ.", "ສ.ຫ.", "ກ.ຍ.", "ຕ.ລ.", "ພ.ຈ.", "ທ.ວ."],
|
||||
days: ["ວັນອາທິດ", "ວັນຈັນ", "ວັນອັງຄານ", "ວັນພຸດ", "ວັນພະຫັດ", "ວັນສຸກ", "ວັນເສົາ"],
|
||||
days_short: ["ອາທິດ", "ຈັນ", "ອັງຄານ", "ພຸດ", "ພະຫັດ", "ສຸກ", "ເສົາ"],
|
||||
},
|
||||
];
|
||||
|
||||
/// The date language for `code` (any case), or `None` when there's none.
|
||||
@@ -604,6 +730,8 @@ mod tests {
|
||||
"07.03.2026",
|
||||
"2026-03-07",
|
||||
"2026.03.07.",
|
||||
"2026/03/07",
|
||||
"2026/3/7",
|
||||
"7 Mar 2026",
|
||||
"7 March 2026",
|
||||
"Mar 7, 2026",
|
||||
@@ -701,6 +829,8 @@ mod tests {
|
||||
assert_eq!(in_lang("yyyy\\年mmmmd\\日 dddd", "ja"), "2026年3月7日 土曜日");
|
||||
assert_eq!(in_lang("yyyy\\年mmmmd\\日 dddd", "zh-hans"), "2026年三月7日 星期六");
|
||||
assert_eq!(in_lang("ddd", "zh-hant"), "週六");
|
||||
assert_eq!(in_lang("dddd, d mmmm yyyy", "sq"), "e shtunë, 7 mars 2026");
|
||||
assert_eq!(in_lang("ddd d mmm", "sq"), "sht 7 mar");
|
||||
assert_eq!(date_language("PT-BR").map(|l| l.code), Some("pt-br"));
|
||||
assert!(date_language("xx").is_none());
|
||||
for l in &DATE_LANGUAGES {
|
||||
@@ -718,6 +848,17 @@ mod tests {
|
||||
assert_eq!(in_lang("dddd, mmmm", "cs"), "sobota, březen");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalan_months_elide_the_preposition_after_a_day() {
|
||||
assert_eq!(in_lang("dddd d mmmm \\de yyyy", "ca"), "dissabte 7 de març de 2026");
|
||||
assert_eq!(in_lang("mmmm yyyy", "ca"), "març 2026");
|
||||
let ca = date_language("ca").unwrap();
|
||||
assert_eq!(format_day("d mmmm \\de yyyy", (2026, 4, 23), ca), "23 d'abril de 2026");
|
||||
assert_eq!(format_day("d mmmm", (2026, 8, 1), ca), "1 d'agost");
|
||||
assert_eq!(format_day("d mmmm", (2026, 10, 8), ca), "8 d'octubre");
|
||||
assert_eq!(format_day("mmmm", (2026, 10, 8), ca), "octubre", "no preposition without a day");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_session_writes_names_in_its_date_language() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
@@ -741,6 +882,23 @@ mod tests {
|
||||
assert_eq!(s.date_language(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn romanian_month_and_weekday_names() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
s.set_date_language(Some("ro")).unwrap();
|
||||
assert_eq!(s.date_language(), Some("ro"));
|
||||
s.set_date_format("d mmmm yyyy").unwrap();
|
||||
assert_eq!(s.today_text(None, None).as_deref(), Ok("14 noiembrie 2023"));
|
||||
s.set_date_format("mmmm yyyy").unwrap();
|
||||
assert_eq!(s.today_text(None, None).as_deref(), Ok("noiembrie 2023"));
|
||||
s.set_date_format("ddd, d mmm").unwrap();
|
||||
assert_eq!(s.today_text(None, None).as_deref(), Ok("mar., 14 nov."));
|
||||
// `14 noiembrie 2023` is WinAnsi; the weekday `marți` (ț, comma below) is not, so Fill & Sign refuses that format.
|
||||
assert_eq!(s.today_text_for_pdf(Some("d mmmm yyyy"), Some("ro")).as_deref(), Ok("14 noiembrie 2023"));
|
||||
let e = s.today_text_for_pdf(Some("dddd d mmmm yyyy"), Some("ro")).unwrap_err();
|
||||
assert!(e.contains("can't be written into the PDF yet"), "{e}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vietnamese_month_and_weekday_names() {
|
||||
let mut s = Session::new().with_clock(|| 1_700_000_000);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+247
-21
@@ -2434,20 +2434,20 @@ animation effects Off Vypnuto
|
||||
Couldn't print from the browser ({e}); downloaded {name} to print instead Z prohlížeče nelze tisknout ({e}); místo toho byl k tisku stažen soubor {name}
|
||||
Tools panel side Strana panelu nástrojů
|
||||
Add comment Přidat komentář
|
||||
Change tag properties Změnit vlastnosti značky
|
||||
Change tag properties Změnit vlastnosti tagu
|
||||
# Accessibility structure tags.
|
||||
Tags panel Panel značek
|
||||
Tags Značky
|
||||
Tag type Typ značky
|
||||
Tags panel Panel tagů
|
||||
Tags Tagy
|
||||
Tag type Typ tagu
|
||||
Actual text Skutečný text
|
||||
Find a tag Najít značku
|
||||
Collapse tag Sbalit značku
|
||||
Expand tag Rozbalit značku
|
||||
Find a tag Najít tag
|
||||
Collapse tag Sbalit tag
|
||||
Expand tag Rozbalit tag
|
||||
Revert changes Vrátit změny
|
||||
Save tag properties Uložit vlastnosti značky
|
||||
This document has no editable structure tags. Tento dokument nemá upravitelné značky struktury.
|
||||
{n} tags {n} značek
|
||||
Save or revert changes before selecting another tag. Před výběrem jiné značky změny uložte nebo vraťte.
|
||||
Save tag properties Uložit vlastnosti tagu
|
||||
This document has no editable structure tags. Tento dokument nemá žádné upravitelné tagy struktury.
|
||||
{n} tags Tagy: {n}
|
||||
Save or revert changes before selecting another tag. Před výběrem jiného tagu změny uložte nebo vraťte.
|
||||
Left out: {names} Vynecháno: {names}
|
||||
already a PDF již je PDF
|
||||
no unused output name žádný volný název výstupního souboru
|
||||
@@ -2499,8 +2499,8 @@ animation effects Off Vypnuto
|
||||
Not now Teď ne
|
||||
Open this local PDF? Otevřít tento místní soubor PDF?
|
||||
This document is trying to open a local file: Tento dokument se pokouší otevřít místní soubor:
|
||||
Move tag earlier Přesunout značku dříve
|
||||
Move tag later Přesunout značku později
|
||||
Move tag earlier Přesunout tag dříve
|
||||
Move tag later Přesunout tag později
|
||||
|
||||
# Historical snapshot notice bar (View signed version / View revision).
|
||||
You are viewing the signed version of “{from}” (revision {rev}). It is a snapshot: changes here won't affect the original. Prohlížíte si podepsanou verzi dokumentu „{from}“ (revize {rev}). Je to snímek: změny zde neovlivní originál.
|
||||
@@ -2508,19 +2508,19 @@ animation effects Off Vypnuto
|
||||
Turn upside down (180°) Otočit vzhůru nohama (180°)
|
||||
4 x 6 in label (101.6 x 152.4 mm) Štítek 4 × 6 in (101,6 × 152,4 mm)
|
||||
Cuts each page to its printed area, turns it upright and fits it to the sheet without stretching. One label per sheet. Ořízne každou stránku na potištěnou oblast, otočí ji svisle a přizpůsobí listu bez deformace. Jeden štítek na list.
|
||||
Find untagged content Najít neoznačený obsah
|
||||
No untagged content was found. Nebyl nalezen žádný neoznačený obsah.
|
||||
Found {n} untagged content problems. Nalezeno problémů s neoznačeným obsahem: {n}.
|
||||
Tag form fields Označit pole formuláře
|
||||
Find untagged content Najít neoznačkovaný obsah
|
||||
No untagged content was found. Nebyl nalezen žádný neoznačkovaný obsah.
|
||||
Found {n} untagged content problems. Nalezeno problémů s neoznačkovaným obsahem: {n}.
|
||||
Tag form fields Označkovat formulářová pole
|
||||
Mark as artifact Označit jako artefakt
|
||||
Remove this leaf tag from reading order and mark its direct content as an artifact Odeberte tuto značku listu z pořadí čtení a označte její přímý obsah jako artefakt
|
||||
Remove this leaf tag from reading order and mark its direct content as an artifact Odebrat tento koncový tag z pořadí čtení a jeho přímý obsah označit jako artefakt
|
||||
Mark content as artifact Označit obsah jako artefakt
|
||||
Word count Počet slov
|
||||
Current page only Pouze aktuální stránka
|
||||
Exclude tagged tables Vynechat označené tabulky
|
||||
Exclude tagged code blocks Vynechat označené bloky kódu
|
||||
Exclude tagged tables Vynechat označkované tabulky
|
||||
Exclude tagged code blocks Vynechat označkované bloky kódu
|
||||
Exclude image/OCR text Vynechat text obrázků a OCR
|
||||
Exclusions use PDF tags. Untagged tables and code remain included. Image exclusion also removes invisible text. Vynechávání využívá tagy PDF. Neoznačené tabulky a kód zůstávají zahrnuty. Vynechání obrázků odstraní i neviditelný text.
|
||||
Exclusions use PDF tags. Untagged tables and code remain included. Image exclusion also removes invisible text. Vynechávání využívá tagy PDF. Neoznačkované tabulky a kód zůstávají zahrnuty. Vynechání obrázků odstraní i neviditelný text.
|
||||
Words Slova
|
||||
Characters Znaky
|
||||
Characters without spaces Znaky bez mezer
|
||||
@@ -2567,3 +2567,229 @@ animation effects Off Vypnuto
|
||||
Larger thumbnails Větší miniatury
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Změnit tvar komentáře
|
||||
|
||||
# What the layers below word for themselves (engine `WORDINGS` lists): accessibility findings and
|
||||
# the saved report, PDF/A problems, signature details and the changes they name, pages to print,
|
||||
# history labels. Terms: timestamp = "časové razítko", timestamp authority = "autorita časových
|
||||
# razítek", signer = "podepisující osoba", byte range = "rozsah bajtů".
|
||||
A font isn't embedded Písmo není vložené
|
||||
A {} action isn't allowed Akce {} není povolena
|
||||
A {} annotation has additional actions Anotace {} má další akce
|
||||
A {} annotation has no appearance stream Anotace {} nemá datový proud vzhledu
|
||||
A {} annotation isn't set to print, or is hidden Anotace {} není nastavena k tisku nebo je skrytá
|
||||
Accessibility Report Zpráva o přístupnosti
|
||||
Change Author Změnit: Autor
|
||||
Change Keywords Změnit: Klíčová slova
|
||||
Change Subject Změnit: Předmět
|
||||
Change Title Změnit: Název
|
||||
Create links Vytvořit odkazy
|
||||
Detailed Report Podrobná zpráva
|
||||
DeviceCMYK is used, but the PDF/A output intent isn't a CMYK profile Je použit DeviceCMYK, ale výstupní záměr PDF/A není profil CMYK
|
||||
DeviceRGB is used, but the PDF/A output intent isn't an RGB profile Je použit DeviceRGB, ale výstupní záměr PDF/A není profil RGB
|
||||
Field "{}" on page {p} has no description (tooltip) Pole „{}“ na stránce {p} nemá popis (popisek nástroje)
|
||||
Filename Název souboru
|
||||
Flatten Fill & Sign Sloučit Vyplnit a podepsat se stránkou
|
||||
Font (unnamed) on page {p} doesn't map its characters to Unicode Písmo (bez názvu) na stránce {p} nemapuje své znaky na Unicode
|
||||
Font {} on page {p} doesn't map its characters to Unicode Písmo {} na stránce {p} nemapuje své znaky na Unicode
|
||||
Form field on page {p} isn't tagged Formulářové pole na stránce {p} není označkované
|
||||
H{n} follows an H{d}; headings should not skip levels H{n} následuje po H{d}; nadpisy by neměly přeskakovat úrovně
|
||||
No document language is set Není nastaven jazyk dokumentu
|
||||
No page has text: the document appears to be images of pages Žádná stránka nemá text: dokument se zdá být tvořen obrázky stránek
|
||||
Page {p} doesn't tab in structure order Stránka {p} nepřechází tabulátorem v pořadí struktury
|
||||
Page {p}: {n} untagged content item Stránka {p}: neoznačkované položky obsahu: {n}
|
||||
Page {p}: {n} untagged content items Stránka {p}: neoznačkované položky obsahu: {n}
|
||||
Page {} has additional actions Stránka {} má další akce
|
||||
PdfCraft can't check this signature yet: {}. PdfCraft zatím nedokáže tento podpis ověřit: {}.
|
||||
Report created Zpráva vytvořena
|
||||
Rule Name Název pravidla
|
||||
Save as {level} Uložit jako {level}
|
||||
Signature is invalid Podpis je neplatný
|
||||
Signature is valid Podpis je platný
|
||||
Signature validity is unknown Platnost podpisu je neznámá
|
||||
Signing time is from the clock on the signer's computer. Čas podpisu pochází z hodin v počítači podepisující osoby.
|
||||
The ECDSA signature is not in canonical DER (trailing bytes, padding or a missing sign byte); it was read anyway. Podpis ECDSA není v kanonickém DER (přebytečné bajty, výplň nebo chybějící bajt znaménka); přesto byl načten.
|
||||
The ECDSA signature is the raw r and s values instead of a DER sequence; it was read anyway. Podpis ECDSA tvoří holé hodnoty r a s místo sekvence DER; přesto byl načten.
|
||||
The RSA signature value does not have the length of the key's modulus (leading zero bytes dropped or added); it was read anyway. Hodnota podpisu RSA nemá délku modulu klíče (úvodní nulové bajty chybí nebo přebývají); přesto byla načtena.
|
||||
The RSA signature's DigestInfo has no NULL parameter (older signers write it so); it was read anyway. DigestInfo podpisu RSA nemá parametr NULL (starší podepisovací programy jej tak zapisují); přesto byl načten.
|
||||
The certificate of {} does not allow this many CA certificates below it (path length), so it is not used to vouch for {}. Certifikát {} nepovoluje pod sebou tolik certifikátů CA (délka cesty), proto se nepoužije k ručení za {}.
|
||||
The certificate of {} is not a CA certificate that may issue certificates, so it is not used to vouch for {}. Certifikát {} není certifikát CA, který smí vydávat certifikáty, proto se nepoužije k ručení za {}.
|
||||
The certificate of {} was not valid at the time of signing, so it is not used to vouch for {}. Certifikát {} nebyl v době podpisu platný, proto se nepoužije k ručení za {}.
|
||||
The checker found problems which may prevent the document from being fully accessible. Kontrola našla problémy, které mohou bránit plné přístupnosti dokumentu.
|
||||
The document has been altered or corrupted since the signature was applied. Dokument byl od připojení podpisu změněn nebo poškozen.
|
||||
The document has been altered or corrupted since the timestamp was applied. Dokument byl od připojení časového razítka změněn nebo poškozen.
|
||||
The document has been altered since this signature was applied in ways it does not permit ({}). Dokument byl od připojení tohoto podpisu změněn způsobem, který podpis nepovoluje ({}).
|
||||
The document has been altered since this timestamp was applied in ways it does not permit ({}). Dokument byl od připojení tohoto časového razítka změněn způsobem, který razítko nepovoluje ({}).
|
||||
The document has been modified since this signature was applied, but the changes are permitted ({}). Dokument byl od připojení tohoto podpisu upraven, ale změny jsou povolené ({}).
|
||||
The document has been modified since this timestamp was applied, but the changes are permitted ({}). Dokument byl od připojení tohoto časového razítka upraven, ale změny jsou povolené ({}).
|
||||
The document has no tags (structure tree) Dokument nemá tagy (strom struktury)
|
||||
The document has no title Dokument nemá název
|
||||
The document isn't marked as tagged (MarkInfo Marked) Dokument není označen jako označkovaný (MarkInfo Marked)
|
||||
The document isn't tagged, so none of its content is Dokument není označkovaný, a tak není označkovaný ani žádný jeho obsah
|
||||
The document's embedded revocation information shows that the signer's certificate has not been revoked. Informace o odvolání vložené v dokumentu ukazují, že certifikát podepisující osoby nebyl odvolán.
|
||||
The embedded timestamp token is valid and its authority is trusted; trusted time is {}. Vložené časové razítko je platné a jeho autorita je důvěryhodná; důvěryhodný čas je {}.
|
||||
The font {} isn't embedded Písmo {} není vložené
|
||||
The metadata doesn't identify the file as {} Metadata neoznačují soubor jako {}
|
||||
The security settings don't allow screen readers to read the text Nastavení zabezpečení nedovoluje čtečkám obrazovky číst text
|
||||
The signature algorithm and the SignerInfo's digest algorithm name different hashes; the signature was made with the SignerInfo's. Algoritmus podpisu a algoritmus otisku v SignerInfo uvádějí různé hashe; podpis byl vytvořen tím ze SignerInfo.
|
||||
The signature carries an unverified timestamp ({}): the timestamp authority is not in your list of trusted certificates, so the signing time claimed by the signer is used instead. Podpis nese neověřené časové razítko ({}): autorita časových razítek není ve vašem seznamu důvěryhodných certifikátů, proto se místo něj použije čas podpisu uvedený podepisující osobou.
|
||||
The signature contents are not hexadecimal. Obsah podpisu není šestnáctkový.
|
||||
The signature could not be checked ({}). Podpis nebylo možné zkontrolovat ({}).
|
||||
The signature could not be read ({}). Podpis nebylo možné načíst ({}).
|
||||
The signature could not be verified ({}). Podpis nebylo možné ověřit ({}).
|
||||
The signature has no valid byte range. Podpis nemá platný rozsah bajtů.
|
||||
The signature includes an embedded timestamp. Podpis obsahuje vložené časové razítko.
|
||||
The signature is BER-encoded (indefinite lengths) rather than DER; it was read leniently. Podpis je kódován v BER (neurčité délky) místo DER; byl načten benevolentně.
|
||||
The signature uses the legacy adbe.x509.rsa_sha1 format. Podpis používá zastaralý formát adbe.x509.rsa_sha1.
|
||||
The signature value does not match the signer's certificate: the signature is corrupt. Hodnota podpisu neodpovídá certifikátu podepisující osoby: podpis je poškozený.
|
||||
The signature's byte range does not exclude exactly its contents. Rozsah bajtů podpisu nevynechává přesně jeho obsah.
|
||||
The signature's byte range does not match the file. Rozsah bajtů podpisu neodpovídá souboru.
|
||||
The signature's timestamp token could not be verified ({}). Časové razítko podpisu nebylo možné ověřit ({}).
|
||||
The signature's timestamp token does not cover the signature value. Časové razítko podpisu nepokrývá hodnotu podpisu.
|
||||
The signed content is a constructed (segmented) OCTET STRING, as BER allows; it was read anyway. Podepsaný obsah je složený (segmentovaný) OCTET STRING, jak BER dovoluje; přesto byl načten.
|
||||
The signer's certificate does not allow digital signatures (its key usage has neither digital signature nor non-repudiation). Certifikát podepisující osoby nepovoluje digitální podpisy (jeho použití klíče nezahrnuje digitální podpis ani nepopiratelnost).
|
||||
The signer's certificate has been revoked ({}). Certifikát podepisující osoby byl odvolán ({}).
|
||||
The signer's certificate has critical extensions PdfCraft does not recognize ({}). Certifikát podepisující osoby má kritická rozšíření, která PdfCraft nezná ({}).
|
||||
The signer's certificate is not in the signature. Certifikát podepisující osoby není v podpisu.
|
||||
The signer's certificate is not issued for signing documents (its extended key usage has no document-signing purpose). Certifikát podepisující osoby není vydán k podepisování dokumentů (jeho rozšířené použití klíče nezahrnuje podepisování dokumentů).
|
||||
The signer's certificate was not valid at the time of signing. Certifikát podepisující osoby nebyl v době podpisu platný.
|
||||
The signer's identity is unknown because it has not been included in your list of trusted certificates and none of its parent certificates are trusted certificates. Identita podepisující osoby je neznámá, protože není ve vašem seznamu důvěryhodných certifikátů a žádný z jejích nadřazených certifikátů není důvěryhodný.
|
||||
The signer's identity is valid. Identita podepisující osoby je platná.
|
||||
The timestamp authority's certificate was not valid at the time of timestamping. Certifikát autority časových razítek nebyl v době vystavení razítka platný.
|
||||
The timestamp contents are not hexadecimal. Obsah časového razítka není šestnáctkový.
|
||||
The timestamp has no valid byte range. Časové razítko nemá platný rozsah bajtů.
|
||||
The timestamp token could not be read ({}). Časové razítko nebylo možné načíst ({}).
|
||||
The timestamp token is valid and its authority is trusted. Časové razítko je platné a jeho autorita je důvěryhodná.
|
||||
The timestamp token is valid, but the timestamp authority is not in your list of trusted certificates. Časové razítko je platné, ale autorita časových razítek není ve vašem seznamu důvěryhodných certifikátů.
|
||||
The timestamp's byte range does not exclude exactly its contents. Rozsah bajtů časového razítka nevynechává přesně jeho obsah.
|
||||
The timestamp's byte range does not match the file. Rozsah bajtů časového razítka neodpovídá souboru.
|
||||
The window shows the file name, not the title (Initial View > Show) Okno zobrazuje název souboru, ne název dokumentu (Počáteční zobrazení > Zobrazit)
|
||||
This document has not been modified since this signature was applied. Tento dokument nebyl od připojení tohoto podpisu upraven.
|
||||
This document has not been modified since this timestamp was applied. Tento dokument nebyl od připojení tohoto časového razítka upraven.
|
||||
This signature uses RIPEMD-160, a legacy 160-bit hash algorithm that is no longer recommended for signatures. It still validates, but it should not be relied on. Tento podpis používá RIPEMD-160, zastaralý 160bitový hashovací algoritmus, který se už pro podpisy nedoporučuje. Podpis se stále ověří, ale nelze na něj spoléhat.
|
||||
This signature uses SHA-1, a weak hash algorithm: collisions in it have been demonstrated. It still validates because many documents signed years ago use it, but it should not be relied on. Tento podpis používá SHA-1, slabý hashovací algoritmus, u kterého byly prokázány kolize. Stále se ověří, protože jej používá mnoho dokumentů podepsaných před lety, ale nelze na něj spoléhat.
|
||||
Unsigned signature field Nepodepsané podpisové pole
|
||||
alternate text hides an annotation inside it alternativní text skrývá anotaci uvnitř
|
||||
alternate text on an element with no page content alternativní text u prvku bez obsahu stránky
|
||||
comments komentáře
|
||||
document security store úložiště zabezpečení dokumentu
|
||||
document structure struktura dokumentu
|
||||
form fill vyplnění formuláře
|
||||
its alternate text is inside another element's and will never be read jeho alternativní text je uvnitř alternativního textu jiného prvku a nikdy nebude přečten
|
||||
links odkazy
|
||||
metadata metadata
|
||||
no alternate text chybí alternativní text
|
||||
no header cells (TH) chybí buňky záhlaví (TH)
|
||||
no summary chybí souhrn
|
||||
not in a TR není v TR
|
||||
not in a Table, THead, TBody or TFoot není v Table, THead, TBody ani TFoot
|
||||
not in an L (list) není v L (seznam)
|
||||
not in an LI (list item) není v LI (položka seznamu)
|
||||
other changes jiné změny
|
||||
page content obsah stránek
|
||||
page {n} is out of range (1–{count}) stránka {n} je mimo rozsah (1–{count})
|
||||
pages added or removed přidané nebo odebrané stránky
|
||||
rows have between {min} and {max} columns řádky mají {min} až {max} sloupců
|
||||
the first heading is an H{n}; headings should not skip levels první nadpis je H{n}; nadpisy by neměly přeskakovat úrovně
|
||||
the signed version could not be read podepsanou verzi nebylo možné načíst
|
||||
{n} pages and no bookmarks Počet stránek: {n}, žádné záložky
|
||||
{page} is not a page number or label {page} není číslo ani označení stránky
|
||||
{ty} element on page {p}: {what} Prvek {ty} na stránce {p}: {what}
|
||||
{ty} element: {what} Prvek {ty}: {what}
|
||||
{} annotation on page {p} isn't tagged Anotace {} na stránce {p} není označkovaná
|
||||
{} annotations aren't allowed Anotace {} nejsou povoleny
|
||||
… and {n} more … a další ({n})
|
||||
|
||||
# Labels other catalogs carry (shared buttons, tooltips with key caps, the folder picker).
|
||||
on page {label} na stránce {label}
|
||||
of z
|
||||
Add the PDFs to combine Přidejte soubory PDF ke sloučení
|
||||
Added the first {n} PDFs in {folder} Přidány první soubory PDF ze složky {folder} (počet: {n})
|
||||
Always Vždy
|
||||
Automatically Automaticky
|
||||
Choose a file… Vybrat soubor…
|
||||
Choose a folder… Vybrat složku…
|
||||
Choose… Vybrat…
|
||||
Color Barva
|
||||
Comment Komentář
|
||||
Comment and review Komentovat a revidovat
|
||||
Copied to clipboard Zkopírováno do schránky
|
||||
Copy to clipboard Kopírovat do schránky
|
||||
Create folder Vytvořit složku
|
||||
Disabled Vypnuto
|
||||
Document properties (⌘D) Vlastnosti dokumentu (⌘D)
|
||||
Drop PDFs or folders here, or choose them. Přetáhněte sem soubory PDF nebo složky, nebo je vyberte.
|
||||
Duplicate Duplikovat
|
||||
Enabled Zapnuto
|
||||
Error Chyba
|
||||
Every PDF in the folder Všechny soubory PDF ve složce
|
||||
Every PDF in the folder and the folders inside it Všechny soubory PDF ve složce a jejích podsložkách
|
||||
Folder Složka
|
||||
Help… Nápověda…
|
||||
Import Importovat
|
||||
Information Informace
|
||||
Loading… Načítání…
|
||||
Mouse wheel scroll speed Rychlost posouvání kolečkem myši
|
||||
Move Přesunout
|
||||
Never Nikdy
|
||||
New bookmark (⌘B) Nová záložka (⌘B)
|
||||
Next Další
|
||||
Next (⌘G) Další (⌘G)
|
||||
No PDFs found in {folder} Ve složce {folder} nebyly nalezeny žádné soubory PDF
|
||||
No results Žádné výsledky
|
||||
On Zapnuto
|
||||
Open a PDF (⌘O) Otevřít PDF (⌘O)
|
||||
Open folder Otevřít složku
|
||||
Organize Uspořádat
|
||||
Page {n} Stránka {n}
|
||||
Page {n} of {total} Stránka {n} z {total}
|
||||
Paste Vložit
|
||||
Previous Předchozí
|
||||
Previous (⇧⌘G) Předchozí (⇧⌘G)
|
||||
Print (⌘P) Tisk (⌘P)
|
||||
Refresh Obnovit
|
||||
Rotate view clockwise (⇧⌘+) Otočit zobrazení po směru hodinových ručiček (⇧⌘+)
|
||||
Save changes? Uložit změny?
|
||||
Save file Uložit soubor
|
||||
Search results Výsledky hledání
|
||||
Select all Vybrat vše
|
||||
Success Hotovo
|
||||
System Podle systému
|
||||
The password must have at least 6 characters. Heslo musí mít alespoň 6 znaků.
|
||||
The standard fonts can't draw “{c}” ({code}). Only Western European characters can be added as text for now. Standardní písma nedokážou vykreslit „{c}“ ({code}). Jako text lze zatím přidat jen západoevropské znaky.
|
||||
This file changed on disk. Reload it to see the new version; your unsaved changes will be lost. Tento soubor se na disku změnil. Načtěte ho znovu, abyste viděli novou verzi; neuložené změny budou ztraceny.
|
||||
Theme Motiv
|
||||
Warning Upozornění
|
||||
Zoom in (⌘+) Přiblížit (⌘+)
|
||||
Zoom in / out (also pinch or ⌘-scroll) Přiblížit / oddálit (také sevřením prstů nebo posouváním s ⌘)
|
||||
Zoom out (⌘−) Oddálit (⌘−)
|
||||
@plural {n} comment|{n} comments {n} komentář|{n} komentáře|{n} komentářů
|
||||
@plural {n} file|{n} files {n} soubor|{n} soubory|{n} souborů
|
||||
@plural {n} result|{n} results {n} výsledek|{n} výsledky|{n} výsledků
|
||||
theme Appearance Vzhled
|
||||
|
||||
# The date picker's weekday heads.
|
||||
calendar weekday Su Ne
|
||||
calendar weekday Mo Po
|
||||
calendar weekday Tu Út
|
||||
calendar weekday We St
|
||||
calendar weekday Th Čt
|
||||
calendar weekday Fr Pá
|
||||
calendar weekday Sa So
|
||||
|
||||
# A certificate's fields in the certificate viewer.
|
||||
certificate Issued to Vydáno pro
|
||||
certificate Issued by Vydal
|
||||
certificate Valid from Platný od
|
||||
certificate Valid to Platný do
|
||||
certificate Intended usage Zamýšlené použití
|
||||
certificate Serial number Sériové číslo
|
||||
certificate Issuer Vydavatel
|
||||
certificate Validity starts Začátek platnosti
|
||||
certificate Validity ends Konec platnosti
|
||||
certificate Public key Veřejný klíč
|
||||
certificate Basic constraints Základní omezení
|
||||
certificate Key usage Použití klíče
|
||||
certificate Self-signed Samopodepsaný
|
||||
certificate SHA-1 digest Otisk SHA-1
|
||||
certificate SHA-256 digest Otisk SHA-256
|
||||
certificate Version Verze
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2633,3 +2633,175 @@ animation effects Off Desactivados
|
||||
Larger thumbnails Miniaturas más grandes
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Cambiar la forma del comentario
|
||||
|
||||
#
|
||||
# Keys the other catalogs carry that this one was missing, so Spanish covers the bundled key union
|
||||
# the way Lithuanian and Vietnamese do (`lithuanian_covers_bundled_catalog_keys_including_dynamic_dialog_labels`).
|
||||
# Same clean-room rule as the header: written from the plain meaning of the English label, reusing
|
||||
# the vocabulary already in this file (ID digital, marcador, Acercar / alejar, Portapapeles).
|
||||
#
|
||||
# The date picker.
|
||||
calendar date January enero
|
||||
calendar date February febrero
|
||||
calendar date March marzo
|
||||
calendar date April abril
|
||||
calendar date May mayo
|
||||
calendar date June junio
|
||||
calendar date July julio
|
||||
calendar date August agosto
|
||||
calendar date September septiembre
|
||||
calendar date October octubre
|
||||
calendar date November noviembre
|
||||
calendar date December diciembre
|
||||
calendar weekday Mo Lu
|
||||
calendar weekday Tu Ma
|
||||
calendar weekday We Mi
|
||||
calendar weekday Th Ju
|
||||
calendar weekday Fr Vi
|
||||
calendar weekday Sa Sá
|
||||
calendar weekday Su Do
|
||||
#
|
||||
# Certificate details, in their own context beside the plain labels.
|
||||
certificate Issued to Emitido a
|
||||
certificate Issued by Emitido por
|
||||
certificate Issuer Emisor
|
||||
certificate Serial number Número de serie
|
||||
certificate Version Versión
|
||||
certificate Public key Clave pública
|
||||
certificate Key usage Uso de la clave
|
||||
certificate Intended usage Uso previsto
|
||||
certificate Basic constraints Restricciones básicas
|
||||
certificate Self-signed Autofirmado
|
||||
certificate Valid from Válido desde
|
||||
certificate Valid to Válido hasta
|
||||
certificate Validity starts La validez empieza
|
||||
certificate Validity ends La validez termina
|
||||
certificate SHA-1 digest Huella SHA-1
|
||||
certificate SHA-256 digest Huella SHA-256
|
||||
#
|
||||
# What a certificate's key may be used for (X.509 key usage), as the details list them.
|
||||
Digital Signature Firma digital
|
||||
Non-Repudiation No repudio
|
||||
Key Encipherment Cifrado de claves
|
||||
Data Encipherment Cifrado de datos
|
||||
Key Agreement Acuerdo de claves
|
||||
Certificate Signing Firma de certificados
|
||||
CRL Signing Firma de CRL
|
||||
Encipher Only Solo cifrado
|
||||
Decipher Only Solo descifrado
|
||||
#
|
||||
# Signatures, revisions and digital IDs.
|
||||
{who}, certificate issued by {issuer}. {who}, certificado emitido por {issuer}.
|
||||
{who}, certificate issued by an unknown issuer. {who}, certificado emitido por un emisor desconocido.
|
||||
Rev. {rev}: Signed by {name} Rev. {rev}: Firmado por {name}
|
||||
Rev. {rev}: Signed by an unknown signer Rev. {rev}: Firmado por un firmante desconocido
|
||||
Rev. {rev}: Certified by {name} Rev. {rev}: Certificado por {name}
|
||||
Rev. {rev}: Certified by an unknown signer Rev. {rev}: Certificado por un firmante desconocido
|
||||
Unsigned signature field: {name} Campo de firma sin firmar: {name}
|
||||
Choose a digital ID. Elige un ID digital.
|
||||
There is no folder to save the digital ID in. No hay ninguna carpeta donde guardar el ID digital.
|
||||
#
|
||||
# Passwords.
|
||||
The password is incorrect. La contraseña es incorrecta.
|
||||
The password must have at least 6 characters. La contraseña debe tener al menos 6 caracteres.
|
||||
The password must have at least 8 characters. La contraseña debe tener al menos 8 caracteres.
|
||||
The passwords do not match. Las contraseñas no coinciden.
|
||||
Only the document's owner can change its security (open it with the permissions password) Solo el propietario del documento puede cambiar su seguridad (ábrelo con la contraseña de permisos)
|
||||
#
|
||||
# Counts.
|
||||
@plural {n} byte|{n} bytes {n} byte|{n} bytes
|
||||
@plural {n} pixel|{n} pixels {n} píxel|{n} píxeles
|
||||
@plural {n} file|{n} files {n} archivo|{n} archivos
|
||||
@plural {n} comment|{n} comments {n} comentario|{n} comentarios
|
||||
@plural {n} result|{n} results {n} resultado|{n} resultados
|
||||
@plural {n} image optimized|{n} images optimized {n} imagen optimizada|{n} imágenes optimizadas
|
||||
@plural {n} item discarded|{n} items discarded {n} elemento descartado|{n} elementos descartados
|
||||
@plural Delete {n} field|Delete {n} fields Eliminar {n} campo|Eliminar {n} campos
|
||||
#
|
||||
# Combining PDFs from a folder.
|
||||
Add the PDFs to combine Añade los PDF que vas a combinar
|
||||
Drop PDFs or folders here, or choose them. Suelta aquí PDF o carpetas, o elígelos.
|
||||
Every PDF in the folder Todos los PDF de la carpeta
|
||||
Every PDF in the folder and the folders inside it Todos los PDF de la carpeta y de las carpetas que contiene
|
||||
Added the first {n} PDFs in {folder} Se han añadido los primeros {n} PDF de {folder}
|
||||
No PDFs found in {folder} No se ha encontrado ningún PDF en {folder}
|
||||
#
|
||||
# Panels, rendering and notices.
|
||||
Panel layout could not be restored: {error} No se ha podido restaurar la disposición de los paneles: {error}
|
||||
Panel move was not applied: {error} No se ha aplicado el movimiento del panel: {error}
|
||||
Rendering… Renderizando…
|
||||
Still rendering — this page is unusually complex… Sigue renderizando: esta página es excepcionalmente compleja…
|
||||
Loading… Cargando…
|
||||
This file changed on disk. Reload it to see the new version; your unsaved changes will be lost. Este archivo cambió en el disco. Recárgalo para ver la versión nueva; se perderán los cambios sin guardar.
|
||||
Text recognition isn't installed: its models are missing (run `cargo xtask models`, or set PDFCRAFT_MODELS). El reconocimiento de texto no está instalado: faltan sus modelos (ejecuta `cargo xtask models` o define PDFCRAFT_MODELS).
|
||||
Cut and stack needs Two-sided: Off. Print single-sided sheets. Cortar y apilar necesita «A doble cara: Desactivado». Imprime hojas a una cara.
|
||||
Error Error
|
||||
Warning Advertencia
|
||||
Information Información
|
||||
Success Correcto
|
||||
#
|
||||
# Asking for something, and choosing it.
|
||||
Enter a name. Introduce un nombre.
|
||||
Enter a page number Introduce un número de página
|
||||
Enter a URL Introduce una URL
|
||||
Enter the field names Introduce los nombres de los campos
|
||||
Choose… Elegir…
|
||||
Choose a file… Elegir un archivo…
|
||||
Choose a folder… Elegir una carpeta…
|
||||
Create folder Crear carpeta
|
||||
Open folder Abrir carpeta
|
||||
Save file Guardar archivo
|
||||
Save changes? ¿Guardar los cambios?
|
||||
#
|
||||
# Settings and their values.
|
||||
Theme Tema
|
||||
theme Appearance Aspecto
|
||||
System Sistema
|
||||
English Inglés
|
||||
Always Siempre
|
||||
Never Nunca
|
||||
Automatically Automáticamente
|
||||
On Activado
|
||||
Enabled Activado
|
||||
Disabled Desactivado
|
||||
Mouse wheel scroll speed Velocidad de desplazamiento de la rueda del ratón
|
||||
Margins (in) Márgenes (pulg.)
|
||||
#
|
||||
# Labels and commands the catalogs name on their own.
|
||||
Color Color
|
||||
Folder Carpeta
|
||||
Comment Comentario
|
||||
Comment and review Comentar y revisar
|
||||
Creator Creador
|
||||
Producer Productor
|
||||
Organize Organizar
|
||||
Import Importar
|
||||
Move Mover
|
||||
Duplicate Duplicar
|
||||
Paste Pegar
|
||||
Select all Seleccionar todo
|
||||
Refresh Actualizar
|
||||
Next Siguiente
|
||||
Previous Anterior
|
||||
of de
|
||||
No results Sin resultados
|
||||
Search results Resultados de la búsqueda
|
||||
Copy to clipboard Copiar al portapapeles
|
||||
Copied to clipboard Copiado al portapapeles
|
||||
Help… Ayuda…
|
||||
on page {label} en la página {label}
|
||||
Page {n} Página {n}
|
||||
Page {n} of {total} Página {n} de {total}
|
||||
#
|
||||
# Tooltips that spell their shortcut out.
|
||||
Open a PDF (⌘O) Abrir un PDF (⌘O)
|
||||
Print (⌘P) Imprimir (⌘P)
|
||||
Document properties (⌘D) Propiedades del documento (⌘D)
|
||||
New bookmark (⌘B) Nuevo marcador (⌘B)
|
||||
Next (⌘G) Siguiente (⌘G)
|
||||
Previous (⇧⌘G) Anterior (⇧⌘G)
|
||||
Zoom in (⌘+) Acercar (⌘+)
|
||||
Zoom out (⌘−) Alejar (⌘−)
|
||||
Zoom in / out (also pinch or ⌘-scroll) Acercar / alejar (también con pellizco o ⌘ + desplazamiento)
|
||||
Rotate view clockwise (⇧⌘+) Girar la vista a la derecha (⇧⌘+)
|
||||
Save (M4) Guardar (M4)
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 60.
|
File diff suppressed because it is too large
Load Diff
@@ -2493,3 +2493,269 @@ animation effects Off Désactivés
|
||||
Larger thumbnails Agrandir les vignettes
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Modifier la forme du commentaire
|
||||
on page {label} à la page {label}
|
||||
A font isn't embedded Une police n'est pas incorporée
|
||||
A {} action isn't allowed Une action {} n'est pas autorisée
|
||||
A {} annotation has additional actions Une annotation {} contient des actions supplémentaires
|
||||
A {} annotation has no appearance stream Une annotation {} n'a pas de flux d'apparence
|
||||
A {} annotation isn't set to print, or is hidden Une annotation {} n'est pas réglée pour l'impression, ou est masquée
|
||||
Accessibility Report Rapport d'accessibilité
|
||||
Add the PDFs to combine Ajoutez les PDF à combiner
|
||||
Added the first {n} PDFs in {folder} Les {n} premiers PDF de {folder} ont été ajoutés
|
||||
Always Toujours
|
||||
Automatically Automatiquement
|
||||
CRL Signing Signature de LCR
|
||||
Certificate Signing Signature de certificats
|
||||
Certificate authority Autorité de certification
|
||||
Change Author Modifier l'auteur
|
||||
Change Keywords Modifier les mots-clés
|
||||
Change Subject Modifier le sujet
|
||||
Change Title Modifier le titre
|
||||
Choose a digital ID. Choisissez un ID numérique.
|
||||
Choose a file… Choisir un fichier…
|
||||
Choose a folder… Choisir un dossier…
|
||||
Choose… Choisir…
|
||||
Color Couleur
|
||||
Comment Commentaire
|
||||
Comment and review Commenter et réviser
|
||||
Copied to clipboard Copié dans le presse-papiers
|
||||
Copy to clipboard Copier dans le presse-papiers
|
||||
Create folder Créer un dossier
|
||||
Create links Créer des liens
|
||||
Creator Application
|
||||
Cut and stack needs Two-sided: Off. Print single-sided sheets. Couper et empiler exige Recto verso : Désactivé. Imprimez des feuilles en recto seul.
|
||||
Data Encipherment Chiffrement des données
|
||||
Decipher Only Déchiffrement seul
|
||||
Detailed Report Rapport détaillé
|
||||
DeviceCMYK is used, but the PDF/A output intent isn't a CMYK profile DeviceCMYK est utilisé, mais l'intention de sortie PDF/A n'est pas un profil CMJN
|
||||
DeviceRGB is used, but the PDF/A output intent isn't an RGB profile DeviceRGB est utilisé, mais l'intention de sortie PDF/A n'est pas un profil RVB
|
||||
Digital Signature Signature numérique
|
||||
Disabled Désactivé
|
||||
Document properties (⌘D) Propriétés du document (⌘D)
|
||||
Drop PDFs or folders here, or choose them. Déposez des PDF ou des dossiers ici, ou choisissez-les.
|
||||
Duplicate Dupliquer
|
||||
Enabled Activé
|
||||
Encipher Only Chiffrement seul
|
||||
End entity Entité finale
|
||||
English Anglais
|
||||
Enter a URL Saisissez une URL
|
||||
Enter a name. Saisissez un nom.
|
||||
Enter a page number Saisissez un numéro de page
|
||||
Enter the field names Saisissez les noms des champs
|
||||
Error Erreur
|
||||
Every PDF in the folder Tous les PDF du dossier
|
||||
Every PDF in the folder and the folders inside it Tous les PDF du dossier et de ses sous-dossiers
|
||||
Field "{}" on page {p} has no description (tooltip) Le champ « {} » de la page {p} n'a pas de description (info-bulle)
|
||||
Filename Nom du fichier
|
||||
Flatten Fill & Sign Aplatir Remplir et signer
|
||||
Folder Dossier
|
||||
Font (unnamed) on page {p} doesn't map its characters to Unicode La police (sans nom) de la page {p} n'associe pas ses caractères à Unicode
|
||||
Font {} on page {p} doesn't map its characters to Unicode La police {} de la page {p} n'associe pas ses caractères à Unicode
|
||||
Form field on page {p} isn't tagged Un champ de formulaire de la page {p} n'est pas balisé
|
||||
Help… Aide…
|
||||
H{n} follows an H{d}; headings should not skip levels H{n} suit H{d} ; les niveaux de titre ne doivent pas être sautés
|
||||
Import Importer
|
||||
Information Information
|
||||
Key Agreement Accord de clé
|
||||
Key Encipherment Chiffrement de clé
|
||||
Loading… Chargement…
|
||||
Margins (in) Marges (pouces)
|
||||
Move Déplacer
|
||||
Never Jamais
|
||||
New bookmark (⌘B) Nouveau signet (⌘B)
|
||||
Next Suivant
|
||||
Next (⌘G) Suivant (⌘G)
|
||||
No PDFs found in {folder} Aucun PDF trouvé dans {folder}
|
||||
No document language is set Aucune langue de document n'est définie
|
||||
No page has text: the document appears to be images of pages Aucune page ne contient de texte : le document semble être constitué d'images de pages
|
||||
No results Aucun résultat
|
||||
Non-Repudiation Non-répudiation
|
||||
On Activé
|
||||
Only the document's owner can change its security (open it with the permissions password) Seul le propriétaire du document peut modifier sa protection (ouvrez-le avec le mot de passe d'autorisations)
|
||||
Open a PDF (⌘O) Ouvrir un PDF (⌘O)
|
||||
Open folder Ouvrir le dossier
|
||||
Organize Organiser
|
||||
Page {n} Page {n}
|
||||
Page {n} of {total} Page {n} sur {total}
|
||||
Page {p} doesn't tab in structure order La page {p} ne se parcourt pas dans l'ordre de la structure
|
||||
Page {p}: {n} untagged content item Page {p} : {n} élément de contenu non balisé
|
||||
Page {p}: {n} untagged content items Page {p} : {n} éléments de contenu non balisés
|
||||
Page {} has additional actions La page {} contient des actions supplémentaires
|
||||
Panel layout could not be restored: {error} Impossible de restaurer la disposition des panneaux : {error}
|
||||
Panel move was not applied: {error} Le déplacement du panneau n'a pas été appliqué : {error}
|
||||
Paste Coller
|
||||
PdfCraft can't check this signature yet: {}. PdfCraft ne peut pas encore contrôler cette signature : {}.
|
||||
Previous Précédent
|
||||
Previous (⇧⌘G) Précédent (⇧⌘G)
|
||||
Print (⌘P) Imprimer (⌘P)
|
||||
Producer Producteur du PDF
|
||||
Refresh Actualiser
|
||||
Rendering… Rendu en cours…
|
||||
Report created Rapport créé
|
||||
Rev. {rev}: Certified by an unknown signer Rév. {rev} : certifié par un signataire inconnu
|
||||
Rev. {rev}: Certified by {name} Rév. {rev} : certifié par {name}
|
||||
Rev. {rev}: Signed by an unknown signer Rév. {rev} : signé par un signataire inconnu
|
||||
Rev. {rev}: Signed by {name} Rév. {rev} : signé par {name}
|
||||
Rotate view clockwise (⇧⌘+) Pivoter l'affichage vers la droite (⇧⌘+)
|
||||
Rule Name Nom de la règle
|
||||
Save (M4) Enregistrer (M4)
|
||||
Save as {level} Enregistrer comme {level}
|
||||
Save changes? Enregistrer les modifications ?
|
||||
Save file Enregistrer le fichier
|
||||
Search results Résultats de la recherche
|
||||
Select all Tout sélectionner
|
||||
Signature is invalid La signature n'est pas valide
|
||||
Signature is valid La signature est valide
|
||||
Signature validity is unknown La validité de la signature est inconnue
|
||||
Signing time is from the clock on the signer's computer. L'heure de signature provient de l'horloge de l'ordinateur du signataire.
|
||||
Still rendering — this page is unusually complex… Rendu toujours en cours : cette page est exceptionnellement complexe…
|
||||
Success Succès
|
||||
System Système
|
||||
Text recognition isn't installed: its models are missing (run `cargo xtask models`, or set PDFCRAFT_MODELS). La reconnaissance de texte n'est pas installée : ses modèles sont absents (exécutez `cargo xtask models`, ou définissez PDFCRAFT_MODELS).
|
||||
The ECDSA signature is not in canonical DER (trailing bytes, padding or a missing sign byte); it was read anyway. La signature ECDSA n'est pas en DER canonique (octets en trop, bourrage ou octet de signe manquant) ; elle a tout de même été lue.
|
||||
The ECDSA signature is the raw r and s values instead of a DER sequence; it was read anyway. La signature ECDSA est constituée des valeurs brutes r et s au lieu d'une séquence DER ; elle a tout de même été lue.
|
||||
The RSA signature value does not have the length of the key's modulus (leading zero bytes dropped or added); it was read anyway. La valeur de la signature RSA n'a pas la longueur du module de la clé (octets nuls de tête supprimés ou ajoutés) ; elle a tout de même été lue.
|
||||
The RSA signature's DigestInfo has no NULL parameter (older signers write it so); it was read anyway. Le DigestInfo de la signature RSA n'a pas de paramètre NULL (d'anciens outils de signature l'écrivent ainsi) ; il a tout de même été lu.
|
||||
The certificate of {} does not allow this many CA certificates below it (path length), so it is not used to vouch for {}. Le certificat de {} n'autorise pas autant de certificats d'AC en dessous de lui (longueur du chemin) : il n'est donc pas utilisé pour se porter garant de {}.
|
||||
The certificate of {} is not a CA certificate that may issue certificates, so it is not used to vouch for {}. Le certificat de {} n'est pas un certificat d'AC autorisé à émettre des certificats : il n'est donc pas utilisé pour se porter garant de {}.
|
||||
The certificate of {} was not valid at the time of signing, so it is not used to vouch for {}. Le certificat de {} n'était pas valide au moment de la signature : il n'est donc pas utilisé pour se porter garant de {}.
|
||||
The checker found problems which may prevent the document from being fully accessible. Le vérificateur a trouvé des problèmes qui peuvent empêcher le document d'être entièrement accessible.
|
||||
The document has been altered or corrupted since the signature was applied. Le document a été modifié ou corrompu depuis l'application de la signature.
|
||||
The document has been altered or corrupted since the timestamp was applied. Le document a été modifié ou corrompu depuis l'application de l'horodatage.
|
||||
The document has been altered since this signature was applied in ways it does not permit ({}). Le document a été modifié depuis l'application de cette signature d'une manière qu'elle n'autorise pas ({}).
|
||||
The document has been altered since this timestamp was applied in ways it does not permit ({}). Le document a été modifié depuis l'application de cet horodatage d'une manière qu'il n'autorise pas ({}).
|
||||
The document has been modified since this signature was applied, but the changes are permitted ({}). Le document a été modifié depuis l'application de cette signature, mais les modifications sont autorisées ({}).
|
||||
The document has been modified since this timestamp was applied, but the changes are permitted ({}). Le document a été modifié depuis l'application de cet horodatage, mais les modifications sont autorisées ({}).
|
||||
The document has no tags (structure tree) Le document n'a aucune balise (arbre de structure)
|
||||
The document has no title Le document n'a pas de titre
|
||||
The document isn't marked as tagged (MarkInfo Marked) Le document n'est pas indiqué comme balisé (MarkInfo Marked)
|
||||
The document isn't tagged, so none of its content is Le document n'est pas balisé, son contenu non plus
|
||||
The document's embedded revocation information shows that the signer's certificate has not been revoked. Les informations de révocation incorporées au document montrent que le certificat du signataire n'a pas été révoqué.
|
||||
The embedded timestamp token is valid and its authority is trusted; trusted time is {}. Le jeton d'horodatage incorporé est valide et son autorité est approuvée ; l'heure de confiance est {}.
|
||||
The font {} isn't embedded La police {} n'est pas incorporée
|
||||
The metadata doesn't identify the file as {} Les métadonnées n'identifient pas le fichier comme {}
|
||||
The password is incorrect. Le mot de passe est incorrect.
|
||||
The password must have at least 6 characters. Le mot de passe doit comporter au moins 6 caractères.
|
||||
The passwords do not match. Les mots de passe ne correspondent pas.
|
||||
The security settings don't allow screen readers to read the text Les paramètres de protection ne permettent pas aux lecteurs d'écran de lire le texte
|
||||
The signature algorithm and the SignerInfo's digest algorithm name different hashes; the signature was made with the SignerInfo's. L'algorithme de signature et l'algorithme d'empreinte du SignerInfo désignent des hachages différents ; la signature a été faite avec celui du SignerInfo.
|
||||
The signature carries an unverified timestamp ({}): the timestamp authority is not in your list of trusted certificates, so the signing time claimed by the signer is used instead. La signature comporte un horodatage non vérifié ({}) : l'autorité d'horodatage ne figure pas dans votre liste de certificats approuvés ; c'est donc l'heure de signature déclarée par le signataire qui est utilisée.
|
||||
The signature contents are not hexadecimal. Le contenu de la signature n'est pas hexadécimal.
|
||||
The signature could not be checked ({}). La signature n'a pas pu être contrôlée ({}).
|
||||
The signature could not be read ({}). La signature n'a pas pu être lue ({}).
|
||||
The signature could not be verified ({}). La signature n'a pas pu être vérifiée ({}).
|
||||
The signature has no valid byte range. La signature n'a pas de plage d'octets valide.
|
||||
The signature includes an embedded timestamp. La signature comprend un horodatage incorporé.
|
||||
The signature is BER-encoded (indefinite lengths) rather than DER; it was read leniently. La signature est codée en BER (longueurs indéfinies) plutôt qu'en DER ; elle a été lue avec tolérance.
|
||||
The signature uses the legacy adbe.x509.rsa_sha1 format. La signature utilise l'ancien format adbe.x509.rsa_sha1.
|
||||
The signature value does not match the signer's certificate: the signature is corrupt. La valeur de la signature ne correspond pas au certificat du signataire : la signature est corrompue.
|
||||
The signature's byte range does not exclude exactly its contents. La plage d'octets de la signature n'exclut pas exactement son contenu.
|
||||
The signature's byte range does not match the file. La plage d'octets de la signature ne correspond pas au fichier.
|
||||
The signature's timestamp token could not be verified ({}). Le jeton d'horodatage de la signature n'a pas pu être vérifié ({}).
|
||||
The signature's timestamp token does not cover the signature value. Le jeton d'horodatage de la signature ne couvre pas la valeur de la signature.
|
||||
The signed content is a constructed (segmented) OCTET STRING, as BER allows; it was read anyway. Le contenu signé est une OCTET STRING construite (segmentée), comme le BER l'autorise ; il a tout de même été lu.
|
||||
The signer's certificate does not allow digital signatures (its key usage has neither digital signature nor non-repudiation). Le certificat du signataire n'autorise pas les signatures numériques (son usage de la clé ne comprend ni la signature numérique ni la non-répudiation).
|
||||
The signer's certificate has been revoked ({}). Le certificat du signataire a été révoqué ({}).
|
||||
The signer's certificate has critical extensions PdfCraft does not recognize ({}). Le certificat du signataire comporte des extensions critiques que PdfCraft ne reconnaît pas ({}).
|
||||
The signer's certificate is not in the signature. Le certificat du signataire ne figure pas dans la signature.
|
||||
The signer's certificate is not issued for signing documents (its extended key usage has no document-signing purpose). Le certificat du signataire n'est pas émis pour signer des documents (son usage étendu de la clé n'inclut pas la signature de documents).
|
||||
The signer's certificate was not valid at the time of signing. Le certificat du signataire n'était pas valide au moment de la signature.
|
||||
The signer's identity is unknown because it has not been included in your list of trusted certificates and none of its parent certificates are trusted certificates. L'identité du signataire est inconnue car elle n'a pas été incluse dans votre liste de certificats approuvés et aucun de ses certificats parents n'est un certificat approuvé.
|
||||
The signer's identity is valid. L'identité du signataire est valide.
|
||||
The timestamp authority's certificate was not valid at the time of timestamping. Le certificat de l'autorité d'horodatage n'était pas valide au moment de l'horodatage.
|
||||
The timestamp contents are not hexadecimal. Le contenu de l'horodatage n'est pas hexadécimal.
|
||||
The timestamp has no valid byte range. L'horodatage n'a pas de plage d'octets valide.
|
||||
The timestamp token could not be read ({}). Le jeton d'horodatage n'a pas pu être lu ({}).
|
||||
The timestamp token is valid and its authority is trusted. Le jeton d'horodatage est valide et son autorité est approuvée.
|
||||
The timestamp token is valid, but the timestamp authority is not in your list of trusted certificates. Le jeton d'horodatage est valide, mais l'autorité d'horodatage ne figure pas dans votre liste de certificats approuvés.
|
||||
The timestamp's byte range does not exclude exactly its contents. La plage d'octets de l'horodatage n'exclut pas exactement son contenu.
|
||||
The timestamp's byte range does not match the file. La plage d'octets de l'horodatage ne correspond pas au fichier.
|
||||
The window shows the file name, not the title (Initial View > Show) La fenêtre affiche le nom du fichier et non le titre (Affichage initial > Afficher)
|
||||
Theme Thème
|
||||
There is no folder to save the digital ID in. Il n'y a aucun dossier où enregistrer l'ID numérique.
|
||||
This document has not been modified since this signature was applied. Ce document n'a pas été modifié depuis l'application de cette signature.
|
||||
This document has not been modified since this timestamp was applied. Ce document n'a pas été modifié depuis l'application de cet horodatage.
|
||||
This signature uses RIPEMD-160, a legacy 160-bit hash algorithm that is no longer recommended for signatures. It still validates, but it should not be relied on. Cette signature utilise RIPEMD-160, un ancien algorithme de hachage de 160 bits qui n'est plus recommandé pour les signatures. Elle reste valide, mais il ne faut pas s'y fier.
|
||||
This signature uses SHA-1, a weak hash algorithm: collisions in it have been demonstrated. It still validates because many documents signed years ago use it, but it should not be relied on. Cette signature utilise SHA-1, un algorithme de hachage faible : des collisions ont été démontrées. Elle reste valide car de nombreux documents signés il y a des années l'utilisent, mais il ne faut pas s'y fier.
|
||||
Unsigned signature field Champ de signature non signé
|
||||
Unsigned signature field: {name} Champ de signature non signé : {name}
|
||||
Warning Avertissement
|
||||
Zoom in (⌘+) Zoom avant (⌘+)
|
||||
Zoom in / out (also pinch or ⌘-scroll) Zoom avant / arrière (aussi pincer ou ⌘-défilement)
|
||||
Zoom out (⌘−) Zoom arrière (⌘−)
|
||||
alternate text hides an annotation inside it le texte de remplacement masque une annotation qu'il contient
|
||||
alternate text on an element with no page content texte de remplacement sur un élément sans contenu de page
|
||||
comments commentaires
|
||||
document security store magasin de sécurité du document
|
||||
document structure structure du document
|
||||
form fill remplissage de formulaire
|
||||
its alternate text is inside another element's and will never be read son texte de remplacement est contenu dans celui d'un autre élément et ne sera jamais lu
|
||||
links liens
|
||||
metadata métadonnées
|
||||
no alternate text pas de texte de remplacement
|
||||
no header cells (TH) pas de cellules d'en-tête (TH)
|
||||
no summary pas de résumé
|
||||
not in a TR pas dans un TR
|
||||
not in a Table, THead, TBody or TFoot pas dans un Table, THead, TBody ou TFoot
|
||||
not in an L (list) pas dans un L (liste)
|
||||
not in an LI (list item) pas dans un LI (élément de liste)
|
||||
of sur
|
||||
other changes autres modifications
|
||||
page content contenu de la page
|
||||
page {n} is out of range (1–{count}) la page {n} est hors de l'intervalle (1–{count})
|
||||
pages added or removed pages ajoutées ou supprimées
|
||||
rows have between {min} and {max} columns les lignes comptent entre {min} et {max} colonnes
|
||||
the first heading is an H{n}; headings should not skip levels le premier titre est un H{n} ; les niveaux de titre ne doivent pas être sautés
|
||||
the signed version could not be read la version signée n'a pas pu être lue
|
||||
{n} pages and no bookmarks {n} pages et aucun signet
|
||||
{page} is not a page number or label {page} n'est ni un numéro de page ni une étiquette de page
|
||||
{ty} element on page {p}: {what} Élément {ty} de la page {p} : {what}
|
||||
{ty} element: {what} Élément {ty} : {what}
|
||||
{who}, certificate issued by an unknown issuer. {who}, certificat émis par un émetteur inconnu.
|
||||
{who}, certificate issued by {issuer}. {who}, certificat émis par {issuer}.
|
||||
{} annotation on page {p} isn't tagged Une annotation {} de la page {p} n'est pas balisée
|
||||
{} annotations aren't allowed Les annotations {} ne sont pas autorisées
|
||||
… and {n} more … et {n} autres
|
||||
@plural Delete {n} field|Delete {n} fields Supprimer {n} champ|Supprimer {n} champs
|
||||
@plural {n} byte|{n} bytes {n} octet|{n} octets
|
||||
@plural {n} comment|{n} comments {n} commentaire|{n} commentaires
|
||||
@plural {n} file|{n} files {n} fichier|{n} fichiers
|
||||
@plural {n} image optimized|{n} images optimized {n} image optimisée|{n} images optimisées
|
||||
@plural {n} item discarded|{n} items discarded {n} élément ignoré|{n} éléments ignorés
|
||||
@plural {n} pixel|{n} pixels {n} pixel|{n} pixels
|
||||
@plural {n} result|{n} results {n} résultat|{n} résultats
|
||||
calendar date April avril
|
||||
calendar date August août
|
||||
calendar date December décembre
|
||||
calendar date February février
|
||||
calendar date January janvier
|
||||
calendar date July juillet
|
||||
calendar date June juin
|
||||
calendar date March mars
|
||||
calendar date May mai
|
||||
calendar date November novembre
|
||||
calendar date October octobre
|
||||
calendar date September septembre
|
||||
calendar weekday Fr Ve
|
||||
calendar weekday Mo Lu
|
||||
calendar weekday Sa Sa
|
||||
calendar weekday Su Di
|
||||
calendar weekday Th Je
|
||||
calendar weekday Tu Ma
|
||||
calendar weekday We Me
|
||||
certificate Basic constraints Contraintes de base
|
||||
certificate Intended usage Usage prévu
|
||||
certificate Issued by Émis par
|
||||
certificate Issued to Émis pour
|
||||
certificate Issuer Émetteur
|
||||
certificate Key usage Usage de la clé
|
||||
certificate Public key Clé publique
|
||||
certificate SHA-1 digest Empreinte SHA-1
|
||||
certificate SHA-256 digest Empreinte SHA-256
|
||||
certificate Self-signed Auto-signé
|
||||
certificate Serial number Numéro de série
|
||||
certificate Valid from Valide à partir du
|
||||
certificate Valid to Valide jusqu'au
|
||||
certificate Validity ends Fin de validité
|
||||
certificate Validity starts Début de validité
|
||||
certificate Version Version
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 39.
|
@@ -2705,3 +2705,19 @@ certificate SHA-256 digest Impronta SHA-256
|
||||
Larger thumbnails Miniature più grandi
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Modifica la forma del commento
|
||||
|
||||
# Entries the other catalogs had and Italian lacked (2026-10-21)
|
||||
The password must have at least 8 characters. La password deve contenere almeno 8 caratteri.
|
||||
|
||||
# Entries from #1523 that the catalog lacked.
|
||||
Color Colore
|
||||
Comment Commento
|
||||
Error Errore
|
||||
Next Avanti
|
||||
On Attivo
|
||||
Rotate view clockwise (⇧⌘+) Ruota la vista in senso orario (⇧⌘+)
|
||||
Save (M4) Salva (M4)
|
||||
Save changes? Salvare le modifiche?
|
||||
System Sistema
|
||||
Zoom in / out (also pinch or ⌘-scroll) Ingrandisci / riduci (anche con il pizzico o ⌘+scorrimento)
|
||||
of di
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,18 @@ fn plural_none(_: u64) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// Romanian (CLDR `ro`): 1 is `one`; 0 and numbers whose last two digits are 1–19 (2, 19, 101,
|
||||
/// 119) are `few`; everything else (20, 100, 120) is `other`, the form with "de" ("20 de pagini").
|
||||
fn plural_ro(n: u64) -> usize {
|
||||
if n == 1 {
|
||||
0
|
||||
} else if n == 0 || (1..=19).contains(&(n % 100)) {
|
||||
1
|
||||
} else {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
/// Lithuanian: one (ending in 1 except 11), few (ending in 2–9 except 12–19), other otherwise.
|
||||
fn plural_lithuanian(n: u64) -> usize {
|
||||
match (n % 10, n % 100) {
|
||||
@@ -147,7 +159,7 @@ fn plural_sl(n: u64) -> usize {
|
||||
}
|
||||
|
||||
/// The registry. English first: it is the fallback and the source language.
|
||||
pub static LANGUAGES: [LangInfo; 23] = [
|
||||
pub static LANGUAGES: [LangInfo; 30] = [
|
||||
LangInfo { code: "en", name: "English", source: "", plural: plural_one_other, rtl: false, catalog: OnceLock::new() },
|
||||
LangInfo { code: "ja", name: "日本語", source: include_str!("ja.tsv"), plural: plural_none, rtl: false, catalog: OnceLock::new() },
|
||||
// Simplified Chinese; `zh`, `zh-CN`, `zh-SG` and `zh-Hans-*` locales resolve here (see `candidates`).
|
||||
@@ -198,6 +210,11 @@ pub static LANGUAGES: [LangInfo; 23] = [
|
||||
// Arabic (Modern Standard, Western digits); every `ar-*` locale (`ar-MA`, `ar-EG`, `ar-SA` ...)
|
||||
// resolves here. Right to left: see `LangInfo::rtl`.
|
||||
LangInfo { code: "ar", name: "العربية", source: include_str!("ar.tsv"), plural: plural_arabic, rtl: true, catalog: OnceLock::new() },
|
||||
// Central Kurdish (Sorani); every `ckb-*` locale (`ckb-IQ`, `ckb-IR`) resolves here. Right to
|
||||
// left like Arabic: see `LangInfo::rtl`. CLDR `ckb` counts have two forms (one, other).
|
||||
LangInfo {
|
||||
code: "ckb", name: "کوردیی ناوەندی", source: include_str!("ckb.tsv"), plural: plural_one_other, rtl: true, catalog: OnceLock::new()
|
||||
},
|
||||
// Polish; every `pl-*` locale (`pl-pl`, `pl_pl.UTF-8`) resolves here.
|
||||
LangInfo { code: "pl", name: "Polski", source: include_str!("pl.tsv"), plural: plural_polish, rtl: false, catalog: OnceLock::new() },
|
||||
// Slovene; every `sl-*` locale (`sl-SI`) resolves here. Four plural forms (one, two, few, other).
|
||||
@@ -210,6 +227,19 @@ pub static LANGUAGES: [LangInfo; 23] = [
|
||||
// Vietnamese; every `vi-*` locale (`vi-VN`, `vi_VN.UTF-8`) resolves here. CLDR `vi` counts have
|
||||
// one form ("other"), so `@plural` entries list a single form.
|
||||
LangInfo { code: "vi", name: "Tiếng Việt", source: include_str!("vi.tsv"), plural: plural_none, rtl: false, catalog: OnceLock::new() },
|
||||
// Finnish; every `fi-*` locale (`fi-FI`, `fi_FI.UTF-8`) resolves here. Two plural forms (one, other):
|
||||
// the partitive singular follows any number but 1 (`1 sivu`, `2 sivua`).
|
||||
LangInfo { code: "fi", name: "Suomi", source: include_str!("fi.tsv"), plural: plural_one_other, rtl: false, catalog: OnceLock::new() },
|
||||
// Albanian; every `sq-*` locale (`sq-AL`, `sq_AL.UTF-8`, `sq-XK`) resolves here. One/other plural, like English.
|
||||
LangInfo { code: "sq", name: "Shqip", source: include_str!("sq.tsv"), plural: plural_one_other, rtl: false, catalog: OnceLock::new() },
|
||||
// Thai; every `th-*` locale (`th-TH`, `th_TH.UTF-8`) resolves here. No grammatical plural.
|
||||
LangInfo { code: "th", name: "ไทย", source: include_str!("th.tsv"), plural: plural_none, rtl: false, catalog: OnceLock::new() },
|
||||
// Catalan; every `ca-*` locale (`ca-ES`, `ca_ES.UTF-8`, `ca_ES@valencia`) resolves here.
|
||||
LangInfo { code: "ca", name: "Català", source: include_str!("ca.tsv"), plural: plural_one_other, rtl: false, catalog: OnceLock::new() },
|
||||
// Romanian; every `ro-*` locale (`ro-RO`, `ro_RO.UTF-8`, `ro-MD`) resolves here. Three plural forms (one, few, other).
|
||||
LangInfo { code: "ro", name: "Română", source: include_str!("ro.tsv"), plural: plural_ro, rtl: false, catalog: OnceLock::new() },
|
||||
// Lao; every `lo-*` locale (`lo-LA`, `lo_LA.UTF-8` ...) resolves here.
|
||||
LangInfo { code: "lo", name: "ພາສາລາວ", source: include_str!("lo.tsv"), plural: plural_none, rtl: false, catalog: OnceLock::new() },
|
||||
];
|
||||
|
||||
impl LangInfo {
|
||||
@@ -273,6 +303,16 @@ impl Lang {
|
||||
LANGUAGES.iter().map(Lang)
|
||||
}
|
||||
|
||||
/// Every registered language in the order a picker lists them: English first (the source
|
||||
/// language and the fallback), then the rest by their own name with accents folded, so
|
||||
/// Čeština sits under C rather than after Z. Names in other scripts follow the Latin ones in
|
||||
/// code point order: Greek, Cyrillic, Arabic, then the CJK languages.
|
||||
pub fn for_picker() -> Vec<Lang> {
|
||||
let mut rest: Vec<Lang> = Lang::all().filter(|l| l.code() != Lang::EN.code()).collect();
|
||||
rest.sort_by_cached_key(|l| name_sort_key(l.name()));
|
||||
std::iter::once(Lang::EN).chain(rest).collect()
|
||||
}
|
||||
|
||||
pub fn name(self) -> &'static str {
|
||||
self.0.name
|
||||
}
|
||||
@@ -601,6 +641,27 @@ pub fn trn(lang: Lang, n: u64, one: &str, other: &str) -> String {
|
||||
fmt(text, &[("n", &n.to_string())])
|
||||
}
|
||||
|
||||
/// `name` lowercased with the Latin accents that occur in language names folded away, so a
|
||||
/// byte-wise sort reads alphabetically. Other scripts are left as they are.
|
||||
fn name_sort_key(name: &str) -> String {
|
||||
name.chars()
|
||||
.flat_map(char::to_lowercase)
|
||||
.map(|c| match c {
|
||||
'à'..='å' | 'ā' | 'ă' | 'ą' => 'a',
|
||||
'ç' | 'ć' | 'č' => 'c',
|
||||
'è'..='ë' | 'ē' | 'ě' | 'ę' | 'ế' | 'ệ' => 'e',
|
||||
'ì'..='ï' | 'ī' => 'i',
|
||||
'ñ' | 'ń' | 'ň' => 'n',
|
||||
'ò'..='ö' | 'ø' | 'ő' => 'o',
|
||||
'ś' | 'š' => 's',
|
||||
'ù'..='ü' | 'ū' | 'ů' | 'ű' => 'u',
|
||||
'ý' | 'ÿ' => 'y',
|
||||
'ź' | 'ż' | 'ž' => 'z',
|
||||
c => c,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::catalog::{Entry, parse_entries, placeholders};
|
||||
@@ -643,6 +704,9 @@ mod tests {
|
||||
assert_eq!(lang_from_tag("zh"), Lang::from_code("zh-hans"));
|
||||
assert_eq!(lang_from_tag("zh_HK.UTF-8"), Lang::from_code("zh-hant"));
|
||||
assert_eq!(lang_from_tag("zh-Hant-MO"), Lang::from_code("zh-hant"));
|
||||
assert_eq!(lang_from_tag("lo_LA.UTF-8"), Lang::from_code("lo"));
|
||||
assert_eq!(lang_from_tag("lo-LA"), Lang::from_code("lo"));
|
||||
assert_eq!(lang_from_tag("lo"), Lang::from_code("lo"));
|
||||
assert_eq!(lang_from_tag(""), None);
|
||||
assert_eq!(lang_from_tag("_"), None);
|
||||
}
|
||||
@@ -655,6 +719,7 @@ mod tests {
|
||||
assert_eq!(candidates("zh_TW"), ["zh-tw", "zh-hant", "zh"]);
|
||||
assert_eq!(candidates("zh-CN"), ["zh-cn", "zh-hans", "zh"]);
|
||||
assert_eq!(candidates("zh-Hant-HK"), ["zh-hant-hk", "zh-hant", "zh"]);
|
||||
assert_eq!(candidates("lo_LA.UTF-8"), ["lo-la", "lo"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -689,6 +754,7 @@ mod tests {
|
||||
}
|
||||
assert_eq!(first_supported("en-US\r\n"), Some(Lang::EN));
|
||||
assert_eq!(first_supported("fr-FR\r\n"), Lang::from_code("fr"));
|
||||
assert_eq!(first_supported("lo-LA\r\n"), Lang::from_code("lo"));
|
||||
assert_eq!(first_supported("\r\n"), None);
|
||||
}
|
||||
|
||||
@@ -1021,6 +1087,26 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// Polish translates every `tl!("…")` literal in the UI source, as Japanese does.
|
||||
#[test]
|
||||
fn polish_covers_ui_literals() {
|
||||
let pl = Lang::from_code("pl").expect("pl registered");
|
||||
let missing: Vec<_> = ui_literals().into_iter().filter(|label| !has(pl, label)).collect();
|
||||
assert!(missing.is_empty(), "untranslated Polish UI literals: {missing:#?}");
|
||||
}
|
||||
|
||||
/// Polish says everything a signature's validation says, and the changes after signing it
|
||||
/// names, keeping each sentence's holes: a Polish signature panel listed these in English.
|
||||
#[test]
|
||||
fn polish_says_what_a_signature_says() {
|
||||
let pl = Lang::from_code("pl").expect("pl registered");
|
||||
for wording in pdfcraft_engine::sign::pdf::WORDINGS.iter().chain(pdfcraft_engine::sign::pdf::kind::ALL) {
|
||||
assert!(has(pl, wording), "missing signature wording: {wording}");
|
||||
let said = tr(pl, wording);
|
||||
assert_eq!(wording.matches("{}").count(), said.matches("{}").count(), "the Polish of {wording:?} loses a hole: {said:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// Japanese translates every `tl!("…")` literal in the UI source, so a new string can't ship in
|
||||
/// English by accident (the same check French, German, Russian and Simplified Chinese have).
|
||||
#[test]
|
||||
@@ -1182,6 +1268,28 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn brazilian_portuguese_covers_catalog_union() {
|
||||
let pt = Lang::from_code("pt-br").expect("pt-br registered");
|
||||
let pt_catalog = pt.catalog();
|
||||
for language in LANGUAGES.iter().filter(|language| !language.source.is_empty()) {
|
||||
let (entries, errors) = catalog::parse_entries(language.source, language.plural_forms());
|
||||
assert!(errors.is_empty(), "{} catalog: {errors:?}", language.code);
|
||||
for entry in entries {
|
||||
let covered = match entry.context.as_str() {
|
||||
"" => pt_catalog.plain(&entry.source).is_some(),
|
||||
"@id" => pt_catalog.id(&entry.source).is_some(),
|
||||
"@plural" => {
|
||||
let (one, other) = entry.source.split_once('|').expect("validated plural source");
|
||||
pt_catalog.plural(one, other, 0).is_some()
|
||||
}
|
||||
context => pt_catalog.contextual(context, &entry.source).is_some(),
|
||||
};
|
||||
assert!(covered, "Brazilian Portuguese lacks {} / {:?}", entry.context, entry.source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check direct lookups and multiline literals as well as ordinary tl!("literal") calls,
|
||||
/// following the complete-catalog check for Simplified Chinese.
|
||||
#[test]
|
||||
@@ -1457,6 +1565,7 @@ mod tests {
|
||||
"Text",
|
||||
"Index",
|
||||
"Metadata",
|
||||
"metadata",
|
||||
"Model",
|
||||
"{field}: {e}",
|
||||
"{0}: {1}",
|
||||
@@ -1544,6 +1653,69 @@ mod tests {
|
||||
set_current(Lang::EN);
|
||||
}
|
||||
|
||||
/// Czech says everything the layers below word for themselves (see
|
||||
/// `spanish_covers_what_the_engine_says`), and keeps each sentence's holes.
|
||||
#[test]
|
||||
fn czech_covers_what_the_engine_says() {
|
||||
let cs = Lang::from_code("cs").expect("cs registered");
|
||||
let lists: [(&str, &[&str]); 8] = [
|
||||
("accessibility finding", pdfcraft_engine::a11y::WORDINGS),
|
||||
("accessibility report", pdfcraft_engine::a11y::REPORT_WORDS),
|
||||
("PDF/A problem", pdfcraft_engine::pdfa::WORDINGS),
|
||||
("signature detail", pdfcraft_engine::sign::pdf::WORDINGS),
|
||||
("change after signing", pdfcraft_engine::sign::pdf::kind::ALL),
|
||||
("pages to print", pdfcraft_engine::print::WORDINGS),
|
||||
("edit label", pdfcraft_engine::EDIT_LABELS),
|
||||
("batch label", pdfcraft_engine::BATCH_LABELS),
|
||||
];
|
||||
for (what, list) in lists {
|
||||
assert!(!list.is_empty(), "no {what} wordings to cover");
|
||||
for wording in list {
|
||||
assert!(has(cs, wording), "missing {what}: {wording}");
|
||||
let said = tr(cs, wording);
|
||||
assert_eq!(wording.matches("{}").count(), said.matches("{}").count(), "the Czech of {wording:?} loses a hole: {said:?}");
|
||||
for hole in wording.split('{').skip(1).filter_map(|rest| rest.split_once('}')).map(|(name, _)| name).filter(|n| !n.is_empty()) {
|
||||
assert!(said.contains(&format!("{{{hole}}}")), "the Czech of {wording:?} loses {{{hole}}}: {said:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
assert_eq!(tr(cs, "Signature is valid"), "Podpis je platný");
|
||||
}
|
||||
|
||||
/// The date picker's weekday heads and the certificate viewer's fields are looked up in their
|
||||
/// own contexts, which the `tl!` scan doesn't see: none of them may fall back to English.
|
||||
#[test]
|
||||
fn czech_covers_weekdays_and_certificate_fields() {
|
||||
let cs = Lang::from_code("cs").expect("cs registered");
|
||||
assert_eq!(
|
||||
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map(|day| tr_ctx(cs, "calendar weekday", day)),
|
||||
["Ne", "Po", "Út", "St", "Čt", "Pá", "So"]
|
||||
);
|
||||
assert_eq!(tr_ctx(cs, "certificate", "Subject"), "Subjekt");
|
||||
for field in [
|
||||
"Issued to",
|
||||
"Issued by",
|
||||
"Valid from",
|
||||
"Valid to",
|
||||
"Intended usage",
|
||||
"Serial number",
|
||||
"Issuer",
|
||||
"Validity starts",
|
||||
"Validity ends",
|
||||
"Public key",
|
||||
"Basic constraints",
|
||||
"Key usage",
|
||||
"Self-signed",
|
||||
"SHA-1 digest",
|
||||
"SHA-256 digest",
|
||||
"Version",
|
||||
] {
|
||||
assert_ne!(tr_ctx(cs, "certificate", field), field, "certificate field remains untranslated: {field}");
|
||||
}
|
||||
assert_eq!(trn(cs, 3, "{n} file", "{n} files"), "3 soubory");
|
||||
assert_eq!(fmt(tr(cs, "{n} tags"), &[("n", "1")]), "Tagy: 1");
|
||||
}
|
||||
|
||||
/// Turkish covers every registered menu title and menu command label, keeps ellipses, and
|
||||
/// persists in preferences.
|
||||
#[test]
|
||||
@@ -2172,6 +2344,102 @@ mod tests {
|
||||
set_current(Lang::EN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finnish_is_registered_and_persists() {
|
||||
let fi = Lang::from_code("fi").expect("fi registered");
|
||||
assert_eq!(fi.name(), "Suomi");
|
||||
assert_eq!(normalize_pref("FI"), Some("fi"));
|
||||
for tag in ["fi", "fi-FI", "fi_FI.UTF-8", "FI-fi"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(fi), "{tag}");
|
||||
}
|
||||
// Filipino (`fil`) and Swedish in Finland (`sv-FI`) don't pick Finnish.
|
||||
assert_ne!(lang_from_tag("fil"), Some(fi));
|
||||
assert_ne!(lang_from_tag("sv-FI"), Some(fi));
|
||||
assert_eq!(tr(fi, "File"), "Tiedosto");
|
||||
assert_eq!(tr(fi, "Edit"), "Muokkaa");
|
||||
assert_eq!(tr(fi, "Save"), "Tallenna");
|
||||
assert_eq!(tr(fi, "Interface language"), "Käyttöliittymän kieli");
|
||||
// The partitive singular follows any number but 1.
|
||||
assert_eq!(trn(fi, 0, "{n} page", "{n} pages"), "0 sivua");
|
||||
assert_eq!(trn(fi, 1, "{n} page", "{n} pages"), "1 sivu");
|
||||
assert_eq!(trn(fi, 2, "{n} page", "{n} pages"), "2 sivua");
|
||||
assert_eq!(trn(fi, 21, "{n} page", "{n} pages"), "21 sivua");
|
||||
// Calendar headings use the nominative, dates the partitive.
|
||||
assert_eq!(fmt(tr(fi, "{month} {y}"), &[("month", tr(fi, "October")), ("y", "2026")]), "Lokakuu 2026");
|
||||
assert_eq!(
|
||||
fmt(tr(fi, "{month} {day}, {y}"), &[("month", tr_ctx(fi, "calendar date", "October")), ("day", "14"), ("y", "2026")]),
|
||||
"14. lokakuuta 2026"
|
||||
);
|
||||
let mut app = crate::PdfCraftApp::default();
|
||||
app.set_option("language", "FI").unwrap();
|
||||
assert_eq!(app.language, "fi");
|
||||
let mut restored = crate::PdfCraftApp::default();
|
||||
restored.restore(&app.persist());
|
||||
assert_eq!(restored.language, "fi");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finnish_covers_commands_and_tools() {
|
||||
let fi = Lang::from_code("fi").expect("fi registered");
|
||||
let mut missing = std::collections::BTreeSet::new();
|
||||
for command in pdfcraft_engine::commands::COMMANDS {
|
||||
if !has(fi, command.label) {
|
||||
missing.insert(command.label);
|
||||
}
|
||||
if let Some(menu) = command.menu
|
||||
&& !has(fi, menu)
|
||||
{
|
||||
missing.insert(menu);
|
||||
}
|
||||
}
|
||||
for group in pdfcraft_engine::catalog::TOOL_GROUPS {
|
||||
if !has(fi, group.label) {
|
||||
missing.insert(group.label);
|
||||
}
|
||||
for section in group.sections {
|
||||
if !has(fi, section.title) {
|
||||
missing.insert(section.title);
|
||||
}
|
||||
for item in section.items {
|
||||
if !has(fi, item.label) {
|
||||
missing.insert(item.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(missing.is_empty(), "Finnish misses commands/tools: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finnish_covers_ui_literals() {
|
||||
let fi = Lang::from_code("fi").expect("fi registered");
|
||||
let missing: Vec<_> = scan_ui_literals(true).into_iter().filter(|label| !has(fi, label)).collect();
|
||||
assert!(missing.is_empty(), "Untranslated Finnish UI labels: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finnish_covers_bundled_catalog_keys() {
|
||||
// Compare English keys, not other languages' translations.
|
||||
let fi = Lang::from_code("fi").expect("fi registered");
|
||||
let mut missing = std::collections::BTreeSet::new();
|
||||
for reference in LANGUAGES.iter().filter(|language| language.code != "fi") {
|
||||
let (entries, errors) = catalog::parse_entries(reference.source, reference.plural_forms());
|
||||
assert!(errors.is_empty(), "{}: invalid reference catalog: {errors:?}", reference.code);
|
||||
for entry in entries {
|
||||
let translated = match entry.context.as_str() {
|
||||
"" => fi.catalog().plain(&entry.source),
|
||||
"@id" => fi.catalog().id(&entry.source),
|
||||
"@plural" => entry.source.split_once('|').and_then(|(one, other)| fi.catalog().plural(one, other, 0)),
|
||||
context => fi.catalog().contextual(context, &entry.source),
|
||||
};
|
||||
if translated.is_none() {
|
||||
missing.insert((entry.context, entry.source));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(missing.is_empty(), "Finnish misses bundled catalog keys: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn lithuanian_is_registered_and_persists() {
|
||||
let lt = Lang::from_code("lt").expect("lt registered");
|
||||
@@ -2524,6 +2792,46 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn romanian_is_registered_with_three_plural_forms() {
|
||||
let ro = Lang::from_code("ro").expect("ro registered");
|
||||
for tag in ["ro", "ro-RO", "ro_RO.UTF-8", "RO-ro", "ro-MD"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(ro), "{tag}");
|
||||
}
|
||||
assert_eq!(normalize_pref("Ro"), Some("ro"));
|
||||
let info = LANGUAGES.iter().find(|language| language.code == "ro").expect("ro row");
|
||||
assert_eq!(info.plural_forms(), 3);
|
||||
// one: 1; few: 0 and n % 100 in 1..=19 ("2 pagini", "101 pagini"); other: the "de" form ("20 de pagini").
|
||||
for (n, form) in [(1, 0), (0, 1), (2, 1), (19, 1), (101, 1), (119, 1), (20, 2), (100, 2), (120, 2), (1000, 2)] {
|
||||
assert_eq!(plural_ro(n), form, "{n}");
|
||||
}
|
||||
assert_eq!(trn(ro, 1, "{n} page", "{n} pages"), "1 pagină");
|
||||
assert_eq!(trn(ro, 5, "{n} page", "{n} pages"), "5 pagini");
|
||||
assert_eq!(trn(ro, 25, "{n} page", "{n} pages"), "25 de pagini");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn romanian_covers_bundled_catalog_keys() {
|
||||
let ro = Lang::from_code("ro").expect("ro registered");
|
||||
let mut missing = std::collections::BTreeSet::new();
|
||||
for reference in LANGUAGES.iter().filter(|language| language.code != "ro") {
|
||||
let (entries, errors) = catalog::parse_entries(reference.source, reference.plural_forms());
|
||||
assert!(errors.is_empty(), "{}: invalid reference catalog: {errors:?}", reference.code);
|
||||
for entry in entries {
|
||||
let translated = match entry.context.as_str() {
|
||||
"" => ro.catalog().plain(&entry.source),
|
||||
"@id" => ro.catalog().id(&entry.source),
|
||||
"@plural" => entry.source.split_once('|').and_then(|(one, other)| ro.catalog().plural(one, other, 0)),
|
||||
context => ro.catalog().contextual(context, &entry.source),
|
||||
};
|
||||
if translated.is_none() {
|
||||
missing.insert((entry.context, entry.source));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(missing.is_empty(), "Romanian misses bundled catalog keys: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn vietnamese_covers_bundled_catalog_keys() {
|
||||
let vi = Lang::from_code("vi").expect("vi registered");
|
||||
@@ -2613,6 +2921,89 @@ mod tests {
|
||||
assert!(unchanged.is_empty(), "unapproved English Vietnamese catalog entries: {unchanged:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn catalan_is_registered_and_persists() {
|
||||
let ca = Lang::from_code("ca").expect("ca registered");
|
||||
assert_eq!(ca.name(), "Català");
|
||||
assert_eq!(normalize_pref("CA"), Some("ca"));
|
||||
for tag in ["ca", "ca-ES", "ca_ES.UTF-8", "CA-es", "ca_ES@valencia"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(ca), "{tag}");
|
||||
}
|
||||
assert_eq!(first_supported("ca-ES\r\nen-US"), Some(ca));
|
||||
assert_eq!(tr(ca, "File"), "Fitxer");
|
||||
assert_eq!(tr(ca, "Save as…"), "Anomena i desa…");
|
||||
assert_eq!(tr(ca, "Cancel"), "Cancel·la");
|
||||
assert_eq!(tr_ctx(ca, "comment menu", "Edit"), "Edita");
|
||||
assert_eq!(tr_ctx(ca, "signature pad", "Type"), "Escriu");
|
||||
// one (1), other (0, 2+), as in English
|
||||
assert_eq!((0..=3).map(|n| (ca.0.plural)(n)).collect::<Vec<_>>(), [1, 0, 1, 1]);
|
||||
assert_eq!(trn(ca, 1, "{n} page", "{n} pages"), "1 pàgina");
|
||||
assert_eq!(trn(ca, 3, "{n} page", "{n} pages"), "3 pàgines");
|
||||
let mut app = crate::PdfCraftApp::default();
|
||||
app.set_option("language", "CA").unwrap();
|
||||
assert_eq!(app.language, "ca");
|
||||
let mut restored = crate::PdfCraftApp::default();
|
||||
restored.restore(&app.persist());
|
||||
assert_eq!(restored.language, "ca");
|
||||
assert!(restored.set_option("language", "xx").is_err());
|
||||
assert_eq!(restored.language, "ca");
|
||||
}
|
||||
|
||||
/// Catalan translates every registered command, menu, All tools group, section and item.
|
||||
#[test]
|
||||
fn catalan_covers_commands_and_catalogue() {
|
||||
let ca = Lang::from_code("ca").expect("ca registered");
|
||||
for command in pdfcraft_engine::commands::COMMANDS {
|
||||
assert!(has(ca, command.label), "missing command: {}", command.label);
|
||||
if let Some(menu) = command.menu {
|
||||
assert!(has(ca, menu), "missing menu: {menu}");
|
||||
}
|
||||
}
|
||||
for group in pdfcraft_engine::catalog::TOOL_GROUPS {
|
||||
assert!(has(ca, group.label), "missing group: {}", group.label);
|
||||
for section in group.sections {
|
||||
assert!(has(ca, section.title), "missing section: {}", section.title);
|
||||
for item in section.items {
|
||||
assert!(has(ca, item.label), "missing item: {}", item.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Catalan translates every `tl!("…")` literal in the UI source, so a new string can't ship in
|
||||
/// English by accident.
|
||||
#[test]
|
||||
fn catalan_covers_ui_literals() {
|
||||
let ca = Lang::from_code("ca").expect("ca registered");
|
||||
let literals = ui_literals();
|
||||
assert!(literals.len() > 900, "source scan found only {} literals", literals.len());
|
||||
let missing: Vec<_> = literals.iter().filter(|label| !has(ca, label)).collect();
|
||||
assert!(missing.is_empty(), "untranslated Catalan UI literals: {missing:#?}");
|
||||
}
|
||||
|
||||
/// Catalan has every key the other bundled catalogs have (English keys, not their translations).
|
||||
#[test]
|
||||
fn catalan_covers_bundled_catalog_keys() {
|
||||
let ca = Lang::from_code("ca").expect("ca registered");
|
||||
let mut missing = std::collections::BTreeSet::new();
|
||||
for reference in LANGUAGES.iter().filter(|language| language.code != "ca") {
|
||||
let (entries, errors) = catalog::parse_entries(reference.source, reference.plural_forms());
|
||||
assert!(errors.is_empty(), "{}: invalid reference catalog: {errors:?}", reference.code);
|
||||
for entry in entries {
|
||||
let translated = match entry.context.as_str() {
|
||||
"" => ca.catalog().plain(&entry.source),
|
||||
"@id" => ca.catalog().id(&entry.source),
|
||||
"@plural" => entry.source.split_once('|').and_then(|(one, other)| ca.catalog().plural(one, other, 0)),
|
||||
context => ca.catalog().contextual(context, &entry.source),
|
||||
};
|
||||
if translated.is_none() {
|
||||
missing.insert((entry.context, entry.source));
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(missing.is_empty(), "Catalan misses bundled catalog keys: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slovene_is_registered_and_persists() {
|
||||
let sl = Lang::from_code("sl").expect("sl registered");
|
||||
@@ -2642,6 +3033,60 @@ mod tests {
|
||||
assert_eq!(restored.language, "sl");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn albanian_is_registered_and_persists() {
|
||||
let sq = Lang::from_code("sq").expect("sq registered");
|
||||
assert_eq!(sq.name(), "Shqip");
|
||||
assert_eq!(normalize_pref("SQ"), Some("sq"));
|
||||
for tag in ["sq", "sq-AL", "sq_AL.UTF-8", "SQ-xk", "sq_XK@variant"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(sq), "{tag}");
|
||||
}
|
||||
assert_eq!(first_supported("sq-AL\r\nen-US"), Some(sq));
|
||||
assert_eq!(tr(sq, "File"), "Skedari");
|
||||
// one (1), other (0, 2+)
|
||||
assert_eq!((0..=3).map(|n| (sq.0.plural)(n)).collect::<Vec<_>>(), [1, 0, 1, 1]);
|
||||
assert_eq!(trn(sq, 1, "{n} page", "{n} pages"), "1 faqe");
|
||||
assert_eq!(trn(sq, 0, "{n} page", "{n} pages"), "0 faqe");
|
||||
assert_eq!(trn(sq, 5, "{n} page", "{n} pages"), "5 faqe");
|
||||
let mut app = crate::PdfCraftApp::default();
|
||||
app.set_option("language", "SQ").unwrap();
|
||||
assert_eq!(app.language, "sq");
|
||||
let mut restored = crate::PdfCraftApp::default();
|
||||
restored.restore(&app.persist());
|
||||
assert_eq!(restored.language, "sq");
|
||||
assert!(restored.set_option("language", "xx").is_err());
|
||||
assert_eq!(restored.language, "sq");
|
||||
}
|
||||
|
||||
/// Albanian translates every registered command and every All tools group, section and item.
|
||||
#[test]
|
||||
fn albanian_covers_commands_and_catalogue() {
|
||||
let sq = Lang::from_code("sq").expect("sq registered");
|
||||
for command in pdfcraft_engine::commands::COMMANDS {
|
||||
assert!(has(sq, command.label), "missing command: {}", command.label);
|
||||
if let Some(menu) = command.menu {
|
||||
assert!(has(sq, menu), "missing menu: {menu}");
|
||||
}
|
||||
}
|
||||
for group in pdfcraft_engine::catalog::TOOL_GROUPS {
|
||||
assert!(has(sq, group.label), "missing group: {}", group.label);
|
||||
for section in group.sections {
|
||||
assert!(has(sq, section.title), "missing section: {}", section.title);
|
||||
for item in section.items {
|
||||
assert!(has(sq, item.label), "missing item: {}", item.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// New tl!("literal") labels must not silently fall back to English.
|
||||
#[test]
|
||||
fn albanian_covers_ui_literals() {
|
||||
let sq = Lang::from_code("sq").expect("sq registered");
|
||||
let missing: Vec<_> = scan_ui_literals(false).into_iter().filter(|label| !has(sq, label)).collect();
|
||||
assert!(missing.is_empty(), "untranslated Albanian UI literals: {missing:#?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn slovene_plurals_cover_dual_few_teens_and_large_counts() {
|
||||
let sl = Lang::from_code("sl").expect("sl registered");
|
||||
@@ -3283,7 +3728,8 @@ mod tests {
|
||||
let ar = arabic();
|
||||
assert_eq!(ar.name(), "العربية");
|
||||
assert!(ar.rtl());
|
||||
assert!(Lang::all().filter(|l| l.rtl()).eq([ar]), "Arabic is the only right-to-left language");
|
||||
let rtl: Vec<&str> = Lang::all().filter(|l| l.rtl()).map(|l| l.code()).collect();
|
||||
assert_eq!(rtl, ["ar", "ckb"], "Arabic and Kurdish are the right-to-left languages");
|
||||
assert_eq!(normalize_pref("AR"), Some("ar"));
|
||||
for tag in ["ar", "ar-MA", "ar_EG.UTF-8", "AR-sa", "ar_DZ@variant"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(ar), "{tag}");
|
||||
@@ -3426,3 +3872,19 @@ mod tests {
|
||||
assert_eq!(dates, interface);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod picker_order_tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn picker_lists_english_first_then_names_alphabetically() {
|
||||
let order = Lang::for_picker();
|
||||
assert_eq!(order.first().map(|l| l.code()), Some(Lang::EN.code()));
|
||||
assert_eq!(order.len(), Lang::all().count());
|
||||
let keys: Vec<String> = order[1..].iter().map(|l| name_sort_key(l.name())).collect();
|
||||
assert!(keys.windows(2).all(|w| w[0] <= w[1]), "{keys:?}");
|
||||
assert_eq!(name_sort_key("Čeština"), "cestina");
|
||||
assert_eq!(name_sort_key("Türkçe"), "turkce");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2469,3 +2469,117 @@ animation effects Off Wyłączone
|
||||
Larger thumbnails Większe miniatury
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Zmień kształt komentarza
|
||||
|
||||
# Signature validation: what a signature's details say and the changes after signing they name
|
||||
# (pdfcraft_engine::sign::pdf::WORDINGS and kind::ALL).
|
||||
The signature has no valid byte range. Podpis nie ma prawidłowego zakresu bajtów.
|
||||
The signature's byte range does not match the file. Zakres bajtów podpisu nie odpowiada plikowi.
|
||||
The signature's byte range does not exclude exactly its contents. Zakres bajtów podpisu nie pomija dokładnie jego zawartości.
|
||||
The signature contents are not hexadecimal. Zawartość podpisu nie jest zapisana szesnastkowo.
|
||||
The signature could not be read ({}). Nie udało się odczytać podpisu ({}).
|
||||
PdfCraft can't check this signature yet: {}. PdfCraft nie potrafi jeszcze sprawdzić tego podpisu: {}.
|
||||
The signature uses the legacy adbe.x509.rsa_sha1 format. Podpis używa przestarzałego formatu adbe.x509.rsa_sha1.
|
||||
The signature is BER-encoded (indefinite lengths) rather than DER; it was read leniently. Podpis jest zakodowany w BER (długości nieokreślone), a nie w DER; odczytano go z tolerancją.
|
||||
The signed content is a constructed (segmented) OCTET STRING, as BER allows; it was read anyway. Podpisana treść jest złożonym (segmentowanym) OCTET STRING, na co pozwala BER; mimo to ją odczytano.
|
||||
The RSA signature value does not have the length of the key's modulus (leading zero bytes dropped or added); it was read anyway. Wartość podpisu RSA nie ma długości modułu klucza (pominięte lub dodane początkowe bajty zerowe); mimo to ją odczytano.
|
||||
The RSA signature's DigestInfo has no NULL parameter (older signers write it so); it was read anyway. DigestInfo podpisu RSA nie ma parametru NULL (tak zapisują go starsze programy); mimo to go odczytano.
|
||||
The ECDSA signature is not in canonical DER (trailing bytes, padding or a missing sign byte); it was read anyway. Podpis ECDSA nie jest w kanonicznym DER (nadmiarowe bajty końcowe, dopełnienie lub brak bajtu znaku); mimo to go odczytano.
|
||||
The ECDSA signature is the raw r and s values instead of a DER sequence; it was read anyway. Podpis ECDSA zawiera surowe wartości r i s zamiast sekwencji DER; mimo to go odczytano.
|
||||
The signature algorithm and the SignerInfo's digest algorithm name different hashes; the signature was made with the SignerInfo's. Algorytm podpisu i algorytm skrótu w SignerInfo wskazują różne funkcje skrótu; podpis złożono funkcją wskazaną w SignerInfo.
|
||||
This signature uses SHA-1, a weak hash algorithm: collisions in it have been demonstrated. It still validates because many documents signed years ago use it, but it should not be relied on. Ten podpis używa SHA-1, słabej funkcji skrótu, dla której wykazano kolizje. Podpis nadal przechodzi weryfikację, bo używa jej wiele dokumentów podpisanych przed laty, ale nie należy na nim polegać.
|
||||
This signature uses RIPEMD-160, a legacy 160-bit hash algorithm that is no longer recommended for signatures. It still validates, but it should not be relied on. Ten podpis używa RIPEMD-160, przestarzałej 160-bitowej funkcji skrótu, której nie zaleca się już do podpisów. Podpis nadal przechodzi weryfikację, ale nie należy na nim polegać.
|
||||
The document has been altered or corrupted since the signature was applied. Dokument został zmieniony lub uszkodzony po złożeniu podpisu.
|
||||
The signer's certificate is not in the signature. Podpis nie zawiera certyfikatu podpisującego.
|
||||
The signature value does not match the signer's certificate: the signature is corrupt. Wartość podpisu nie pasuje do certyfikatu podpisującego: podpis jest uszkodzony.
|
||||
The signature could not be checked ({}). Nie udało się sprawdzić podpisu ({}).
|
||||
The signature could not be verified ({}). Nie udało się zweryfikować podpisu ({}).
|
||||
This document has not been modified since this signature was applied. Dokument nie był modyfikowany od złożenia tego podpisu.
|
||||
The document has been modified since this signature was applied, but the changes are permitted ({}). Dokument zmodyfikowano po złożeniu tego podpisu, ale zmiany są dozwolone ({}).
|
||||
The document has been altered since this signature was applied in ways it does not permit ({}). Dokument zmieniono po złożeniu tego podpisu w sposób, na który podpis nie pozwala ({}).
|
||||
The signer's certificate was not valid at the time of signing. Certyfikat podpisującego nie był ważny w chwili podpisania.
|
||||
The signer's certificate does not allow digital signatures (its key usage has neither digital signature nor non-repudiation). Certyfikat podpisującego nie pozwala na podpisy cyfrowe (jego użycie klucza nie obejmuje ani podpisu cyfrowego, ani niezaprzeczalności).
|
||||
The signer's certificate is not issued for signing documents (its extended key usage has no document-signing purpose). Certyfikat podpisującego nie jest wystawiony do podpisywania dokumentów (jego rozszerzone użycie klucza nie obejmuje podpisywania dokumentów).
|
||||
The signer's certificate has critical extensions PdfCraft does not recognize ({}). Certyfikat podpisującego ma rozszerzenia krytyczne, których PdfCraft nie rozpoznaje ({}).
|
||||
The certificate of {} is not a CA certificate that may issue certificates, so it is not used to vouch for {}. Certyfikat podmiotu {} nie jest certyfikatem urzędu certyfikacji, który może wystawiać certyfikaty, dlatego nie poświadcza certyfikatu {}.
|
||||
The certificate of {} does not allow this many CA certificates below it (path length), so it is not used to vouch for {}. Certyfikat podmiotu {} nie dopuszcza tylu certyfikatów urzędów certyfikacji poniżej siebie (długość ścieżki), dlatego nie poświadcza certyfikatu {}.
|
||||
The certificate of {} was not valid at the time of signing, so it is not used to vouch for {}. Certyfikat podmiotu {} nie był ważny w chwili podpisania, dlatego nie poświadcza certyfikatu {}.
|
||||
The signer's identity is unknown because it has not been included in your list of trusted certificates and none of its parent certificates are trusted certificates. Tożsamość podpisującego jest nieznana, ponieważ jego certyfikatu nie ma na liście zaufanych certyfikatów i żaden z certyfikatów nadrzędnych nie jest zaufany.
|
||||
The signer's identity is valid. Tożsamość podpisującego jest prawidłowa.
|
||||
The signature includes an embedded timestamp. Podpis zawiera osadzony znacznik czasu.
|
||||
Signing time is from the clock on the signer's computer. Czas podpisania pochodzi z zegara komputera podpisującego.
|
||||
The signature's timestamp token does not cover the signature value. Token znacznika czasu nie obejmuje wartości podpisu.
|
||||
The signature's timestamp token could not be verified ({}). Nie udało się zweryfikować tokenu znacznika czasu podpisu ({}).
|
||||
The embedded timestamp token is valid and its authority is trusted; trusted time is {}. Osadzony token znacznika czasu jest prawidłowy, a jego urząd jest zaufany; zaufany czas to {}.
|
||||
The signature carries an unverified timestamp ({}): the timestamp authority is not in your list of trusted certificates, so the signing time claimed by the signer is used instead. Podpis zawiera niezweryfikowany znacznik czasu ({}): urzędu znacznika czasu nie ma na liście zaufanych certyfikatów, dlatego użyto czasu podpisania podanego przez podpisującego.
|
||||
The signer's certificate has been revoked ({}). Certyfikat podpisującego został unieważniony ({}).
|
||||
The document's embedded revocation information shows that the signer's certificate has not been revoked. Osadzone w dokumencie informacje o unieważnieniach potwierdzają, że certyfikat podpisującego nie został unieważniony.
|
||||
The timestamp has no valid byte range. Znacznik czasu nie ma prawidłowego zakresu bajtów.
|
||||
The timestamp's byte range does not match the file. Zakres bajtów znacznika czasu nie odpowiada plikowi.
|
||||
The timestamp's byte range does not exclude exactly its contents. Zakres bajtów znacznika czasu nie pomija dokładnie jego zawartości.
|
||||
The timestamp contents are not hexadecimal. Zawartość znacznika czasu nie jest zapisana szesnastkowo.
|
||||
The timestamp token could not be read ({}). Nie udało się odczytać tokenu znacznika czasu ({}).
|
||||
The document has been altered or corrupted since the timestamp was applied. Dokument został zmieniony lub uszkodzony po dodaniu znacznika czasu.
|
||||
The timestamp authority's certificate was not valid at the time of timestamping. Certyfikat urzędu znacznika czasu nie był ważny w chwili oznaczania czasem.
|
||||
This document has not been modified since this timestamp was applied. Dokument nie był modyfikowany od dodania tego znacznika czasu.
|
||||
The document has been modified since this timestamp was applied, but the changes are permitted ({}). Dokument zmodyfikowano po dodaniu tego znacznika czasu, ale zmiany są dozwolone ({}).
|
||||
The document has been altered since this timestamp was applied in ways it does not permit ({}). Dokument zmieniono po dodaniu tego znacznika czasu w sposób, na który znacznik nie pozwala ({}).
|
||||
The timestamp token is valid and its authority is trusted. Token znacznika czasu jest prawidłowy, a jego urząd jest zaufany.
|
||||
The timestamp token is valid, but the timestamp authority is not in your list of trusted certificates. Token znacznika czasu jest prawidłowy, ale urzędu znacznika czasu nie ma na liście zaufanych certyfikatów.
|
||||
Unsigned signature field Niepodpisane pole podpisu
|
||||
Signature is valid Podpis jest prawidłowy
|
||||
Signature validity is unknown Ważność podpisu jest nieznana
|
||||
Signature is invalid Podpis jest nieprawidłowy
|
||||
page content zawartość stron
|
||||
form fill wypełnianie formularzy
|
||||
comments komentarze
|
||||
document security store magazyn zabezpieczeń dokumentu
|
||||
metadata metadane
|
||||
links łącza
|
||||
document structure struktura dokumentu
|
||||
pages added or removed dodane lub usunięte strony
|
||||
other changes inne zmiany
|
||||
the signed version could not be read nie udało się odczytać podpisanej wersji
|
||||
|
||||
# The rest of the interface the Polish catalog lacked.
|
||||
Auto ({percent}%) Automatycznie ({percent}%)
|
||||
Auto follows the system's text size. Pages always render at the display's full resolution. Tryb automatyczny dopasowuje się do rozmiaru tekstu w systemie. Strony są zawsze renderowane w pełnej rozdzielczości ekranu.
|
||||
Check the pages Sprawdź strony
|
||||
Collapse all Zwiń wszystko
|
||||
Discard this text (Esc) Odrzuć ten tekst (Esc)
|
||||
Done adding text Zakończ dodawanie tekstu
|
||||
Drawing scale changes. Use Actual size for full-scale plans. Skala rysunku się zmieni. Do planów w pełnej skali użyj opcji Rzeczywisty rozmiar.
|
||||
Expand all Rozwiń wszystko
|
||||
Files are combined in the order shown. Drag them to change it. Pliki są łączone w pokazanej kolejności. Przeciągnij je, aby ją zmienić.
|
||||
Fill colour Kolor wypełnienia
|
||||
Fill colour: none Kolor wypełnienia: brak
|
||||
For page sizes and margins. Dotyczy rozmiarów stron i marginesów.
|
||||
Grid view Widok siatki
|
||||
Import list… Importuj listę…
|
||||
Interface size Rozmiar interfejsu
|
||||
List view Widok listy
|
||||
Margins Marginesy
|
||||
Match page at 100% Dopasuj stronę w skali 100%
|
||||
Multiple words or phrases Wiele słów lub fraz
|
||||
New bookmarks from structure Nowe zakładki ze struktury
|
||||
No fill Bez wypełnienia
|
||||
Offset from centre Przesunięcie od środka
|
||||
One word or phrase per line Jedno słowo lub fraza w wierszu
|
||||
PDF page: {size} Strona PDF: {size}
|
||||
PDF scale: {scale}% Skala PDF: {scale}%
|
||||
Pages: {k} of {n} Strony: {k} z {n}
|
||||
Preview unavailable: {e} Podgląd niedostępny: {e}
|
||||
Printer paper and scaling may differ. Check driver settings. Papier i skalowanie w drukarce mogą się różnić. Sprawdź ustawienia sterownika.
|
||||
Remove page Usuń stronę
|
||||
Remove {n} pages Usuń strony ({n})
|
||||
Some bookmarks are not shown here: the panel lists a limited number, nested a limited depth. Niektóre zakładki nie są tu widoczne: panel pokazuje ograniczoną ich liczbę i ograniczoną głębokość zagnieżdżenia.
|
||||
Switch to List view to change the pages it takes. Przełącz na widok listy, aby zmienić strony, które obejmuje.
|
||||
The document's security settings don't allow copying text and images Ustawienia zabezpieczeń dokumentu nie pozwalają kopiować tekstu i obrazów
|
||||
{n} word(s) or phrase(s) Słowa lub frazy: {n}
|
||||
You are viewing revision {rev} of “{from}”. It is a snapshot: changes here won't affect the original. Wyświetlasz rewizję {rev} dokumentu „{from}”. To migawka: zmiany wprowadzone tutaj nie wpłyną na oryginał.
|
||||
You are viewing the signed version of “{from}” (revision {rev}). It is a snapshot: changes here won't affect the original. Wyświetlasz podpisaną wersję dokumentu „{from}” (rewizja {rev}). To migawka: zmiany wprowadzone tutaj nie wpłyną na oryginał.
|
||||
# Untranslated: English text until a translator fills these in.
|
||||
Float panel Float panel
|
||||
Move to group Move to group
|
||||
Panels Panels
|
||||
Resize panel window Resize panel window
|
||||
Resize panels Resize panels
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -2493,6 +2493,62 @@ animation effects Off Desativados
|
||||
Make properties default Tornar propriedades padrão
|
||||
Pages selected Páginas selecionadas
|
||||
Page properties Propriedades da página
|
||||
|
||||
# Remaining keys from the current catalog union, translated from their English meaning (2026-10-21).
|
||||
on page {label} na página {label}
|
||||
A font isn't embedded Uma fonte não está incorporada
|
||||
A {} action isn't allowed A ação {} não é permitida
|
||||
A {} annotation has additional actions A anotação {} tem ações adicionais
|
||||
A {} annotation has no appearance stream A anotação {} não tem fluxo de aparência
|
||||
A {} annotation isn't set to print, or is hidden A anotação {} não está configurada para impressão ou está oculta
|
||||
Accessibility Report Relatório de acessibilidade
|
||||
Add the PDFs to combine Adicione os PDFs que deseja combinar
|
||||
Added the first {n} PDFs in {folder} Os primeiros {n} PDFs de {folder} foram adicionados
|
||||
Always Sempre
|
||||
Automatically Automaticamente
|
||||
CRL Signing Assinatura de CRL
|
||||
Certificate Signing Assinatura de certificado
|
||||
Change Author Alterar autor
|
||||
Change Keywords Alterar palavras-chave
|
||||
Change Subject Alterar assunto
|
||||
Change Title Alterar título
|
||||
Choose a digital ID. Escolha uma identidade digital.
|
||||
Choose a file… Escolher um arquivo…
|
||||
Choose a folder… Escolher uma pasta…
|
||||
Choose… Escolher…
|
||||
Color Cor
|
||||
Comment Comentário
|
||||
Comment and review Comentar e revisar
|
||||
Copied to clipboard Copiado para a área de transferência
|
||||
Copy to clipboard Copiar para a área de transferência
|
||||
Create folder Criar pasta
|
||||
Create links Criar links
|
||||
Creator Criador
|
||||
Cut and stack needs Two-sided: Off. Print single-sided sheets. Recortar e empilhar requer Frente e verso: desativado. Imprima em folhas de um só lado.
|
||||
Data Encipherment Criptografia de dados
|
||||
Decipher Only Somente descriptografia
|
||||
Detailed Report Relatório detalhado
|
||||
DeviceCMYK is used, but the PDF/A output intent isn't a CMYK profile O DeviceCMYK está em uso, mas o perfil de saída do PDF/A não é um perfil CMYK
|
||||
DeviceRGB is used, but the PDF/A output intent isn't an RGB profile O DeviceRGB está em uso, mas o perfil de saída do PDF/A não é um perfil RGB
|
||||
Digital Signature Assinatura digital
|
||||
Disabled Desativado
|
||||
Document properties (⌘D) Propriedades do documento (⌘D)
|
||||
Drop PDFs or folders here, or choose them. Solte PDFs ou pastas aqui, ou selecione-os.
|
||||
Duplicate Duplicar
|
||||
Enabled Ativado
|
||||
Encipher Only Somente criptografia
|
||||
English Inglês
|
||||
Enter a URL Informe uma URL
|
||||
Enter a name. Informe um nome.
|
||||
Enter a page number Informe o número da página
|
||||
Enter the field names Informe os nomes dos campos
|
||||
Error Erro
|
||||
Every PDF in the folder Todos os PDFs da pasta
|
||||
Every PDF in the folder and the folders inside it Todos os PDFs da pasta e de suas subpastas
|
||||
Field "{}" on page {p} has no description (tooltip) O campo "{}" na página {p} não tem descrição (dica de ferramenta)
|
||||
Filename Nome do arquivo
|
||||
Flatten Fill & Sign Achatar Preencher e assinar
|
||||
Folder Pasta
|
||||
Font Fonte
|
||||
Bulleted list Lista com marcadores
|
||||
Numbered list Lista numerada
|
||||
@@ -2507,3 +2563,204 @@ animation effects Off Desativados
|
||||
Larger thumbnails Miniaturas maiores
|
||||
# Lines, connected lines and polygons reshaped by their ends and corners (M5).
|
||||
Reshape comment Alterar a forma do comentário
|
||||
Font (unnamed) on page {p} doesn't map its characters to Unicode A fonte (sem nome) na página {p} não mapeia seus caracteres para Unicode
|
||||
Font {} on page {p} doesn't map its characters to Unicode A fonte {} na página {p} não mapeia seus caracteres para Unicode
|
||||
Form field on page {p} isn't tagged O campo de formulário na página {p} não está marcado com tag
|
||||
Help… Ajuda…
|
||||
H{n} follows an H{d}; headings should not skip levels H{n} vem depois de H{d}; os títulos não devem pular níveis
|
||||
Import Importar
|
||||
Information Informações
|
||||
Key Agreement Acordo de chaves
|
||||
Key Encipherment Cifragem de chaves
|
||||
Loading… Carregando…
|
||||
Mouse wheel scroll speed Velocidade de rolagem da roda do mouse
|
||||
Move Mover
|
||||
Never Nunca
|
||||
New bookmark (⌘B) Novo marcador (⌘B)
|
||||
Next Próximo
|
||||
Next (⌘G) Próximo (⌘G)
|
||||
No PDFs found in {folder} Nenhum PDF encontrado em {folder}
|
||||
No document language is set Nenhum idioma foi definido para o documento
|
||||
No page has text: the document appears to be images of pages Nenhuma página contém texto: o documento parece ser composto por imagens de páginas
|
||||
No results Nenhum resultado
|
||||
Non-Repudiation Não repúdio
|
||||
On Ativado
|
||||
Only the document's owner can change its security (open it with the permissions password) Somente o proprietário do documento pode alterar sua segurança (abra-o com a senha de permissões)
|
||||
Open a PDF (⌘O) Abrir um PDF (⌘O)
|
||||
Open folder Abrir pasta
|
||||
Organize Organizar
|
||||
Page {n} Página {n}
|
||||
Page {n} of {total} Página {n} de {total}
|
||||
Page {p} doesn't tab in structure order A ordem de tabulação da página {p} não segue a ordem da estrutura
|
||||
Page {p}: {n} untagged content item Página {p}: {n} item de conteúdo sem tag
|
||||
Page {p}: {n} untagged content items Página {p}: {n} itens de conteúdo sem tag
|
||||
Page {} has additional actions A página {} tem ações adicionais
|
||||
Panel layout could not be restored: {error} Não foi possível restaurar o layout dos painéis: {error}
|
||||
Panel move was not applied: {error} A movimentação do painel não foi aplicada: {error}
|
||||
Paste Colar
|
||||
PdfCraft can't check this signature yet: {}. O PdfCraft ainda não pode verificar esta assinatura: {}.
|
||||
Previous Anterior
|
||||
Previous (⇧⌘G) Anterior (⇧⌘G)
|
||||
Print (⌘P) Imprimir (⌘P)
|
||||
Producer Produtor
|
||||
Refresh Atualizar
|
||||
Rendering… Renderizando…
|
||||
Report created Relatório criado
|
||||
Rev. {rev}: Certified by an unknown signer Rev. {rev}: certificada por um signatário desconhecido
|
||||
Rev. {rev}: Certified by {name} Rev. {rev}: certificada por {name}
|
||||
Rev. {rev}: Signed by an unknown signer Rev. {rev}: assinada por um signatário desconhecido
|
||||
Rev. {rev}: Signed by {name} Rev. {rev}: assinada por {name}
|
||||
Rotate view clockwise (⇧⌘+) Girar a visualização no sentido horário (⇧⌘+)
|
||||
Rule Name Nome da regra
|
||||
Save (M4) Salvar (M4)
|
||||
Save as {level} Salvar como {level}
|
||||
Save changes? Salvar as alterações?
|
||||
Save file Salvar arquivo
|
||||
Search results Resultados da pesquisa
|
||||
Select all Selecionar tudo
|
||||
Signature is invalid A assinatura é inválida
|
||||
Signature is valid A assinatura é válida
|
||||
Signature validity is unknown A validade da assinatura é desconhecida
|
||||
Signing time is from the clock on the signer's computer. O horário da assinatura vem do relógio do computador do signatário.
|
||||
Still rendering — this page is unusually complex… Ainda renderizando — esta página é excepcionalmente complexa…
|
||||
Success Sucesso
|
||||
System Sistema
|
||||
Text recognition isn't installed: its models are missing (run `cargo xtask models`, or set PDFCRAFT_MODELS). O reconhecimento de texto não está instalado: faltam os modelos (execute `cargo xtask models` ou defina PDFCRAFT_MODELS).
|
||||
The ECDSA signature is not in canonical DER (trailing bytes, padding or a missing sign byte); it was read anyway. A assinatura ECDSA não está no formato DER canônico (há bytes excedentes, preenchimento ou falta o byte de sinal); mesmo assim, ela foi lida.
|
||||
The ECDSA signature is the raw r and s values instead of a DER sequence; it was read anyway. A assinatura ECDSA contém os valores brutos de r e s em vez de uma sequência DER; mesmo assim, ela foi lida.
|
||||
The RSA signature value does not have the length of the key's modulus (leading zero bytes dropped or added); it was read anyway. O valor da assinatura RSA não tem o mesmo comprimento do módulo da chave (bytes zero iniciais foram removidos ou adicionados); mesmo assim, ele foi lido.
|
||||
The RSA signature's DigestInfo has no NULL parameter (older signers write it so); it was read anyway. O DigestInfo da assinatura RSA não tem o parâmetro NULL (assinantes mais antigos o incluem); mesmo assim, ele foi lido.
|
||||
The certificate of {} does not allow this many CA certificates below it (path length), so it is not used to vouch for {}. O certificado de {} não permite essa quantidade de certificados de AC abaixo dele (comprimento do caminho), então não é usado para atestar a validade de {}.
|
||||
The certificate of {} is not a CA certificate that may issue certificates, so it is not used to vouch for {}. O certificado de {} não é um certificado de AC autorizado a emitir certificados, então não é usado para atestar a validade de {}.
|
||||
The certificate of {} was not valid at the time of signing, so it is not used to vouch for {}. O certificado de {} não era válido no momento da assinatura, então não é usado para atestar a validade de {}.
|
||||
The checker found problems which may prevent the document from being fully accessible. A verificação encontrou problemas que podem impedir que o documento seja totalmente acessível.
|
||||
The document has been altered or corrupted since the signature was applied. O documento foi alterado ou corrompido desde que a assinatura foi aplicada.
|
||||
The document has been altered or corrupted since the timestamp was applied. O documento foi alterado ou corrompido desde que o carimbo de data e hora foi aplicado.
|
||||
The document has been altered since this signature was applied in ways it does not permit ({}). O documento foi alterado de maneiras não permitidas ({}), depois que esta assinatura foi aplicada.
|
||||
The document has been altered since this timestamp was applied in ways it does not permit ({}). O documento foi alterado de maneiras não permitidas ({}), depois que este carimbo de data e hora foi aplicado.
|
||||
The document has been modified since this signature was applied, but the changes are permitted ({}). O documento foi modificado depois que esta assinatura foi aplicada, mas as alterações são permitidas ({}).
|
||||
The document has been modified since this timestamp was applied, but the changes are permitted ({}). O documento foi modificado depois que este carimbo de data e hora foi aplicado, mas as alterações são permitidas ({}).
|
||||
The document has no tags (structure tree) O documento não tem tags (árvore de estrutura)
|
||||
The document has no title O documento não tem título
|
||||
The document isn't marked as tagged (MarkInfo Marked) O documento não está marcado como etiquetado (MarkInfo Marked)
|
||||
The document isn't tagged, so none of its content is O documento não está etiquetado, portanto nenhum conteúdo está
|
||||
The document's embedded revocation information shows that the signer's certificate has not been revoked. As informações de revogação incorporadas ao documento indicam que o certificado do signatário não foi revogado.
|
||||
The embedded timestamp token is valid and its authority is trusted; trusted time is {}. O token de carimbo de data e hora incorporado é válido e sua autoridade é confiável; o horário confiável é {}.
|
||||
The font {} isn't embedded A fonte {} não está incorporada
|
||||
The metadata doesn't identify the file as {} Os metadados não identificam o arquivo como {}
|
||||
The password is incorrect. A senha está incorreta.
|
||||
The password must have at least 6 characters. A senha deve ter pelo menos 6 caracteres.
|
||||
The password must have at least 8 characters. A senha deve ter pelo menos 8 caracteres.
|
||||
The passwords do not match. As senhas não correspondem.
|
||||
The security settings don't allow screen readers to read the text As configurações de segurança não permitem que leitores de tela leiam o texto
|
||||
The signature algorithm and the SignerInfo's digest algorithm name different hashes; the signature was made with the SignerInfo's. O algoritmo de assinatura e o algoritmo de resumo do SignerInfo indicam hashes diferentes; a assinatura foi feita com o hash indicado pelo SignerInfo.
|
||||
The signature carries an unverified timestamp ({}): the timestamp authority is not in your list of trusted certificates, so the signing time claimed by the signer is used instead. A assinatura contém um carimbo de data e hora não verificado ({}): a autoridade de carimbo de data e hora não está na sua lista de certificados confiáveis, então será usado o horário de assinatura informado pelo signatário.
|
||||
The signature contents are not hexadecimal. O conteúdo da assinatura não está em hexadecimal.
|
||||
The signature could not be checked ({}). Não foi possível verificar a assinatura ({}).
|
||||
The signature could not be read ({}). Não foi possível ler a assinatura ({}).
|
||||
The signature could not be verified ({}). Não foi possível validar a assinatura ({}).
|
||||
The signature has no valid byte range. A assinatura não tem um intervalo de bytes válido.
|
||||
The signature includes an embedded timestamp. A assinatura inclui um carimbo de data e hora incorporado.
|
||||
The signature is BER-encoded (indefinite lengths) rather than DER; it was read leniently. A assinatura está codificada em BER (comprimentos indefinidos), e não em DER; ela foi lida de forma permissiva.
|
||||
The signature uses the legacy adbe.x509.rsa_sha1 format. A assinatura usa o formato legado adbe.x509.rsa_sha1.
|
||||
The signature value does not match the signer's certificate: the signature is corrupt. O valor da assinatura não corresponde ao certificado do signatário: a assinatura está corrompida.
|
||||
The signature's byte range does not exclude exactly its contents. O intervalo de bytes da assinatura não exclui exatamente o conteúdo dela.
|
||||
The signature's byte range does not match the file. O intervalo de bytes da assinatura não corresponde ao arquivo.
|
||||
The signature's timestamp token could not be verified ({}). Não foi possível validar o token de carimbo de data e hora da assinatura ({}).
|
||||
The signature's timestamp token does not cover the signature value. O token de carimbo de data e hora da assinatura não abrange o valor da assinatura.
|
||||
The signed content is a constructed (segmented) OCTET STRING, as BER allows; it was read anyway. O conteúdo assinado é uma OCTET STRING construída (segmentada), como permite o BER; mesmo assim, foi lido.
|
||||
The signer's certificate does not allow digital signatures (its key usage has neither digital signature nor non-repudiation). O certificado do signatário não permite assinaturas digitais (o uso da chave não inclui assinatura digital nem não repúdio).
|
||||
The signer's certificate has been revoked ({}). O certificado do signatário foi revogado ({}).
|
||||
The signer's certificate has critical extensions PdfCraft does not recognize ({}). O certificado do signatário tem extensões críticas que o PdfCraft não reconhece ({}).
|
||||
The signer's certificate is not in the signature. O certificado do signatário não está incluído na assinatura.
|
||||
The signer's certificate is not issued for signing documents (its extended key usage has no document-signing purpose). O certificado do signatário não foi emitido para assinar documentos (o uso estendido da chave não inclui essa finalidade).
|
||||
The signer's certificate was not valid at the time of signing. O certificado do signatário não era válido no momento da assinatura.
|
||||
The signer's identity is unknown because it has not been included in your list of trusted certificates and none of its parent certificates are trusted certificates. A identidade do signatário é desconhecida porque não foi incluída na sua lista de certificados confiáveis e nenhum dos certificados na cadeia acima dela é confiável.
|
||||
The signer's identity is valid. A identidade do signatário é válida.
|
||||
The timestamp authority's certificate was not valid at the time of timestamping. O certificado da autoridade de carimbo de data e hora não era válido no momento da emissão do carimbo.
|
||||
The timestamp contents are not hexadecimal. O conteúdo do carimbo de data e hora não está em hexadecimal.
|
||||
The timestamp has no valid byte range. O carimbo de data e hora não tem um intervalo de bytes válido.
|
||||
The timestamp token could not be read ({}). Não foi possível ler o token de carimbo de data e hora ({}).
|
||||
The timestamp token is valid and its authority is trusted. O token de carimbo de data e hora é válido e sua autoridade é confiável.
|
||||
The timestamp token is valid, but the timestamp authority is not in your list of trusted certificates. O token de carimbo de data e hora é válido, mas a autoridade não está na sua lista de certificados confiáveis.
|
||||
The timestamp's byte range does not exclude exactly its contents. O intervalo de bytes do carimbo de data e hora não exclui exatamente o conteúdo dele.
|
||||
The timestamp's byte range does not match the file. O intervalo de bytes do carimbo de data e hora não corresponde ao arquivo.
|
||||
The window shows the file name, not the title (Initial View > Show) A janela exibe o nome do arquivo, e não o título (Exibição inicial > Mostrar)
|
||||
Theme Tema
|
||||
There is no folder to save the digital ID in. Não há uma pasta para salvar a identidade digital.
|
||||
This document has not been modified since this signature was applied. Este documento não foi modificado desde que esta assinatura foi aplicada.
|
||||
This document has not been modified since this timestamp was applied. Este documento não foi modificado desde que este carimbo de data e hora foi aplicado.
|
||||
This file changed on disk. Reload it to see the new version; your unsaved changes will be lost. Este arquivo foi alterado no disco. Recarregue-o para ver a nova versão; suas alterações não salvas serão perdidas.
|
||||
This signature uses RIPEMD-160, a legacy 160-bit hash algorithm that is no longer recommended for signatures. It still validates, but it should not be relied on. Esta assinatura usa RIPEMD-160, um algoritmo de hash legado de 160 bits que não é mais recomendado para assinaturas. Ela ainda é validada, mas não deve ser considerada confiável.
|
||||
This signature uses SHA-1, a weak hash algorithm: collisions in it have been demonstrated. It still validates because many documents signed years ago use it, but it should not be relied on. Esta assinatura usa SHA-1, um algoritmo de hash fraco para o qual já foram demonstradas colisões. Ela ainda é validada porque muitos documentos assinados há anos o utilizam, mas não deve ser considerada confiável.
|
||||
Unsigned signature field Campo de assinatura não assinado
|
||||
Unsigned signature field: {name} Campo de assinatura não assinado: {name}
|
||||
Warning Aviso
|
||||
Zoom in (⌘+) Ampliar (⌘+)
|
||||
Zoom in / out (also pinch or ⌘-scroll) Ampliar / reduzir (também com pinça ou rolagem com ⌘)
|
||||
Zoom out (⌘−) Reduzir (⌘−)
|
||||
alternate text hides an annotation inside it o texto alternativo oculta uma anotação em seu interior
|
||||
alternate text on an element with no page content texto alternativo em um elemento sem conteúdo na página
|
||||
comments comentários
|
||||
document security store repositório de segurança do documento
|
||||
document structure estrutura do documento
|
||||
form fill preenchimento de formulário
|
||||
its alternate text is inside another element's and will never be read seu texto alternativo está dentro do texto de outro elemento e nunca será lido
|
||||
links links
|
||||
metadata metadados
|
||||
no alternate text sem texto alternativo
|
||||
no header cells (TH) sem células de cabeçalho (TH)
|
||||
no summary sem resumo
|
||||
not in a TR fora de uma TR
|
||||
not in a Table, THead, TBody or TFoot fora de uma Table, THead, TBody ou TFoot
|
||||
not in an L (list) fora de uma L (lista)
|
||||
not in an LI (list item) fora de um LI (item de lista)
|
||||
of de
|
||||
other changes outras alterações
|
||||
page content conteúdo da página
|
||||
page {n} is out of range (1–{count}) a página {n} está fora do intervalo (1–{count})
|
||||
pages added or removed páginas adicionadas ou removidas
|
||||
rows have between {min} and {max} columns as linhas têm entre {min} e {max} colunas
|
||||
the first heading is an H{n}; headings should not skip levels o primeiro título é H{n}; os títulos não devem pular níveis
|
||||
the signed version could not be read não foi possível ler a versão assinada
|
||||
{n} pages and no bookmarks {n} páginas e nenhum marcador
|
||||
{page} is not a page number or label {page} não é um número nem um rótulo de página
|
||||
{ty} element on page {p}: {what} elemento {ty} na página {p}: {what}
|
||||
{ty} element: {what} elemento {ty}: {what}
|
||||
{who}, certificate issued by an unknown issuer. {who}, certificado emitido por uma autoridade desconhecida.
|
||||
{who}, certificate issued by {issuer}. {who}, certificado emitido por {issuer}.
|
||||
{} annotation on page {p} isn't tagged A anotação {} na página {p} não está marcada com tag
|
||||
{} annotations aren't allowed As anotações {} não são permitidas
|
||||
… and {n} more … e mais {n}
|
||||
@plural Delete {n} field|Delete {n} fields Excluir {n} campo|Excluir {n} campos
|
||||
@plural {n} byte|{n} bytes {n} byte|{n} bytes
|
||||
@plural {n} comment|{n} comments {n} comentário|{n} comentários
|
||||
@plural {n} file|{n} files {n} arquivo|{n} arquivos
|
||||
@plural {n} image optimized|{n} images optimized {n} imagem otimizada|{n} imagens otimizadas
|
||||
@plural {n} item discarded|{n} items discarded {n} item descartado|{n} itens descartados
|
||||
@plural {n} pixel|{n} pixels {n} pixel|{n} pixels
|
||||
@plural {n} result|{n} results {n} resultado|{n} resultados
|
||||
calendar weekday Fr Sex
|
||||
calendar weekday Mo Seg
|
||||
calendar weekday Sa Sáb
|
||||
calendar weekday Su Dom
|
||||
calendar weekday Th Qui
|
||||
calendar weekday Tu Ter
|
||||
calendar weekday We Qua
|
||||
certificate Basic constraints Restrições básicas
|
||||
certificate Intended usage Uso pretendido
|
||||
certificate Issued by Emitido por
|
||||
certificate Issued to Emitido para
|
||||
certificate Issuer Emissor
|
||||
certificate Key usage Uso da chave
|
||||
certificate Public key Chave pública
|
||||
certificate SHA-1 digest Resumo SHA-1
|
||||
certificate SHA-256 digest Resumo SHA-256
|
||||
certificate Self-signed Autoassinado
|
||||
certificate Serial number Número de série
|
||||
certificate Valid from Válido desde
|
||||
certificate Valid to Válido até
|
||||
certificate Validity ends Fim da validade
|
||||
certificate Validity starts Início da validade
|
||||
certificate Version Versão
|
||||
theme Appearance Aparência
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 9 and column 16.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -271,7 +271,7 @@ pub(crate) fn preferences_body(ui: &mut egui::Ui, app: &mut PdfCraftApp, t: &Tok
|
||||
if ui.selectable_value(&mut app.language, crate::i18n::AUTO.to_string(), tl!("Auto")).clicked() {
|
||||
ui.close();
|
||||
}
|
||||
for language in crate::i18n::Lang::all() {
|
||||
for language in crate::i18n::Lang::for_picker() {
|
||||
if ui.selectable_value(&mut app.language, language.code().to_string(), language.name()).clicked() {
|
||||
ui.close();
|
||||
}
|
||||
|
||||
@@ -111,7 +111,9 @@ impl Default for MarksDraft {
|
||||
}
|
||||
|
||||
const PAGE_FORMATS: [&str; 5] = ["<<1>>", "<<1 of n>>", "<<1/n>>", "<<Page 1>>", "<<Page 1 of n>>"];
|
||||
const DATE_FORMATS: [&str; 6] = ["<<m/d/yyyy>>", "<<mm/dd/yyyy>>", "<<d/m/yyyy>>", "<<yyyy-mm-dd>>", "<<m/d/yy>>", "<<mmmm d, yyyy>>"];
|
||||
// New formats go last: `date_format` is an index into this list.
|
||||
const DATE_FORMATS: [&str; 8] =
|
||||
["<<m/d/yyyy>>", "<<mm/dd/yyyy>>", "<<d/m/yyyy>>", "<<yyyy-mm-dd>>", "<<m/d/yy>>", "<<mmmm d, yyyy>>", "<<yyyy/mm/dd>>", "<<yyyy/m/d>>"];
|
||||
const BOX_NAMES: [&str; 6] =
|
||||
["Left Header Text", "Center Header Text", "Right Header Text", "Left Footer Text", "Center Footer Text", "Right Footer Text"];
|
||||
|
||||
|
||||
@@ -314,7 +314,7 @@ fn ui_fonts_work_without_craft_fonts() {
|
||||
theme::install_fonts(&ctx);
|
||||
}
|
||||
|
||||
/// Latin- and Cyrillic-script catalogs (Czech, Brazilian Portuguese, German, Spanish, French, Russian, Bulgarian, Hungarian, Ukrainian, Italian, Slovene) are drawn entirely by the app's own faces
|
||||
/// Latin- and Cyrillic-script catalogs (Czech, Brazilian Portuguese, German, Spanish, French, Russian, Bulgarian, Hungarian, Ukrainian, Italian, Slovene, Albanian, Catalan) are drawn entirely by the app's own faces
|
||||
/// (Inter, JetBrains Mono with Inter fallback): no letter falls through to egui's defaults or a CJK fallback. (egui's
|
||||
/// `has_glyphs` can't answer this: with only the primary face it is also the replacement face.)
|
||||
#[test]
|
||||
@@ -342,6 +342,10 @@ fn primary_ui_fonts_cover_latin_and_cyrillic_catalogs() {
|
||||
("sl", include_str!("../src/i18n/sl.tsv")),
|
||||
("lt", include_str!("../src/i18n/lt.tsv")),
|
||||
("vi", include_str!("../src/i18n/vi.tsv")),
|
||||
("fi", include_str!("../src/i18n/fi.tsv")),
|
||||
("sq", include_str!("../src/i18n/sq.tsv")),
|
||||
("ca", include_str!("../src/i18n/ca.tsv")),
|
||||
("ro", include_str!("../src/i18n/ro.tsv")),
|
||||
] {
|
||||
let mut text = String::from("áčďéěíňóřšťúůýžÁČĎÉĚÍŇÓŘŠŤÚŮÝŽãõçâêôàÃÕÇÂÊÔÀñÑüÜäÄöÖőűß„“¿¡«»…ґҐєЄіІїЇәғқңөұүһӘҒҚҢӨҰҮҺ");
|
||||
for line in catalog.lines().filter(|l| !l.starts_with('#')) {
|
||||
|
||||
+32
-19
@@ -1,7 +1,7 @@
|
||||
# Localization parity
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-13 · **Change:** minor (Vietnamese 100% of current key union; native-speaker community review; twelve-language mean ≈68%) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-14 · **Change:** minor (Italian count after completing its catalog) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
> **Last reviewed:** 2026-10-21 · **Last updated:** 2026-10-21 · **Change:** minor (Brazilian Portuguese now covers the 2,674-key catalog union; twelve-language mean still rounds to ≈68%; Spanish 100% of the current key union) · **Target:** Adobe Acrobat Pro (Acrobat DC, continuous track 26.002.21931, macOS)
|
||||
|
||||
Per-language status of PdfCraft's interface against Acrobat Pro's. How translations work and how to
|
||||
add a language: [localization.md](localization.md). Summary in [ROADMAP.md](../ROADMAP.md).
|
||||
@@ -9,11 +9,16 @@ add a language: [localization.md](localization.md). Summary in [ROADMAP.md](../R
|
||||
## How this was measured
|
||||
|
||||
- **Strings translated** is measured: the catalogs in `crates/ui-egui/src/i18n/<code>.tsv`, counted
|
||||
as distinct `(context, English)` keys with a non-empty translation. The **current** denominator is
|
||||
the union of keys across all catalogs (**2,590** plain keys as of 2026-10-13, plus language-specific
|
||||
context rows such as Vietnamese `theme`/`Appearance`). The twelve-language percentage table below
|
||||
still quotes the **historical 2,143-key snapshot** from 2026-10-10 for every language except
|
||||
Vietnamese (re-measured against the current union). English is built in.
|
||||
as distinct `(context, English)` keys with a non-empty translation. The denominator is the union of
|
||||
keys across all catalogs, counting language-specific context rows such as `theme`/`Appearance`.
|
||||
**That union is a moving target**: every change that adds a string widens it, so a count is only
|
||||
comparable with others measured on the same date, and a catalog that reached 100% falls behind
|
||||
without losing a single translation. Every figure here therefore carries its date. The current
|
||||
union is **2,674** keys as of 2026-10-20, against the **2,143-key snapshot** of 2026-10-10; earlier
|
||||
revisions quote the union of their own date (see the revision history), not this one. The
|
||||
twelve-language percentage table below still quotes the 2026-10-10 snapshot for every language
|
||||
except Spanish, Vietnamese, Lithuanian and Brazilian Portuguese, which are measured against the current union. English is
|
||||
built in.
|
||||
- **Not counted:** error details from the engine and the operating system, which are shown in
|
||||
English inside a translated frame; there is no translated user documentation or help yet (Acrobat
|
||||
ships localized help).
|
||||
@@ -31,16 +36,16 @@ add a language: [localization.md](localization.md). Summary in [ROADMAP.md](../R
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| English | `en` | built in (100%) | all; README and docs | Latin | yes | **full** | yes | 0 |
|
||||
| Simplified Chinese | `zh-hans` | 2,088 (97.4%) | dialogs and tooltips through `tl!`; no help | CJK text and IME work, but **release builds have no Hans face**: many characters show as boxes (#826, #688, #728, #758; Flatpak #689) | no | partial | yes | 6–12 |
|
||||
| Spanish | `es` | 2,046 (95.5%) | dialogs and tooltips; no help | Latin | no | partial | yes | 2–4 |
|
||||
| Spanish | `es` | 2,674 (100% of current key union) | dialogs and tooltips; no help | Latin | no | partial | yes | 2–4 |
|
||||
| Hindi | `hi` | 0 | none | Devanagari not tested (egui shapes Telugu conjuncts, so shaping is likely workable); no Devanagari face in craft-fonts | no | none | no | 10–18 |
|
||||
| Arabic | `ar` | 2,143 (100%) | dialogs and tooltips; no help | Letters joined and lines reordered at load, but **layout not mirrored**, wrapped lines break at the wrong end, typed text runs left to right (`localization.md` §Arabic) | no | partial | yes (Middle East edition) | 25–45 |
|
||||
| French | `fr` | 2,128 (99.3%) | dialogs and tooltips; no help | Latin | no | partial | yes | 1–2 |
|
||||
| Portuguese (Brazil) | `pt-br` | 2,130 (99.4%) | dialogs and tooltips; no help | Latin | community (#288) | partial | yes | 1–2 |
|
||||
| Portuguese (Brazil) | `pt-br` | 2,674 (100% of current union) | dialogs and tooltips; no help | Latin | community (#288) | partial | yes | 1–2 |
|
||||
| Indonesian | `id` | 0 | none | Latin | no | none | no | 3–5 |
|
||||
| Japanese | `ja` | 2,123 (99.1%) | dialogs and tooltips; no help | BIZ UDPGothic from craft-fonts; IME patched on macOS, Windows, X11, Wayland; vertical text renders but can't be edited | no | partial | yes | 4–8 |
|
||||
| German | `de` | 2,128 (99.3%) | dialogs and tooltips; no help | Latin | community, in progress (#828: terminology, clipping) | partial | yes | 2–4 |
|
||||
| Korean | `ko` | 0 | none | Hangul IME patched (Microsoft and Apple Korean, `vendor/README.md` winit 3, 6, 9, 10); no Hangul UI face in craft-fonts | no | none | yes | 6–10 |
|
||||
| Vietnamese | `vi` | 2,591 (100% of current union + theme Appearance) | dialogs and tooltips; no help | Latin with stacked diacritics; bundled Inter covers them (fonts test) | community | partial | no | 2–4 |
|
||||
| Vietnamese | `vi` | 2,674 (100% of current key union) | dialogs and tooltips; no help | Latin with stacked diacritics; bundled Inter covers them (fonts test) | community | partial | no | 2–4 |
|
||||
|
||||
**Localization dimension ≈ 68%**: the mean over the twelve, counting a catalog's percentage but only
|
||||
60% for Chinese and Arabic until their script problems are fixed, and 0 for Hindi, Indonesian and
|
||||
@@ -49,8 +54,8 @@ to bring all twelve to `full`, of which ≈ 35–60 h is engineering (Hans face,
|
||||
and the rest catalogs and fixes; native-speaker review needs humans.
|
||||
|
||||
No language is `full` except English: every catalog leaves engine error details in English, and
|
||||
none has translated help. Vietnamese's **To `full`** hours are therefore residual help/docs polish
|
||||
(catalog and script work are already done), not missing UI strings.
|
||||
none has translated help. The **To `full`** hours of Vietnamese and Spanish are therefore residual
|
||||
help/docs polish (catalog and script work are already done), not missing UI strings.
|
||||
|
||||
## Other shipped languages
|
||||
|
||||
@@ -59,7 +64,7 @@ none has translated help. Vietnamese's **To `full`** hours are therefore residua
|
||||
| Traditional Chinese | `zh-hant` | 2,016 (94.1%) | partial (same Hans/Hant face caveat) | yes |
|
||||
| Russian | `ru` | 2,043 (95.3%) | partial | yes |
|
||||
| Bulgarian | `bg` | 2,094 (97.7%) | partial | no |
|
||||
| Czech | `cs` | 135 (6.3%) | menus only | yes |
|
||||
| Czech | `cs` | 2,674 entries (every key of the other catalogs, the engine's sentences, weekdays and certificate fields) | partial | yes |
|
||||
| Telugu | `te` | 2,058 (96.0%) | partial (the release-pinned craft-fonts has no Telugu face yet) | no |
|
||||
| Hungarian | `hu` | 2,126 (99.2%) | partial | yes |
|
||||
| Ukrainian | `uk` | 2,142 (100%) | partial | yes |
|
||||
@@ -69,20 +74,28 @@ none has translated help. Vietnamese's **To `full`** hours are therefore residua
|
||||
| Slovenian | `sl` | 2,324 entries | partial | no |
|
||||
| Greek | `el` | 2,341 entries | partial | no |
|
||||
| Turkish | `tr` | 2,313 entries | partial | yes |
|
||||
| Lithuanian | `lt` | 2,585 entries | partial; community native-speaker review ([#1401](https://github.com/storytold/pdfcraft/pull/1401)) | no |
|
||||
| Lithuanian | `lt` | 2,674 (100% of current key union) | partial; community native-speaker review ([#1401](https://github.com/storytold/pdfcraft/pull/1401)) | no |
|
||||
| Finnish | `fi` | 2,674 entries | partial; AI-assisted, native proofreading pending | yes |
|
||||
| Albanian | `sq` | 2,344 entries | partial; not yet reviewed by a native speaker | no |
|
||||
| Catalan | `ca` | 2,592 entries | partial: no translated help, engine error details in English; native-speaker review by the contributor | no |
|
||||
| Romanian | `ro` | 2,673 entries (every bundled key) | partial; AI-assisted, not yet reviewed line by line by a native speaker | no |
|
||||
|
||||
**14 other languages** ship (22 catalogs plus English = **23** interface languages in Preferences).
|
||||
The entry counts without percentages were measured on 2026-10-12–13; they are not percentages of the older 2,143-key snapshot above. Their presence does not imply a detailed linguistic or runtime review.
|
||||
Acrobat languages PdfCraft lacks: Danish, Dutch, Finnish, Norwegian, Swedish, Hebrew. Vietnamese is shipped here but not by Acrobat.
|
||||
**14 other languages** ship (21 catalogs plus English, 22 interface languages in Preferences).
|
||||
The entry counts without percentages were measured on 2026-10-12 (Italian on 2026-10-14); they are not percentages of the older 2,143-key snapshot above. Their presence does not imply a detailed linguistic or runtime review.
|
||||
Acrobat languages PdfCraft lacks: Danish, Dutch, Finnish, Norwegian, Swedish, Hebrew.
|
||||
**15 other languages** ship (27 catalogs plus English = **28** interface languages in Preferences).
|
||||
The entry counts without percentages were measured on 2026-10-12–14; they are not percentages of the older 2,143-key snapshot above. Their presence does not imply a detailed linguistic or runtime review.
|
||||
Acrobat languages PdfCraft lacks: Danish, Dutch, Norwegian, Swedish, Hebrew. Vietnamese is shipped here but not by Acrobat.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-21 | minor | Brazilian Portuguese (`pt-br`) now covers all 2,674 distinct keys in the current catalog union; no help or engine/OS error-detail localization; twelve-language mean still rounds to ≈ 68% |
|
||||
| 2026-10-20 | minor | Spanish: the 143 keys the other catalogs had and `es.tsv` was missing; `es` now covers the whole 2,674-key union, like `lt` and `vi`. Restated Lithuanian against the current union (its 2,585 was measured on 2026-10-13) and said plainly in *How this was measured* that the union moves, so counts only compare within a date |
|
||||
| 2026-10-16 | minor | Czech: 2,674 entries after adding the keys the other catalogs had (the engine's sentences, weekday heads, certificate fields, shared buttons) and unifying "tag" as *tag* (not *značka*, which is a redaction mark) |
|
||||
| 2026-10-13 | minor | Vietnamese (`vi`) catalog: 2,591 entries (100% of current key union + `theme`/`Appearance`); twelve-language mean ≈ 68%; native-speaker community review; registered with `plural_none` |
|
||||
| 2026-10-14 | minor | Italian: 2,528 entries after adding the 201 keys the other catalogs had and the code looks up |
|
||||
| 2026-10-14 | minor | Added Finnish (2,674 entries, AI-assisted) |
|
||||
| 2026-10-12 | minor | Added Albanian (`sq`): catalog, date names, Preferences entry |
|
||||
| 2026-10-14 | minor | Added Catalan (`ca`, 2,592 entries, measured 2026-10-14); retained existing language assessments |
|
||||
| 2026-10-15 | minor | Romanian (`ro`) catalog: 2,673 entries (every bundled key); three plural forms (`plural_ro`); not one of the twelve key languages, so the mean is unchanged |
|
||||
| 2026-10-12 | minor | Added current counts for Kazakh, Polish, Slovenian, Greek, Turkish and Lithuanian; retained existing language assessments and the original percentage snapshot |
|
||||
| 2026-10-10 | major | Created. Catalog counts measured from `crates/ui-egui/src/i18n/*.tsv` against the 2,143-key union; Acrobat's localizations from its bundle's `.lproj` and Sequences folder names |
|
||||
|
||||
+20
-12
@@ -1,10 +1,10 @@
|
||||
# Interface language
|
||||
|
||||
Choose **Menu > Edit > Preferences…** (Command-comma on macOS, Ctrl-comma elsewhere) **> Interface language** and select **Auto**, **English**, **日本語**, **简体中文**, **繁體中文**, **Čeština**, **Português (Brasil)**, **Deutsch**, **Español**, **Français**, **Русский**, **Қазақша**, **Български**, **తెలుగు**, **Magyar**, **Українська**, **Italiano**, **العربية**, **Polski**, **Slovenščina**, **Ελληνικά**, **Türkçe**, **Lietuvių** or **Tiếng Việt**. The change applies immediately and persists between launches. Command ids, document contents and file names are unchanged.
|
||||
Choose **Menu > Edit > Preferences…** (Command-comma on macOS, Ctrl-comma elsewhere) **> Interface language** and select **Auto**, **English**, **日本語**, **简体中文**, **繁體中文**, **Čeština**, **Português (Brasil)**, **Deutsch**, **Español**, **Français**, **Русский**, **Қазақша**, **Български**, **తెలుగు**, **Magyar**, **Українська**, **Italiano**, **العربية**, **کوردیی ناوەندی**, **Polski**, **Slovenščina**, **Ελληνικά**, **Türkçe**, **Lietuvių**, **Tiếng Việt**, **Suomi**, **Shqip**, **Català** or **Română**. The change applies immediately and persists between launches. Command ids, document contents and file names are unchanged.
|
||||
|
||||
Displayed keyboard shortcuts use the same active interface language. For example, German shows `Strg+K` and `Strg+Umschalt+S` in the toolbar, menus, command palette, tooltips and Keyboard shortcuts dialog; macOS keeps its modifier symbols (`⌘`, `⇧`, `⌃`). Key names have their own `key` catalog context, so the Delete key can read `Entf` while the command remains `Löschen`. A missing key-name entry falls back to the English key name. Actual bindings and machine-facing command ids remain stable.
|
||||
|
||||
**Auto** (the default) follows the system language: `LC_ALL`, `LC_MESSAGES` or `LANG`, then the preferred-languages list on macOS. Any Portuguese locale (`pt_BR`, `pt_PT`) uses the Brazilian catalog, any French locale (`fr`, `fr_FR`, `fr_CA`, `fr_BE`) the French one, any German locale (`de`, `de_DE`, `de_AT`, `de_CH`) the German one, and Chinese locales for Taiwan, Hong Kong and Macau (`zh_TW`, `zh_HK`, `zh_MO`, `zh-Hant`) the Traditional Chinese one; other Chinese locales (`zh`, `zh_CN`, `zh_SG`, `zh-Hans`) the Simplified Chinese one. Telugu locales (`te`, `te_IN`) use the Telugu catalog, Bulgarian locales (`bg`, `bg_BG`) the Bulgarian one, and Hungarian locales (`hu`, `hu_HU`) the Hungarian one, and Ukrainian locales (`uk`, `uk_UA`) the Ukrainian one, and Italian locales (`it`, `it_IT`, `it_CH`) the Italian one, and Arabic locales (`ar`, `ar_MA`, `ar_EG`, `ar_SA`, …) the Arabic one, and Turkish locales (`tr`, `tr_TR`) the Turkish one, and Slovenian locales (`sl`, `sl_SI`) the Slovenian one, and Vietnamese locales (`vi`, `vi_VN`) the Vietnamese one. A system language without a catalog shows English. On Windows, **Auto** uses the Windows display languages, in preference order, when no supported locale is selected by those environment variables. Neutral `C`/`POSIX` locale values (including `C.UTF-8`) inherited from a launcher do not override the Windows display language; explicitly named supported locales such as `fr_FR.UTF-8` still do. The query asks Windows directly (`GetUserPreferredUILanguages`, through the `sys-locale` crate) without starting a process, and is cached for the process. If detection fails or the display language has no catalog, PdfCraft shows English.
|
||||
**Auto** (the default) follows the system language: `LC_ALL`, `LC_MESSAGES` or `LANG`, then the preferred-languages list on macOS. Any Portuguese locale (`pt_BR`, `pt_PT`) uses the Brazilian catalog, any French locale (`fr`, `fr_FR`, `fr_CA`, `fr_BE`) the French one, any German locale (`de`, `de_DE`, `de_AT`, `de_CH`) the German one, and Chinese locales for Taiwan, Hong Kong and Macau (`zh_TW`, `zh_HK`, `zh_MO`, `zh-Hant`) the Traditional Chinese one; other Chinese locales (`zh`, `zh_CN`, `zh_SG`, `zh-Hans`) the Simplified Chinese one. Telugu locales (`te`, `te_IN`) use the Telugu catalog, Bulgarian locales (`bg`, `bg_BG`) the Bulgarian one, and Hungarian locales (`hu`, `hu_HU`) the Hungarian one, and Ukrainian locales (`uk`, `uk_UA`) the Ukrainian one, and Italian locales (`it`, `it_IT`, `it_CH`) the Italian one, and Arabic locales (`ar`, `ar_MA`, `ar_EG`, `ar_SA`, …) the Arabic one, and Turkish locales (`tr`, `tr_TR`) the Turkish one, and Slovenian locales (`sl`, `sl_SI`) the Slovenian one, Vietnamese locales (`vi`, `vi_VN`) the Vietnamese one, Albanian locales (`sq`, `sq_AL`, `sq_XK`, …) the Albanian one, Catalan locales (`ca`, `ca_ES`, `ca_AD`, `ca_ES@valencia`, …) the Catalan one, and Romanian locales (`ro`, `ro_RO`, `ro-RO`, `ro_MD`) the Romanian one. A system language without a catalog shows English. On Windows, **Auto** uses the Windows display languages, in preference order, when no supported locale is selected by those environment variables. Neutral `C`/`POSIX` locale values (including `C.UTF-8`) inherited from a launcher do not override the Windows display language; explicitly named supported locales such as `fr_FR.UTF-8` still do. The query asks Windows directly (`GetUserPreferredUILanguages`, through the `sys-locale` crate) without starting a process, and is cached for the process. If detection fails or the display language has no catalog, PdfCraft shows English.
|
||||
|
||||
The control channel exposes the setting through `ui.set`:
|
||||
|
||||
@@ -12,11 +12,9 @@ The control channel exposes the setting through `ui.set`:
|
||||
{"method":"ui.set","params":{"key":"language","value":"ja"}}
|
||||
```
|
||||
|
||||
The value is `auto` or a language code (`en`, `ja`, `zh-hans`, `zh-hant`, `cs`, `pt-br`, `de`, `es`, `fr`, `ru`, `kk`, `bg`, `te`, `hu`, `uk`, `it`, `ar`, `pl`, `sl`, `el`, `tr`, `lt` or `vi`), in any case. `ui.state` reports `language` as written in the preferences (`auto`, `en`, `ja`, `zh-hans`, `zh-hant`, `cs`, `pt-br`, `de`, `es`, `fr`, `ru`, `kk`, `bg`, `te`, `hu`, `uk`, `it`, `ar`, `pl`, `sl`, `el`, `tr`, `lt` or `vi`). Unknown values return an error without changing the current setting. Preferences saved before this setting existed follow the system language.
|
||||
The value is `auto` or a language code (`en`, `ja`, `zh-hans`, `zh-hant`, `cs`, `pt-br`, `de`, `es`, `fr`, `ru`, `kk`, `bg`, `te`, `hu`, `uk`, `it`, `ar`, `ckb`, `pl`, `sl`, `el`, `tr`, `lt`, `vi`, `fi`, `sq`, `ca` or `ro`), in any case. `ui.state` reports `language` as written in the preferences (`auto`, `en`, `ja`, `zh-hans`, `zh-hant`, `cs`, `pt-br`, `de`, `es`, `fr`, `ru`, `kk`, `bg`, `te`, `hu`, `uk`, `it`, `ar`, `ckb`, `pl`, `sl`, `el`, `tr`, `lt`, `vi`, `fi`, `sq`, `ca` or `ro`). Unknown values return an error without changing the current setting. Preferences saved before this setting existed follow the system language.
|
||||
|
||||
Dialogs, panels, menus, notices and history labels go through the catalog (`tl!`). Most shipped catalogs (Japanese, Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Italian, Brazilian Portuguese, Arabic, Slovenian, Kazakh, Polish, Greek, Turkish, Lithuanian, Vietnamese and others) cover the current localizable surface (about 2,000–2,600 entries each); Czech still covers mainly the menus. Untranslated labels use English. Error details that come from the engine or the operating system are shown as they are, inside a translated frame ("操作「…」に失敗しました: …"). The command palette matches the translated label, the English label and the command id. Vertical Japanese PDF rendering is an existing viewer feature; this change does not add vertical text editing. Document contents, filenames, CLI/MCP/control protocol strings and external help stay outside the catalog. Per-language coverage, script support and what each language still needs are in [localization-parity.md](localization-parity.md).
|
||||
Dialogs, panels, menus, notices and history labels go through the catalog (`tl!`). Japanese, Traditional Chinese, Simplified Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Brazilian Portuguese and Arabic translate them (about 2,000–2,140 entries each), and Italian has 2,528 entries; Czech and Turkish cover the menus so far. Untranslated labels use English. Error details that come from the engine or the operating system are shown as they are, inside a translated frame ("操作「…」に失敗しました: …"). The command palette matches the translated label, the English label and the command id. Vertical Japanese PDF rendering is an existing viewer feature; this change does not add vertical text editing. Per-language coverage, script support and what each language still needs are in [localization-parity.md](localization-parity.md).
|
||||
Dialogs, panels, menus, notices and history labels go through the catalog (`tl!`). Japanese, Traditional Chinese, Simplified Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Brazilian Portuguese, Arabic and Slovenian translate them (about 2,000–2,190 entries each), and Italian has 2,528 entries; Czech covers the menus so far. Untranslated labels use English. Error details that come from the engine or the operating system are shown as they are, inside a translated frame ("操作「…」に失敗しました: …"). The command palette matches the translated label, the English label and the command id. Vertical Japanese PDF rendering is an existing viewer feature; this change does not add vertical text editing. Per-language coverage, script support and what each language still needs are in [localization-parity.md](localization-parity.md).
|
||||
Dialogs, panels, menus, notices and history labels go through the catalog (`tl!`). Most shipped catalogs (Japanese, Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Italian, Brazilian Portuguese, Arabic, Kurdish, Slovenian, Kazakh, Polish, Greek, Turkish, Lithuanian, Vietnamese, Romanian and others) cover the current localizable surface (about 2,000–2,700 entries each), and Czech (2,674 entries) covers the same surface. Untranslated labels use English. Error details that come from the engine or the operating system are shown as they are, inside a translated frame ("操作「…」に失敗しました: …"). The command palette matches the translated label, the English label and the command id. Vertical Japanese PDF rendering is an existing viewer feature; this change does not add vertical text editing. Document contents, filenames, CLI/MCP/control protocol strings and external help stay outside the catalog. Per-language coverage, script support and what each language still needs are in [localization-parity.md](localization-parity.md).
|
||||
|
||||
Whole sentences that the layers below word — what the accessibility checker found, what the PDF/A verifier reports, what a signature's details say, what is wrong with the pages to print, what an edit is called in the history — are translated too, because those layers hand the sentence over apart from the document's own words. See [Sentences the engine words](#sentences-the-engine-words).
|
||||
|
||||
@@ -24,15 +22,23 @@ The Ukrainian catalog has 2,047 entries, written from the meaning of the English
|
||||
|
||||
The Lithuanian catalog has 2,585 entries and three integer plural forms. Calendar headings use standalone month names; dates use genitive forms. Coverage tests check commands/tools, scanned literal and direct lookups, and source/context keys in the other bundled catalogs. Calendar, inspector and password-dialog UI regressions check dynamic labels and preserve document values. A native Lithuanian-speaking contributor has reviewed the translation.
|
||||
|
||||
The Vietnamese catalog has 2,591 entries and one plural form (`plural_none`). Preferences theme `Appearance` uses context `theme` → `Giao diện`; object/comment/signature appearance stays plain `Diện mạo`. Form fields use `Trường`; redaction apply wording states permanent removal. Calendar months are numeric (`Tháng 1`…`12` / `tháng 1`…`12`). Coverage tests require every current command, UI literal, bundled key and credit label. A native Vietnamese-speaking contributor has reviewed the translation. Status stays `partial`: no translated help, and engine/OS details stay English inside a translated frame.
|
||||
The Vietnamese catalog has 2,674 entries and one plural form (`plural_none`), covering the current catalog-key union. Preferences theme `Appearance` uses context `theme` → `Giao diện`; object/comment/signature appearance stays plain `Diện mạo`. Form fields use `Trường`; redaction apply wording states permanent removal. Calendar months are numeric (`Tháng 1`…`12` / `tháng 1`…`12`). Coverage tests require every current command, UI literal, bundled key and credit label. A native Vietnamese-speaking contributor has reviewed the translation. Status stays `partial`: no translated help, and engine/OS details stay English inside a translated frame.
|
||||
|
||||
The Finnish catalog has 2,674 entries: every key of the other bundled catalogs, written from the English labels in ordinary Finnish computing vocabulary and sentence case. Finnish has the English one/other plural rule, with the partitive singular after any number but 1 (`1 sivu`, `2 sivua`, `0 sivua`). Calendar headings use the nominative month (`Lokakuu 2026`); dates use the partitive (`14. lokakuuta 2026`), and Finnish is also a date language for month and weekday names. Any `fi-*` locale selects it; `sv-FI` keeps English until PdfCraft has a Swedish catalog. The bundled Latin faces cover `ä ö å š ž`. The translation is AI-assisted (Claude Code) and has not yet been proofread line by line by a native speaker.
|
||||
|
||||
The Catalan catalog has 2,592 entries, written from the meaning of the English labels in standard Catalan computing vocabulary. Commands use the second-person imperative (`Desa`, `Obre`, `Cancel·la`) and notices use impersonal or informal wording. Catalan has two plural forms like English (1 is singular; 0 and every other count take the plural: `1 pàgina`, `3 pàgines`). Every `ca-*` locale, including Valencian (`ca_ES@valencia`), uses this catalog. The interpunct of `l·l` is U+00B7, which the bundled Latin faces cover (tested in `tests/fonts.rs`). The date picker has Catalan month and weekday names; dates are day-first like French (`dddd d mmmm yyyy`), but after a day the month carries its own preposition, elided before a vowel (`7 de març`, `7 d'abril`, `8 d'octubre`), as Czech and Russian change theirs through `months_with_day`; the year takes `\de` from the pattern (`d mmmm \de yyyy`). A native Catalan speaker (the contributor) has reviewed the translation.
|
||||
|
||||
The Romanian catalog (`ro`, Română) has 2,673 entries and three plural forms (`plural_ro`, CLDR `ro`): `one` for 1, `few` for 0 and counts whose last two digits are 1–19 ("2 pagini", "101 pagini"), `other` for the rest, written with "de" ("20 de pagini"). Commands use the noun form common in Romanian software ("Salvare", "Deschidere…"); messages address the user formally. Redaction is "Anonimizare" ("redactare" means editing in Romanian), a watermark "Filigran". Calendar month names are lowercase inside dates (`{day} {month} {y}`). The bundled Inter faces cover ă, â, î, ș, ț (comma below). Coverage tests require every bundled key. Not yet reviewed by a second native speaker; status `partial`: no translated help, and engine/OS details stay English inside a translated frame.
|
||||
|
||||
Edit text reads Hebrew lines in typing order and writes them back in drawing order (`crates/edit/src/bidi.rs`); letters the page's own font lacks are drawn with the craft-fonts `Hebr` face (Noto Sans Hebrew) as Type 3 glyphs, and a build without one says so. Hebrew points (niqqud) can't be written yet in Edit text. Add text (#128) draws Hebrew with the same face through the shaped path Arabic and Thai use: right to left with numbers and Latin in place, points kept on their letter, and typing order for copy and search. The craft-fonts revision pinned for CI and releases has no `Hebr` face yet, so until one is added releases report that error instead of drawing the missing letters, and refuse Hebrew in Add text.
|
||||
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian, Italian, Turkish and Lithuanian need only the bundled Latin faces (tested in `tests/fonts.rs`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian, Italian and Slovenian need only the bundled Latin faces (tested in `tests/fonts.rs`). Slovenian has four plural forms: one (1, 101, 201…), two (2, 102…), few (3, 4, 103…) and other (everything else, including 0, 5–20 and 21+), so `@plural` entries list four forms (`1 stran`, `2 strani`, `3 strani`, `5 strani`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Until craft-fonts has an allowed `Hans` face, the desktop app draws a Chinese interface with a Chinese face already installed on the machine (Microsoft YaHei or JhengHei on Windows, PingFang, Hiragino Sans GB or STHeiti on macOS, WenQuanYi or Droid Sans Fallback on Linux; never Noto CJK or Source Han), placed before the Japanese faces so a line keeps one face (#826). The web build has no installed fonts to fall back on. Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian and Italian need only the bundled Latin faces (tested in `tests/fonts.rs`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian, Italian, Turkish, Lithuanian and Albanian need only the bundled Latin faces (tested in `tests/fonts.rs`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian, Italian, Slovenian and Albanian need only the bundled Latin faces (tested in `tests/fonts.rs`). Slovenian has four plural forms: one (1, 101, 201…), two (2, 102…), few (3, 4, 103…) and other (everything else, including 0, 5–20 and 21+), so `@plural` entries list four forms (`1 stran`, `2 strani`, `3 strani`, `5 strani`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
Japanese interface text uses BIZ UDPGothic from [craft-fonts](https://github.com/storytold/craft-fonts), an optional build input that every release includes (`CRAFT_FONTS_DIR`; see the README). A build made without it has no Japanese face, so Japanese labels show replacement boxes. Chinese is drawn with the same craft-fonts CJK faces (in Simplified Chinese the `Hans` faces come first, so a line never mixes faces with different baselines), so a character none of them has shows a replacement box (and every Chinese character does in a build without craft-fonts). Until craft-fonts has an allowed `Hans` face, the desktop app draws a Chinese interface with a Chinese face already installed on the machine (Microsoft YaHei or JhengHei on Windows, PingFang, Hiragino Sans GB or STHeiti on macOS, WenQuanYi or Droid Sans Fallback on Linux; never Noto CJK or Source Han), placed before the Japanese faces so a line keeps one face (#826). The web build has no installed fonts to fall back on. Russian, Bulgarian, Czech, Brazilian Portuguese, German, Spanish, French, Hungarian, Italian and Albanian need only the bundled Latin faces (tested in `tests/fonts.rs`). Hungarian uses the same one/other plural rule as English: 1 is singular, and every other count — including 0 — is the other form. After a numeral the noun stays singular (`1 oldal`, `2 oldal`). Telugu is drawn with a craft-fonts `Telu` face (Noto Sans Telugu, kept in the web build too), whose conjuncts egui shapes; a build without one shows Telugu labels as replacement boxes, and the release-pinned craft-fonts input has no Telugu face yet.
|
||||
|
||||
The Brazilian Portuguese catalog has 2,000 entries: the ~1,826-entry gist André Cardoso posted in [#288](https://github.com/storytold/pdfcraft/issues/288), the labels added since, and a review of the existing wording. Portuguese, like French, treats 0 and 1 as singular (`1 página`, `2 páginas`).
|
||||
The Brazilian Portuguese catalog has 2,674 entries and covers the current union of catalog keys. It began with the ~1,826-entry gist André Cardoso posted in [#288](https://github.com/storytold/pdfcraft/issues/288), with labels added since and the existing wording reviewed. Portuguese, like French, treats 0 and 1 as singular (`1 página`, `2 páginas`).
|
||||
|
||||
The Albanian catalog (`sq.tsv`, interface name **Shqip**) is written in Standard Albanian with the imperative for commands (`Ruaj`, `Hap`, `Fshi`). Albanian uses two plural forms like English: 1 is singular and every other count, including 0, is plural (`1 faqe`, `2 faqe`). Month and weekday names are lowercase (`mars`, `e shtunë`), and the letters `ë` and `ç` are covered by the bundled Latin faces. It has not been reviewed by a native Albanian speaker yet.
|
||||
|
||||
## Arabic and right-to-left text
|
||||
|
||||
@@ -49,11 +55,13 @@ What Arabic does not have yet:
|
||||
|
||||
These need bidirectional support in the text layout itself, not in the catalog.
|
||||
|
||||
Central Kurdish (Sorani, `ckb`) takes the same path: its catalog is written in logical order and `rtl: true` puts every entry into display order at load (`bidi::display_rtl`), so it behaves as Arabic does above and has the same four limits. Counts use the two [CLDR ckb forms](https://www.unicode.org/cldr/charts/48/supplemental/language_plural_rules.html#ckb) (`one`, `other`); Sorani keeps the noun singular after a numeral, so the two `@plural` forms usually read the same. Dates use the Kurdish names of the Gregorian months. The `Arab` face (Noto Sans Arabic) covers the Kurdish-only letters (`ێ ڵ ڕ ۆ ە ڤ ژ چ گ پ`).
|
||||
|
||||
Arabic glyphs come from the craft-fonts `Arab` face (Noto Sans Arabic, kept in the web build too). A build without craft-fonts shows Arabic as replacement boxes on the web; on desktop it falls back to one installed font (below). The craft-fonts revision pinned for CI and releases (`.github/workflows/`) has the Arabic face. That revision also holds Noto Sans CJK SC, which `crates/fonts/build.rs` never embeds: `AGENTS.md` §1.1 bars it, so Chinese still has no embedded face of its own (desktop builds fall back to an installed Chinese face, above).
|
||||
|
||||
File names and document titles in Arabic or Hebrew are drawn with a craft-fonts `Arab` face when the build input has one; on desktop, a character no embedded face has is drawn with one font already installed on the machine (`PDFCRAFT_SYSTEM_FONTS=0` turns this off). The tab strip, the recent-files list and Properties show such names in display order; other places (bookmarks, comments, search results) have the glyphs but may order mixed-direction text wrongly.
|
||||
|
||||
Japanese, Simplified Chinese, French, German and Brazilian Portuguese coverage tests, following PhotoCraft's complete-catalog approach, check every registered command, All tools label and `tl!("literal")` in the UI source. Simplified Chinese also checks direct `i18n::t` calls and multiline literals, plus the About tabs, contributor name modes, sort options, table headers and model columns. Generated history labels, contributor summaries and diagnostics are tested with user-supplied names and error details. Catalog coverage does not guarantee glyph coverage: the release-pinned craft-fonts input currently has no `Hans` face, and the web build embeds only BIZ UDPGothic Regular. Chinese font delivery remains separate work, as discussed in [#112](https://github.com/storytold/pdfcraft/pull/112) and [#140](https://github.com/storytold/pdfcraft/pull/140).
|
||||
Japanese, Simplified Chinese, French, German and Brazilian Portuguese coverage tests, following PhotoCraft's complete-catalog approach, check every registered command, All tools label and `tl!("literal")` in the UI source. Brazilian Portuguese also checks every key in the union of the bundled catalogs. Simplified Chinese additionally checks direct `i18n::t` calls and multiline literals, plus the About tabs, contributor name modes, sort options, table headers and model columns. Generated history labels, contributor summaries and diagnostics are tested with user-supplied names and error details. Catalog coverage does not guarantee glyph coverage: the release-pinned craft-fonts input currently has no `Hans` face, and the web build embeds only BIZ UDPGothic Regular. Chinese font delivery remains separate work, as discussed in [#112](https://github.com/storytold/pdfcraft/pull/112) and [#140](https://github.com/storytold/pdfcraft/pull/140).
|
||||
|
||||
German labels keep nouns capitalized, including tool names inserted into notices. The certificate viewer uses the `certificate` context for `Subject` (the certificate holder), while document properties keep the plain translation (the topic). Search hints reserve room for the shortcut, and Home cards limit their title and description to the available rows; hovering shows the full text when it is shortened.
|
||||
|
||||
|
||||
+4
-3
@@ -177,10 +177,10 @@ total matches the parity estimate.
|
||||
| M13 | Automation (MCP, Action Wizard, CLI) + AI providers | 60–120 | 45% | 25–45 | Done: MCP resources (document info, text, page images); headless tool table (123 tools incl. signing, optimizing, initial view, links, stamps, data exchange, comment review, forms authoring and scripts, redaction, sanitize, print, add content), opt-in MCP server over stdio, CLI `run`/`tools` (closed stdout pipes exit cleanly), UI control channel with drag. Missing: Action Wizard, AI providers<br>Done since: CLI run and MCP reject missing, empty, repeated and option-valued --root arguments before any tool/script execution or MCP initialization. A single-hyphen directory name remains valid; synthetic CLI regressions preserve a would-be overwritten file. `text_find` also caps the per-page match ranges it materializes at the remaining result limit plus one continuation match. CLI robustness scans visit each directory once through overlapping roots and symlink aliases. |
|
||||
| M12 | Accessibility, compare, measure, search, XFA | 200–380 | 30% | 90–160 | Done: new `a11y` crate with the Accessibility Checker (all 32 rules, report, Fix/Skip/Explain, options dialog and results panel, agent tools). Locatable figure, annotation and form findings highlight their page bounds.<br>Done since: 2D distance, perimeter and area measurements with persistent viewport calibration, snapping, live information and CSV export; a bounded text-only auto-tag proposal tool; text-only Apply writes marked content, paragraph tags and a parent tree, then opens the Tags panel for review. Missing: mixed-content and field autotag, heading/list/table/figure classification, Order/Content panels, Reading Order tool, compare, geospatial/3D measurement, search index, XFA<br>Done since: CLI info, text and render use dynamic XFA layout pages, with synthetic count/text/pixel and copy-permission regressions (#1645).<br>Reading colours: pending page backgrounds follow the configured colour (#2059). |
|
||||
| M13 | Automation (MCP, Action Wizard, CLI) + AI providers | 60–120 | 45% | 25–45 | Done: MCP resources (document info, text, page images); headless tool table (123 tools incl. signing, optimizing, initial view, links, stamps, data exchange, comment review, forms authoring and scripts, redaction, sanitize, print, add content), opt-in MCP server over stdio, CLI `run`/`tools` (closed stdout pipes exit cleanly), UI control channel with drag. Missing: Action Wizard, AI providers<br>Done since: CLI run and MCP reject missing, empty, repeated and option-valued --root arguments before any tool/script execution or MCP initialization. A single-hyphen directory name remains valid; synthetic CLI regressions preserve a would-be overwritten file. `text_find` also caps the per-page match ranges it materializes at the remaining result limit plus one continuation match. |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Brazilian Portuguese and Arabic (logical-order catalog put into display order; layout not yet mirrored); Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Lithuanian adds a 2,578-entry catalog and date names, reviewed by a native-speaking contributor. Validated candidate (macOS raster probe; Windows runtime unverified): the Windows policy changes only embedded JetBrains Mono; horizontal alpha-edge energy per ink improves 2.78%, 3.87% and 1.59% at 100%, 125% and 150%, and is down 0.79% at 200%. Inter is pixel-identical; layout hashes, glyph coverage and the 8 MiB atlas are unchanged. Timing and RSS ranges overlap, with no improvement claimed. Estimates unchanged. Candidate #2383 clamps GPU requests to supported limits while retaining the adapter texture extent; synthetic V3D/downlevel and Windows GPU-required tests pass, but Raspberry Pi startup is unverified. Estimates unchanged. Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean/Vietnamese, file-backed input and global memory budgets, performance budgets, keyboard-only operation Linux/Unix UI fallback fonts also use Fontconfig directories, including Nix store paths, with bounded discovery and the existing candidate allowlist; relative includes and digit-prefixed config filtering have isolated regressions. |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Brazilian Portuguese and Arabic (logical-order catalog put into display order; layout not yet mirrored); Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Lithuanian adds a 2,578-entry catalog and date names, reviewed by a native-speaking contributor. Validated candidate (macOS raster probe; Windows runtime unverified): the Windows policy changes only embedded JetBrains Mono; horizontal alpha-edge energy per ink improves 2.78%, 3.87% and 1.59% at 100%, 125% and 150%, and is down 0.79% at 200%. Inter is pixel-identical; layout hashes, glyph coverage and the 8 MiB atlas are unchanged. Timing and RSS ranges overlap, with no improvement claimed. Estimates unchanged. Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean/Vietnamese, file-backed input and global memory budgets, performance budgets, keyboard-only operation XDG desktops use the configuration base for preferences with non-overwriting migration and original-data preservation (#1395). |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian and Arabic (logical-order catalog put into display order; layout not yet mirrored); the 2,674-entry Brazilian Portuguese catalog covers the current key union; Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Lithuanian adds a 2,578-entry catalog and date names, reviewed by a native-speaking contributor. Validated candidate (macOS raster probe; Windows runtime unverified): the Windows policy changes only embedded JetBrains Mono; horizontal alpha-edge energy per ink improves 2.78%, 3.87% and 1.59% at 100%, 125% and 150%, and is down 0.79% at 200%. Inter is pixel-identical; layout hashes, glyph coverage and the 8 MiB atlas are unchanged. Timing and RSS ranges overlap, with no improvement claimed. Estimates unchanged. Candidate #2383 clamps GPU requests to supported limits while retaining the adapter texture extent; synthetic V3D/downlevel and Windows GPU-required tests pass, but Raspberry Pi startup is unverified. Estimates unchanged. Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean, file-backed input and global memory budgets, performance budgets, keyboard-only operation Linux/Unix UI fallback fonts also use Fontconfig directories, including Nix store paths, with bounded discovery and the existing candidate allowlist; relative includes and digit-prefixed config filtering have isolated regressions. |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian and Arabic (logical-order catalog put into display order; layout not yet mirrored); the 2,674-entry Brazilian Portuguese catalog covers the current key union; Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Lithuanian adds a 2,578-entry catalog and date names, reviewed by a native-speaking contributor. Validated candidate (macOS raster probe; Windows runtime unverified): the Windows policy changes only embedded JetBrains Mono; horizontal alpha-edge energy per ink improves 2.78%, 3.87% and 1.59% at 100%, 125% and 150%, and is down 0.79% at 200%. Inter is pixel-identical; layout hashes, glyph coverage and the 8 MiB atlas are unchanged. Timing and RSS ranges overlap, with no improvement claimed. Estimates unchanged. Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean, file-backed input and global memory budgets, performance budgets, keyboard-only operation XDG desktops use the configuration base for preferences with non-overwriting migration and original-data preservation (#1395). |
|
||||
| M13 | Automation (MCP, Action Wizard, CLI) + AI providers | 60–120 | 45% | 25–45 | Done: MCP resources (document info, text, page images); headless tool table (123 tools incl. signing, optimizing, initial view, links, stamps, data exchange, comment review, forms authoring and scripts, redaction, sanitize, print, add content), opt-in MCP server over stdio, CLI `run`/`tools` (closed stdout pipes exit cleanly), UI control channel with drag. Missing: Action Wizard, AI providers |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian, Brazilian Portuguese and Arabic (logical-order catalog put into display order; layout not yet mirrored); Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Traditional Chinese accessibility statuses, rule semantics and Taiwan form/table terms have catalog regressions. Long main-menu lists scroll in short windows (#3373). Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean/Vietnamese, file-backed input and global memory budgets, performance budgets, keyboard-only operation |
|
||||
| M14 | 1.0 polish: performance, localization, installers | 120–250 | 15% | 80–150 | Done: PhotoCraft's translation system (`i18n/`: TSV catalogs, `tl!`, command-id and plural entries, system-language detection, strict catalog tests); every dialog, panel and notice goes through `tl!`. Catalogs of ≈ 2,000–2,140 entries for Japanese, Simplified and Traditional Chinese, Russian, Bulgarian, German, Spanish, French, Telugu, Hungarian, Ukrainian and Arabic (logical-order catalog put into display order; layout not yet mirrored); the 2,674-entry Brazilian Portuguese catalog covers the current key union; Czech covers the menus. Italian has 2,528 entries: every key of the other catalogs that the code looks up. Signed and notarized macOS builds, signed Windows installers (x64, x86, ARM64), AppImage, deb, rpm, Flatpak and FreeBSD packages. #307 (bounded large-PDF memory): shared resource indexes and parser metadata, lazy inspection, bounded caches; a 9,156-page file inspects in ≈ 1.8 s at ≈ 500 MiB instead of exceeding 10 GiB. Edits let go of the previous working file before writing the next (a 1 GiB file peaks at two copies while editing, not three; gap 13). Shortcut display uses localized modifier/key names across menus, toolbar, palette, Help and tooltips (#496). Traditional Chinese accessibility statuses, rule semantics and Taiwan form/table terms have catalog regressions. Long main-menu lists scroll in short windows (#3373). Missing: a right-to-left layout, a Chinese UI face in releases, Hindi/Indonesian/Korean, file-backed input and global memory budgets, performance budgets, keyboard-only operation |
|
||||
| | **Total** | **2,085–3,840** | **≈ 49% ready** | **≈ 770–1,400** | Area view of the same work: [target-app-parity.md](target-app-parity.md#by-feature-area) |
|
||||
|
||||
## Upcoming milestones, ranked
|
||||
@@ -268,6 +268,7 @@ M2 (renderer), M7 (content editing), M10 (OCR and Office), M11 (Preflight and st
|
||||
| 2026-10-15 | minor | M2: three vendored hayro-interpret patches (31–33): sampled functions index a flat table (`bug1721218` 1.34 → 0.49 s), one JPEG or Flate decode serves every size an image is drawn at (35–40% less render work zooming a scan), patch meshes copy their vertices less (10–16% on mesh-gradient pages); pixel for pixel the same over the pdf.js corpus. Estimates unchanged. |
|
||||
| 2026-10-13 | minor | M2/M6: images with at most 16 bits of samples a pixel (8-bit Separation/DeviceN, 1-4-bit gray or indexed) convert once per pixel value (hayro-interpret patch 28), so spot-colour form backgrounds draw in milliseconds instead of seconds; widgets without `/P` are placed in one pass; the Fields panel no longer searches the form per row and draws only the rows in view. Estimates unchanged. |
|
||||
| 2026-10-13 | minor | M3: native-open admission preserves modal/picker ownership; regressions cover queued replies and one-shot picker wakes. Estimates unchanged |
|
||||
| 2026-10-14 | minor | M14: Catalan interface and date language (2,592-entry catalog, coverage tests). Estimates unchanged |
|
||||
| 2026-10-12 | minor | M13: CLI check directory identity, with overlap and symlink regressions; estimates unchanged |
|
||||
| 2026-10-12 | minor | M4: shared Type 3 glyph resources survive extraction, with save/reopen and independent raster regressions; estimates unchanged |
|
||||
| 2026-10-12 | minor | M2: packed TIFF-predictor RGB row boundaries, with decoding and page-render regressions; estimates unchanged |
|
||||
|
||||
@@ -5317,7 +5317,7 @@ status = "shipped"
|
||||
commands = ["sign.fill.date"]
|
||||
tools = ["fill_sign_add", "fill_sign_date_format"]
|
||||
evidence = ["crates/ui-egui/tests/fill_sign.rs::text_marks_and_date", "crates/automation/tests/automation.rs::fill_and_sign_through_tools", "crates/ui-egui/tests/date_format.rs::fill_and_sign_dates_follow_the_date_format_preference_and_it_is_remembered", "crates/engine/src/dates.rs::presets_write_the_day_in_their_own_order", "crates/engine/src/dates.rs::names_follow_the_date_language", "crates/ui-egui/tests/date_format.rs::month_names_follow_the_date_language_or_else_the_interface_language", "crates/ui-egui/tests/date_format.rs::a_date_the_pdf_cannot_hold_is_refused_with_a_warning_first"]
|
||||
notes = "local date in Preferences ▸ Date format (default m/d/yyyy; 12 presets or any pattern in Acrobat date letters with \\ escapes, checked and previewed as typed, remembered; only whole date codes accepted; month and weekday names in the interface languages, Czech months in the genitive after a day, following the interface language unless one is picked; fill_sign_add takes a one-off format and language). Beyond Acrobat: its Fill & Sign has no format setting (only Acrobat Sign accounts do). Missing: Fill & Sign text is Helvetica/WinAnsi, so a date with letters outside Western European (Czech ř, Japanese, Chinese names) is refused with a warning instead of being saved as ?; the OS locale's format isn't offered as a preset; names in languages without an interface translation"
|
||||
notes = "local date in Preferences ▸ Date format (default m/d/yyyy; 14 presets, year-first slash forms included, or any pattern in Acrobat date letters with \\ escapes, checked and previewed as typed, remembered; only whole date codes accepted; month and weekday names in the interface languages, Czech months in the genitive after a day, following the interface language unless one is picked; fill_sign_add takes a one-off format and language). Beyond Acrobat: its Fill & Sign has no format setting (only Acrobat Sign accounts do). Missing: Fill & Sign text is Helvetica/WinAnsi, so a date with letters outside Western European (Czech ř, Japanese, Chinese names) is refused with a warning instead of being saved as ?; the OS locale's format isn't offered as a preset; names in languages without an interface translation"
|
||||
|
||||
[[feature]]
|
||||
id = "form.fill-sign-signature"
|
||||
@@ -9961,7 +9961,7 @@ status = "partial"
|
||||
commands = ["app.preferences"]
|
||||
tools = []
|
||||
evidence = ["crates/ui-egui/src/commands.rs::localized_shortcut_labels_follow_language_and_platform", "crates/ui-egui/src/i18n/mod.rs::keyboard_key_names_have_a_separate_context_and_english_fallback", "crates/ui-egui/tests/commands.rs::localized_shortcuts_update_immediately_and_keep_command_ids_and_key_bindings", "crates/ui-egui/src/i18n/mod.rs::windows_display_language_resolves_chinese_scripts", "crates/ui-egui/src/i18n/mod.rs::neutral_locale_does_not_override_display_language", "crates/ui-egui/src/i18n/mod.rs::windows_display_language_query_returns_a_locale_tag", "crates/ui-egui/src/i18n/mod.rs::language_persists_and_invalid_input_keeps_current_language", "crates/ui-egui/src/i18n/mod.rs::bundled_catalogs_are_consistent", "crates/ui-egui/src/i18n/mod.rs::arabic_is_registered_and_persists", "crates/ui-egui/src/i18n/mod.rs::arabic_lookups_are_in_display_order", "crates/ui-egui/src/i18n/mod.rs::arabic_plurals_follow_the_six_cldr_forms", "crates/ui-egui/src/i18n/mod.rs::arabic_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::arabic_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::arabic_labels_have_glyphs", "crates/ui-egui/src/bidi.rs::rtl_labels_keep_placeholders_whole", "crates/ui-egui/src/i18n/mod.rs::japanese_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::simplified_chinese_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::simplified_chinese_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::simplified_chinese_history_and_diagnostics_preserve_user_values", "crates/ui-egui/tests/control.rs::simplified_chinese_signature_prompts_and_errors_keep_document_state", "crates/ui-egui/tests/control.rs::language_switch_preserves_document_and_command_ids", "crates/ui-egui/tests/control.rs::japanese_controls_and_search_keep_command_ids", "crates/ui-egui/tests/control.rs::japanese_dialogs_errors_and_custom_action_names", "crates/ui-egui/src/i18n/mod.rs::french_is_registered", "crates/ui-egui/src/i18n/mod.rs::french_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::french_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::french_history_and_diagnostics_preserve_user_values", "crates/ui-egui/src/i18n/mod.rs::german_certificate_subject_has_a_distinct_context", "crates/ui-egui/src/widgets.rs::search_placeholder_never_overlaps_the_shortcut", "crates/ui-egui/src/home.rs::translated_card_description_leaves_room_for_the_action", "crates/ui-egui/tests/control.rs::german_preferences_and_search_keep_command_ids", "crates/ui-egui/src/i18n/mod.rs::telugu_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::telugu_labels_have_glyphs", "crates/ui-egui/src/i18n/mod.rs::hungarian_is_registered", "crates/ui-egui/src/i18n/mod.rs::hungarian_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::hungarian_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::hungarian_history_and_diagnostics_preserve_user_values", "crates/ui-egui/src/i18n/mod.rs::ukrainian_is_registered_and_persists", "crates/ui-egui/src/i18n/mod.rs::ukrainian_integer_plurals_cover_teens_and_large_counts", "crates/ui-egui/src/i18n/mod.rs::ukrainian_calendar_uses_month_case_for_dates", "crates/ui-egui/src/i18n/mod.rs::ukrainian_catalog_does_not_leave_english_ui_text", "crates/ui-egui/src/i18n/mod.rs::ukrainian_covers_commands_and_catalogue", "crates/ui-egui/src/i18n/mod.rs::ukrainian_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::ukrainian_history_and_diagnostics_preserve_user_values", "crates/ui-egui/src/i18n/mod.rs::spanish_covers_ui_literals", "crates/ui-egui/src/i18n/mod.rs::spanish_covers_what_the_engine_says", "crates/ui-egui/src/i18n/mod.rs::spanish_keeps_the_holes_in_what_the_engine_says", "crates/print/src/tests.rs::wordings_are_said"]
|
||||
notes = "Shortcut modifiers and key names use a dedicated catalog context across toolbar, menus, palette, Help and tooltips, with English fallback and macOS symbols preserved. Preferences switches Auto (system language)/English/Japanese/Simplified Chinese/Traditional Chinese/Czech/Brazilian Portuguese/German/Spanish/French/Telugu/Hungarian/Ukrainian/Italian/Arabic and persists; ui.set language auto|en|ja|zh-hans|zh-hant|cs|pt-br|de|es|fr|te|hu|uk|it|ar and ui.state expose it. TSV catalogs per language (same system as PhotoCraft); every dialog, panel and notice goes through tl!. Japanese, Traditional Chinese, Simplified Chinese, German, Spanish, French and Hungarian cover commands, dialogs, panels, shortcuts and history labels; Czech and Brazilian Portuguese the menus. French locales (fr, fr_FR, fr_CA, fr_BE) select the French catalog, German locales (de, de_DE, de_AT, de_CH) the German one, Hungarian locales (hu, hu_HU) the Hungarian one. German search hints reserve shortcut space, Home cards bound translated text, certificate Subject has its own context, and inserted tool names keep their capitalization. The sentences the layers below word for themselves (accessibility findings and the saved report, PDF/A problems, signature details, page-range mistakes, edit labels) are handed over apart from the document's own values and go through the catalog too, through said(&i18n::words); Spanish and Italian translate them and the other catalogs fall back to English. OS error details, and faults rather than mistakes, stay as they are. Auto detects the Windows display language after explicitly named supported locale overrides; neutral C/POSIX launcher locales are skipped on Windows, with Chinese script/region mapping and English fallback. Arabic (ar and every ar-* locale) covers commands, dialogs and panels with the six CLDR plural forms; its labels are put into display order when the catalog loads, because egui joins Arabic letters but lays words out left to right. Missing: a right-to-left layout (Arabic labels sit in the left-to-right layout, a wrapped Arabic paragraph breaks at the wrong end, and text typed into a field is not reordered), Czech and Brazilian Portuguese dialogs, Chinese and Telugu font delivery in releases (the pinned craft-fonts revision has an Arabic face; its Noto Sans CJK SC is never embedded, AGENTS.md §1.1), the engine's sentences in the other catalogs, a full localization audit."
|
||||
notes = "Shortcut modifiers and key names use a dedicated catalog context across toolbar, menus, palette, Help and tooltips, with English fallback and macOS symbols preserved. Preferences switches Auto (system language)/English/Japanese/Simplified Chinese/Traditional Chinese/Czech/Brazilian Portuguese/German/Spanish/French/Telugu/Hungarian/Ukrainian/Italian/Arabic and persists; ui.set language auto|en|ja|zh-hans|zh-hant|cs|pt-br|de|es|fr|te|hu|uk|it|ar and ui.state expose it. TSV catalogs per language (same system as PhotoCraft); every dialog, panel and notice goes through tl!. Japanese, Traditional Chinese, Simplified Chinese, German, Spanish, French and Hungarian cover commands, dialogs, panels, shortcuts and history labels; Brazilian Portuguese covers the current union of catalog keys, including signature and accessibility messages; Czech remains limited to menus. French locales (fr, fr_FR, fr_CA, fr_BE) select the French catalog, German locales (de, de_DE, de_AT, de_CH) the German one, Hungarian locales (hu, hu_HU) the Hungarian one. German search hints reserve shortcut space, Home cards bound translated text, certificate Subject has its own context, and inserted tool names keep their capitalization. The sentences the layers below word for themselves (accessibility findings and the saved report, PDF/A problems, signature details, page-range mistakes, edit labels) are handed over apart from the document's own values and go through the catalog too, through said(&i18n::words); Spanish, Italian and Brazilian Portuguese translate them, Polish the signature details and the changes after signing; strings absent from other catalogs fall back to English. OS error details, and faults rather than mistakes, stay as they are. Auto detects the Windows display language after explicitly named supported locale overrides; neutral C/POSIX launcher locales are skipped on Windows, with Chinese script/region mapping and English fallback. Arabic (ar and every ar-* locale) covers commands, dialogs and panels with the six CLDR plural forms; its labels are put into display order when the catalog loads, because egui joins Arabic letters but lays words out left to right. Missing: a right-to-left layout (Arabic labels sit in the left-to-right layout, a wrapped Arabic paragraph breaks at the wrong end, and text typed into a field is not reordered), Czech dialogs, Chinese and Telugu font delivery in releases (the pinned craft-fonts revision has an Arabic face; its Noto Sans CJK SC is never embedded, AGENTS.md §1.1), the engine's sentences in the other catalogs, a full localization audit."
|
||||
|
||||
[[feature]]
|
||||
id = "misc.prefs-reading"
|
||||
|
||||
Reference in New Issue
Block a user