From a8940f00031a3079943d69ee55c04e30095541cb Mon Sep 17 00:00:00 2001 From: Earl Co Date: Mon, 12 Oct 2026 03:20:13 +0200 Subject: [PATCH] M10: Create separate PDFs from multiple files (#1183) * M10: Create separate PDFs from multiple files * Separate PDFs: translatable notices "Left out: {names}" and the per-file reasons (already a PDF, no unused output name, no output folder was chosen) go through tl!; the browser's download notice is a plural ("Downloaded {n} PDF" / "Downloaded {n} PDFs") via trn. Rows in all 20 catalogs, with each language's plural forms; catalog hashes refreshed. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Brandon Thomas Co-authored-by: Claude Opus 5.5 --- ATTRIBUTION.toml | 40 ++++++------ crates/engine/src/catalog.rs | 1 + crates/engine/src/commands.rs | 1 + crates/ui-egui/src/commands.rs | 1 + crates/ui-egui/src/create_multiple_ui.rs | 81 ++++++++++++++++++++++-- crates/ui-egui/src/files.rs | 32 +++++++++- crates/ui-egui/src/i18n/ar.tsv | 7 ++ crates/ui-egui/src/i18n/bg.tsv | 7 ++ crates/ui-egui/src/i18n/cs.tsv | 7 ++ crates/ui-egui/src/i18n/de.tsv | 7 ++ crates/ui-egui/src/i18n/el.tsv | 7 ++ crates/ui-egui/src/i18n/es.tsv | 7 ++ crates/ui-egui/src/i18n/fr.tsv | 7 ++ crates/ui-egui/src/i18n/hu.tsv | 7 ++ crates/ui-egui/src/i18n/it.tsv | 7 ++ crates/ui-egui/src/i18n/ja.tsv | 7 ++ crates/ui-egui/src/i18n/kk.tsv | 7 ++ crates/ui-egui/src/i18n/pl.tsv | 7 ++ crates/ui-egui/src/i18n/pt-br.tsv | 7 ++ crates/ui-egui/src/i18n/ru.tsv | 7 ++ crates/ui-egui/src/i18n/sl.tsv | 7 ++ crates/ui-egui/src/i18n/te.tsv | 7 ++ crates/ui-egui/src/i18n/tr.tsv | 7 ++ crates/ui-egui/src/i18n/uk.tsv | 7 ++ crates/ui-egui/src/i18n/zh-hans.tsv | 7 ++ crates/ui-egui/src/i18n/zh-hant.tsv | 7 ++ crates/ui-egui/tests/create.rs | 47 ++++++++++++++ docs/file-format-parity.md | 2 +- 28 files changed, 319 insertions(+), 26 deletions(-) diff --git a/ATTRIBUTION.toml b/ATTRIBUTION.toml index 9365c22f..8ba00ab3 100644 --- a/ATTRIBUTION.toml +++ b/ATTRIBUTION.toml @@ -7,7 +7,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Greek UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "c11d1ab23626a150dcc2c86ccc8da178b14b05005362691c9534c024bd33be33" +sha256 = "23b1e78d022b8d61e529010170f239d3231aa7c8356aca053ed1daa0c6c7e017" # ATTRIBUTION.toml: one entry per asset (AGENTS.md §1). The source of truth for provenance and licences. # ATTRIBUTION.md is generated from this file: `cargo xtask assets --write`. Checked by `cargo xtask assets` (part of `xtask ci`). @@ -30,7 +30,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Simplified Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "1fc90de4950f1ec603a92490739e7774ce460b2519c2143847c462b73a1a3192" +sha256 = "74e0593b46d5a230364bbf5d11d9b3affc5825dc72c20237e3ee99f6af7b423f" [[asset]] path = "crates/ui-egui/src/i18n/zh-hant.tsv" @@ -41,7 +41,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Traditional Chinese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "ec59f43208ce08488a9918a5fe78debf1f07e0f50d231a1c875f013c8f706166" +sha256 = "22b10da7793475fad662e27f6e62eea4f1eb1aa678ff65f7914943b1a7e88b88" [[asset]] path = "crates/ui-egui/src/i18n/cs.tsv" @@ -52,7 +52,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Czech UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "0a83d58709ea31d97accf2be4ac2e588b566a6aa8e9b3ea29b7d45b5c64bb020" +sha256 = "2281deb36a391814012b624cff87c3cbd14f13592a437f84ddf6a5046f2ef6cf" [[asset]] path = "crates/ui-egui/src/i18n/pt-br.tsv" @@ -63,7 +63,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Brazilian Portuguese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "67249c2032d2420e90e84c16194a7f893b57222b600a8ca448bb5dd8425553b7" +sha256 = "c371535d71a4d6b0f8984b74fc75ea81f1b1ae4683ed5f308ef73b1087c3c738" [[asset]] path = "crates/ui-egui/src/i18n/es.tsv" @@ -74,7 +74,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Spanish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "681e0f1ae2e612173b2a1bc3ead5f5eb61f5ac006a961c703e427c258f6bbde1" +sha256 = "f1cc6dd86be23dea0cd07b1984c4d83991b80b5d8ece9296239a64cc1eddf58b" [[asset]] path = "crates/ui-egui/src/i18n/fr.tsv" @@ -85,7 +85,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "French UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "11f3b405f5dd21e25d45ee1543c306bff58104f37ed7ef26a4e13f453ce25798" +sha256 = "27cc77eac03ecf3b75fcd24b458108fa6ebf499c8f83948a434e2b2af0318d1a" [[asset]] path = "crates/ui-egui/src/i18n/de.tsv" @@ -96,7 +96,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "German UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "29582e00b1dac3a5589d23d4aab7a7ebf53ae71ea33cf2c94665ffd89d0b752e" +sha256 = "80e406040f5a1dcc50ba9c6eb9f46da034aebbc86e41fd358a969cdcb9435f35" [[asset]] path = "crates/ui-egui/src/i18n/te.tsv" @@ -107,7 +107,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Telugu UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "d67f16d97586b0c3f6026150ef9590ba0f93d039159d93bcbc6185bb13e1021b" +sha256 = "0e45cd5fd8128696a5c8dcb00925e9e29f14d4ad7f2c8df8932ed2f708a8f67c" [[asset]] path = "crates/ui-egui/src/i18n/it.tsv" @@ -118,7 +118,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Italian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "279aaa24b7a6229da6b1d97b4f9d3cb213862996e32f8230ccba982252aeca64" +sha256 = "4a02931d430cc289627af28f2621e057216762c9522131c91900e455597ba749" [[asset]] path = "crates/ui-egui/src/i18n/pl.tsv" @@ -129,7 +129,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Polish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "1bda6860cd2bd330369746edc97737ebbfe7dc859cde478cc1e9276e852323a9" +sha256 = "f25b2a2752ba525c95fd14ee0e0914c6a1021a3516ea4d5d5ead727467b349b6" [[asset]] path = "crates/ui-egui/src/i18n/ru.tsv" @@ -140,7 +140,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Russian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "55671fb2a1717bac56789c8ab31f8412efb119a61c6d502eb0319ead7f5e9f98" +sha256 = "e35884fa177766b33fa818662c22ceac23e90cfb0b8c8c0f3e45bdee91635078" [[asset]] path = "crates/ui-egui/src/i18n/hu.tsv" @@ -151,7 +151,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Hungarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "408cf4819e263d141c00ea120b2b49e4c4f144226f66f10ac5b8500e963547d1" +sha256 = "544bfb5eeab67471532e888521fedff27abdb43aead1d083b136a287ef0ce668" [[asset]] path = "crates/ui-egui/src/i18n/bg.tsv" @@ -162,7 +162,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Bulgarian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "8024a9e9b14a44d2b75d0a5d1aec21a3bea6662c204769d2dc712c3da484202c" +sha256 = "7181163d2bc168a7a8db0be37c9aa097f562a4f4982ee9026c03811aaf686a84" [[asset]] path = "crates/ui-egui/src/i18n/kk.tsv" @@ -173,7 +173,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Kazakh UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "44e5490cc1a04190c24be19e3f8f84f8fa2a540fa411b757435109e197e20dfd" +sha256 = "47b1c5ac4fbae4a1bbcc49ec716762aa3510b64001dd6474682599fd801570d7" [[asset]] path = "crates/ui-egui/src/i18n/ja.tsv" @@ -184,7 +184,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Japanese UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "5f6f003fda06389782371c65fb24290b9c88cede3b67fa6f4700a3c5996eac76" +sha256 = "17fc33cbec7335295ced83f0584baa3ec057cb318ffc812c0d5c4abe08b8dfbd" [[asset]] path = "crates/ui-egui/src/i18n/uk.tsv" @@ -195,7 +195,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Ukrainian UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "17ca14b6eed104f60e0e8eb2b4cf5e0fb26d73c602707c87db4ce755eaba309c" +sha256 = "289dd18eb4f1ecfba4ec500b2ecfdb2fec4645b5f4452b2d056e39ec00508499" [[asset]] path = "crates/ui-egui/src/i18n/ar.tsv" @@ -206,7 +206,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Arabic UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "7efbefe9cbaa0f0a92f94c34d6435f214556068612c61cfafe79e80c85302356" +sha256 = "d95fca18a279910e9a3b52edd99711510afa94bdc41604a10c662fcb2272e851" [[asset]] path = "crates/ui-egui/src/i18n/tr.tsv" @@ -217,7 +217,7 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Turkish UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "e24109d16048d1867d61509e12ebd9105c1d1530bdca5746844707d7f5e29348" +sha256 = "564f9cbc4e7cb9e8e9bc7263a8951274bcae6be572444fcecb4577441bfd4f24" [[asset]] path = "assets/icons/accessibility.svg" @@ -3339,4 +3339,4 @@ licence = "MIT OR Apache-2.0" licence_file = "LICENSE-MIT" kind = "translation" usage = "Slovene UI strings, compiled in by crates/ui-egui/src/i18n/mod.rs" -sha256 = "85dec9ece83ff99732854d00a5361133ec6ff98afad8d2563d3e2eabd970f042" +sha256 = "b536e21ac698b4b581c5078d4278c7fb81cce3215d32cb370d3dedfa09837fff" diff --git a/crates/engine/src/catalog.rs b/crates/engine/src/catalog.rs index 5f2c52bc..3378e3d5 100644 --- a/crates/engine/src/catalog.rs +++ b/crates/engine/src/catalog.rs @@ -150,6 +150,7 @@ pub static TOOL_GROUPS: &[ToolGroup] = &[ items: &[ item("Single file", "file-input", "create.file", Ready), item("Multiple files", "files", "create.multiple", Ready), + item("Separate PDFs", "files", "create.multiple_separate", Ready), item("Images", "image", "create.images", Ready), item("Clipboard", "copy-plus", "create.clipboard", Ready), item("Blank page", "file-plus-2", "create.blank", Ready), diff --git a/crates/engine/src/commands.rs b/crates/engine/src/commands.rs index 9760ee42..aee26adb 100644 --- a/crates/engine/src/commands.rs +++ b/crates/engine/src/commands.rs @@ -179,6 +179,7 @@ pub const COMMANDS: &[CommandSpec] = &[ c("page.paste", "Paste pages", None, None, Assembly, "clipboard-paste"), c("create.file", "Create PDF from file…", FILE, None, Nothing, "file-input"), c("create.multiple", "Create PDF from multiple files…", FILE, None, Nothing, "files"), + c("create.multiple_separate", "Create separate PDFs…", FILE, None, Nothing, "files"), c("create.images", "Create PDF from images…", FILE, None, Nothing, "image"), c("create.clipboard", "Create PDF from clipboard", FILE, None, Nothing, "copy-plus"), c("page.combine", "Combine files…", FILE, None, Nothing, "files"), diff --git a/crates/ui-egui/src/commands.rs b/crates/ui-egui/src/commands.rs index 4ccca99e..30053142 100644 --- a/crates/ui-egui/src/commands.rs +++ b/crates/ui-egui/src/commands.rs @@ -581,6 +581,7 @@ impl PdfCraftApp { "create.blank" => self.create_blank(), "create.file" => self.open_dialog(), "create.multiple" => self.create_multiple_dialog(), + "create.multiple_separate" => self.create_multiple_separate_dialog(), "create.images" => self.create_from_images_dialog(), "create.clipboard" => self.create_from_clipboard(), "optimize.reduce" => self.reduce_file_size(), diff --git a/crates/ui-egui/src/create_multiple_ui.rs b/crates/ui-egui/src/create_multiple_ui.rs index 19b15c5e..a89f5d59 100644 --- a/crates/ui-egui/src/create_multiple_ui.rs +++ b/crates/ui-egui/src/create_multiple_ui.rs @@ -1,10 +1,11 @@ -//! Create a PDF ▸ Multiple files: the picked PDFs, images and text files become one new, -//! unsaved document, shown in the page grid: remove pages, insert more files between pages, -//! reorder, then save what the grid shows. +//! Create a PDF from multiple files. Combine opens one unsaved document in the page grid; +//! Separate writes one PDF per convertible source without opening tabs. +use std::collections::HashSet; +use std::path::PathBuf; use std::sync::Arc; -use pdfcraft_engine::EditError; +use pdfcraft_engine::{EditError, SourceKind}; use crate::PdfCraftApp; @@ -25,6 +26,78 @@ impl From for Stop { } impl PdfCraftApp { + /// Convert each selected non-PDF file into its own PDF. Existing outputs and duplicate input + /// names receive numbered names, so a batch never silently replaces an earlier file. + pub(crate) fn stage_create_separate(&mut self, files: I, dir: Option) + where + I: IntoIterator), (String, String)>>, + { + let mut used = HashSet::new(); + let mut made = 0usize; + let mut refused = Vec::new(); + for file in files { + let (name, bytes) = match file { + Ok(file) => file, + Err((name, error)) => { + refused.push(format!("{name} ({error})")); + continue; + } + }; + let (kind, pdf) = match self.session.convert_to_pdf(&name, &Arc::new(bytes)) { + Ok(converted) => converted, + Err(error) => { + refused.push(format!("{name} ({error})")); + continue; + } + }; + if kind == SourceKind::Pdf { + refused.push(format!("{name} ({})", tl!("already a PDF"))); + continue; + } + let base = crate::files::file_stem_from_user(stem(&name)); + let base = if base.is_empty() { "document" } else { &base }; + let mut output = None; + for number in 1..10_000 { + let filename = if number == 1 { format!("{base}.pdf") } else { format!("{base} ({number}).pdf") }; + let candidate = dir.as_ref().map(|d| d.join(&filename)); + if !used.contains(&filename.to_lowercase()) && !candidate.as_ref().is_some_and(|path| path.exists()) { + used.insert(filename.to_lowercase()); + output = Some((filename, candidate)); + break; + } + } + let Some((filename, target)) = output else { + refused.push(format!("{name} ({})", tl!("no unused output name"))); + continue; + }; + #[cfg(not(target_arch = "wasm32"))] + let result = match target { + Some(path) => crate::editing::write_atomically(&path.to_string_lossy(), &pdf).map_err(|e| e.to_string()), + None => Err(tl!("no output folder was chosen").to_string()), + }; + #[cfg(target_arch = "wasm32")] + let result = { + let _ = target; + crate::editing::download(&filename, &pdf) + }; + match result { + Ok(()) => made += 1, + Err(error) => refused.push(format!("{filename} ({error})")), + } + } + if made > 0 { + #[cfg(not(target_arch = "wasm32"))] + if let Some(dir) = &dir { + self.notify_fmt("Wrote {n} files to {dir}", &[("n", &made.to_string()), ("dir", &dir.display().to_string())]); + } + #[cfg(target_arch = "wasm32")] + self.notify(crate::i18n::trn(crate::i18n::current(), made as u64, "Downloaded {n} PDF", "Downloaded {n} PDFs")); + } + if !refused.is_empty() { + self.notify(crate::i18n::fmt(tl!("Left out: {names}"), &[("names", &refused.join(", "))])); + } + } + /// Convert the picked files, join them in the order picked, and open the result in the page /// grid. A file that can't be converted is left out (and named in a notice); a file that can't be /// read stops the run. Files are read as their turn comes, so one file's bytes are held at a time. diff --git a/crates/ui-egui/src/files.rs b/crates/ui-egui/src/files.rs index e39b5eff..27c5d70e 100644 --- a/crates/ui-egui/src/files.rs +++ b/crates/ui-egui/src/files.rs @@ -22,6 +22,8 @@ pub enum FilePurpose { Ocr, /// Create a PDF ▸ Multiple files (PDFs, images and text). CreateMultiple, + /// Create one PDF per selected non-PDF file. + CreateMultipleSeparate, /// Find text and redact ▸ Import list: a text file with one word or phrase per line. RedactWords, } @@ -64,7 +66,7 @@ fn files_picker(purpose: FilePurpose) -> rfd::AsyncFileDialog { if purpose == FilePurpose::RedactWords { return dialog.add_filter(tl!("Text"), &["txt"]); } - if !matches!(purpose, FilePurpose::CreateMultiple | FilePurpose::InsertPages | FilePurpose::Combine) { + if !matches!(purpose, FilePurpose::CreateMultiple | FilePurpose::CreateMultipleSeparate | FilePurpose::InsertPages | FilePurpose::Combine) { return dialog.add_filter("PDF", &["pdf"]); } let all: Vec<&str> = std::iter::once("pdf").chain(pdfcraft_engine::CONVERTIBLE).collect(); @@ -228,6 +230,11 @@ impl PdfCraftApp { self.pick_files(FilePurpose::CreateMultiple, true); } + /// Create a PDF ▸ Separate PDFs: pick source files, then a destination folder. + pub fn create_multiple_separate_dialog(&mut self) { + self.pick_files(FilePurpose::CreateMultipleSeparate, true); + } + /// Scan & OCR ▸ Recognize text ▸ In multiple files: ask for the PDFs. pub fn ocr_files_dialog(&mut self) { self.pick_files(FilePurpose::Ocr, true); @@ -291,6 +298,25 @@ impl PdfCraftApp { } return; } + if purpose == FilePurpose::CreateMultipleSeparate { + if !paths.is_empty() { + let paths = paths.to_vec(); + let convert = move |app: &mut Self, dir: std::path::PathBuf| { + app.stage_create_separate(paths.iter().map(|p| read_named(p)), Some(dir)); + }; + match self.export_dir_override.clone() { + Some(dir) => convert(self, std::path::PathBuf::from(dir)), + None => { + self.ask_one( + crate::pickers::Ask::Folder(rfd::AsyncFileDialog::new().set_title(tl!("Choose a folder for the exported files"))), + None, + convert, + ); + } + } + } + return; + } let mut files = Vec::new(); let mut modified = Vec::new(); for p in paths { @@ -433,6 +459,10 @@ impl PdfCraftApp { } FilePurpose::Ocr => self.ocr_files(files), FilePurpose::CreateMultiple => self.stage_create_multiple(files.into_iter().map(Ok)), + FilePurpose::CreateMultipleSeparate => { + let dir = self.export_dir_override.as_ref().map(std::path::PathBuf::from); + self.stage_create_separate(files.into_iter().map(Ok), dir); + } FilePurpose::RedactWords => { let Some((name, bytes)) = files.into_iter().next() else { return }; if bytes.len() > crate::redact_ui::MAX_WORD_LIST_BYTES { diff --git a/crates/ui-egui/src/i18n/ar.tsv b/crates/ui-egui/src/i18n/ar.tsv index c880a6e8..3bd226e1 100644 --- a/crates/ui-egui/src/i18n/ar.tsv +++ b/crates/ui-egui/src/i18n/ar.tsv @@ -347,6 +347,7 @@ Create from إنشاء من Single file ملف واحد Multiple files عدة ملفات + Separate PDFs ملفات PDF منفصلة Images صور Clipboard الحافظة Blank page صفحة فارغة @@ -2039,6 +2040,7 @@ @plural {n} field|{n} fields {n} حقل|{n} حقل|{n} حقلان|{n} حقول|{n} حقلًا|{n} حقل @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} يتعارض {n} من أسماء الحقول مع الملفات السابقة وسيتم تغيير أسمائها: {list}|يتعارض اسم {n} حقل مع الملفات السابقة وسيتم تغيير اسمه: {list}|يتعارض اسما {n} حقل مع الملفات السابقة وسيتم تغيير اسميهما: {list}|تتعارض أسماء {n} حقول مع الملفات السابقة وسيتم تغيير أسمائها: {list}|يتعارض {n} اسم حقل مع الملفات السابقة وسيتم تغيير أسمائها: {list}|يتعارض {n} من أسماء الحقول مع الملفات السابقة وسيتم تغيير أسمائها: {list} Create PDF from multiple files… إنشاء PDF من عدة ملفات… + Create separate PDFs… إنشاء ملفات PDF منفصلة… Optimizing… removing user data جارٍ التحسين… إزالة بيانات المستخدم Optimizing… image {d} of {t} جارٍ التحسين… الصورة {d} من {t} Optimizing… cleaning up جارٍ التحسين… التنظيف @@ -2288,6 +2290,11 @@ scroll speed Fast سريعة Tools panel side جانب لوحة الأدوات Add comment إضافة تعليق Change tag properties تغيير خصائص الوسم + Left out: {names} تم استبعاد: {names} + already a PDF ملف PDF بالفعل + no unused output name لا يوجد اسم ناتج غير مستخدم + no output folder was chosen لم يتم اختيار مجلد للإخراج +@plural Downloaded {n} PDF|Downloaded {n} PDFs تم تنزيل {n} من ملفات PDF|تم تنزيل ملف PDF واحد ({n})|تم تنزيل ملفي PDF ({n})|تم تنزيل {n} ملفات PDF|تم تنزيل {n} ملف PDF|تم تنزيل {n} من ملفات PDF Scan مسح ضوئي Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. وقّع على ورقة بيضاء والتقط لها صورة في إضاءة ساطعة ومتساوية (استخدم الفلاش). اختر الصورة أو أفلتها هنا: يعثر PdfCraft على التوقيع ويزيل الورق. Choose photo… اختيار صورة… diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 1c7b5b7a..c422f471 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -88,6 +88,7 @@ Create PDF from file… Създай PDF от файл… Create PDF from images… Създай PDF от изображения… Create PDF from multiple files… Създай PDF от няколко файла… + Create separate PDFs… Създаване на отделни PDF файлове… Create PDF from clipboard Създай PDF от клипборда Combine files… Обедини файлове… Save Запиши @@ -951,6 +952,7 @@ Bring your own model (off by default) Използвайте собствен модел (изключено по подразбиране) Single file Един файл Multiple files Няколко файла + Separate PDFs Отделни PDF файлове Images Изображения Clipboard Клипборд Blank page Празна страница @@ -2230,6 +2232,11 @@ scroll speed Fast Висока Tools panel side Страна на панела с инструменти Add comment Добавяне на коментар Change tag properties Промяна на свойствата на етикета + Left out: {names} Пропуснати: {names} + already a PDF вече е PDF + no unused output name няма свободно име за изходния файл + no output folder was chosen не е избрана папка за изхода +@plural Downloaded {n} PDF|Downloaded {n} PDFs Изтеглен е {n} PDF|Изтеглени са {n} PDF файла Scan Сканиране Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Подпишете се на лист бяла хартия и го снимайте на ярка, равномерна светлина (със светкавица). Изберете снимката или я пуснете тук: PdfCraft открива подписа и премахва хартията. Choose photo… Избор на снимка… diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index faf1ef5b..8676e2f8 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -54,6 +54,7 @@ Create PDF from file… Vytvořit PDF ze souboru… Create PDF from images… Vytvořit PDF z obrázků… Create PDF from multiple files… Vytvořit PDF z více souborů… + Create separate PDFs… Vytvořit samostatná PDF… Create PDF from clipboard Vytvořit PDF ze schránky Combine files… Sloučit soubory… Save Uložit @@ -427,6 +428,7 @@ key Space Mezerník Create from Vytvořit z Single file Jeden soubor Multiple files Více souborů + Separate PDFs Samostatná PDF Images Obrázky Clipboard Schránka Blank page Prázdná stránka @@ -2341,6 +2343,11 @@ scroll speed Fast Rychlá Tools panel side Strana panelu nástrojů Add comment Přidat komentář Change tag properties Změnit vlastnosti značky + Left out: {names} Vynecháno: {names} + already a PDF již je PDF + no unused output name žádný volný název výstupního souboru + no output folder was chosen nebyla vybrána výstupní složka +@plural Downloaded {n} PDF|Downloaded {n} PDFs Stažen {n} soubor PDF|Staženy {n} soubory PDF|Staženo {n} souborů PDF Scan Skenovat Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Podepište se na bílý list papíru a vyfoťte ho při jasném, rovnoměrném světle (použijte blesk). Vyberte fotografii nebo ji sem přetáhněte: PdfCraft najde podpis a odstraní papír. Choose photo… Vybrat fotografii… diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index ab2342f4..8cb6acb0 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -28,6 +28,7 @@ Create PDF from file… PDF aus Datei erstellen… Create PDF from images… PDF aus Bildern erstellen… Create PDF from multiple files… PDF aus mehreren Dateien erstellen… + Create separate PDFs… Separate PDFs erstellen… Create PDF from clipboard PDF aus Zwischenablage erstellen Combine files… Dateien zusammenführen… Save Speichern @@ -319,6 +320,7 @@ Create from Erstellen aus Single file Einzelne Datei Multiple files Mehrere Dateien + Separate PDFs Einzelne PDFs Images Bilder Clipboard Zwischenablage Blank page Leere Seite @@ -2268,6 +2270,11 @@ scroll speed Fast Schnell Tools panel side Seite des Werkzeugbereichs Add comment Kommentar hinzufügen Change tag properties Tag-Eigenschaften ändern + Left out: {names} Ausgelassen: {names} + already a PDF bereits ein PDF + no unused output name kein freier Ausgabename + no output folder was chosen kein Ausgabeordner gewählt +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF heruntergeladen|{n} PDFs heruntergeladen Scan Scannen Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Unterschreiben Sie auf einem weißen Blatt Papier und fotografieren Sie es bei hellem, gleichmäßigem Licht (mit Blitz). Wählen Sie das Foto aus oder ziehen Sie es hierher: PdfCraft findet die Unterschrift und entfernt das Papier. Choose photo… Foto auswählen… diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index 8354bfd0..043b0e62 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -42,6 +42,7 @@ Create PDF from file… Δημιουργία PDF από αρχείο… Create PDF from images… Δημιουργία PDF από εικόνες… Create PDF from multiple files… Δημιουργία PDF από πολλά αρχεία… + Create separate PDFs… Δημιουργία ξεχωριστών PDF… Create PDF from clipboard Δημιουργία PDF από το πρόχειρο Combine files… Συνένωση αρχείων… Save Αποθήκευση @@ -1691,6 +1692,7 @@ Create from Δημιουργία από Single file Ένα αρχείο Multiple files Πολλά αρχεία + Separate PDFs Ξεχωριστά PDF Clipboard Πρόχειρο Blank page Κενή σελίδα Combine files Συνδυασμός αρχείων @@ -2282,6 +2284,11 @@ scroll speed Fast Γρήγορη Tools panel side Πλευρά πλαισίου εργαλείων Add comment Προσθήκη σχολίου Change tag properties Αλλαγή ιδιοτήτων ετικέτας + Left out: {names} Παραλείφθηκαν: {names} + already a PDF είναι ήδη PDF + no unused output name δεν υπάρχει διαθέσιμο όνομα εξόδου + no output folder was chosen δεν επιλέχθηκε φάκελος εξόδου +@plural Downloaded {n} PDF|Downloaded {n} PDFs Λήφθηκε {n} PDF|Λήφθηκαν {n} PDF @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} {n} όνομα πεδίου συγκρούεται με προηγούμενα αρχεία και θα μετονομαστεί: {list}|{n} ονόματα πεδίων συγκρούονται με προηγούμενα αρχεία και θα μετονομαστούν: {list} Scan Σάρωση Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Υπογράψτε σε ένα λευκό φύλλο χαρτιού και φωτογραφίστε το σε έντονο, ομοιόμορφο φως (χρησιμοποιήστε το φλας). Επιλέξτε τη φωτογραφία ή αφήστε την εδώ: το PdfCraft βρίσκει την υπογραφή και αφαιρεί το χαρτί. diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index ff3b4062..c162f095 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -51,6 +51,7 @@ Create PDF from file… Crear PDF a partir de un archivo… Create PDF from images… Crear PDF a partir de imágenes… Create PDF from multiple files… Crear PDF a partir de varios archivos… + Create separate PDFs… Crear PDF separados… Create PDF from clipboard Crear PDF a partir del portapapeles Combine files… Combinar archivos… Save Guardar @@ -342,6 +343,7 @@ Create from Crear a partir de Single file Un solo archivo Multiple files Varios archivos + Separate PDFs PDF separados Images Imágenes Clipboard Portapapeles Blank page Página en blanco @@ -2397,6 +2399,11 @@ scroll speed Fast Rápida Tools panel side Lado del panel de herramientas Add comment Añadir comentario Change tag properties Cambiar propiedades de la etiqueta + Left out: {names} Omitidos: {names} + already a PDF ya es un PDF + no unused output name no hay un nombre de salida libre + no output folder was chosen no se eligió ninguna carpeta de salida +@plural Downloaded {n} PDF|Downloaded {n} PDFs Se descargó {n} PDF|Se descargaron {n} PDF Scan Escanear Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Firme en una hoja de papel blanco y hágale una foto con luz intensa y uniforme (use el flash). Elija la foto o suéltela aquí: PdfCraft encuentra la firma y elimina el papel. Choose photo… Elegir foto… diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index a50f1879..51854a9d 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -28,6 +28,7 @@ Create PDF from file… Créer un PDF à partir d'un fichier… Create PDF from images… Créer un PDF à partir d'images… Create PDF from multiple files… Créer un PDF à partir de plusieurs fichiers… + Create separate PDFs… Créer des PDF séparés… Create PDF from clipboard Créer un PDF à partir du presse-papiers Combine files… Combiner des fichiers… Save Enregistrer @@ -319,6 +320,7 @@ Create from Créer à partir de Single file Un seul fichier Multiple files Plusieurs fichiers + Separate PDFs PDF séparés Images Images Clipboard Presse-papiers Blank page Page vierge @@ -2267,6 +2269,11 @@ scroll speed Fast Rapide Tools panel side Côté du panneau Outils Add comment Ajouter un commentaire Change tag properties Modifier les propriétés de la balise + Left out: {names} Ignorés : {names} + already a PDF déjà un PDF + no unused output name aucun nom de sortie libre + no output folder was chosen aucun dossier de sortie choisi +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF téléchargé|{n} PDF téléchargés Scan Numériser Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Signez une feuille de papier blanc et prenez-la en photo sous une lumière vive et uniforme (utilisez le flash). Choisissez la photo ou déposez-la ici : PdfCraft trouve la signature et retire le papier. Choose photo… Choisir une photo… diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 3a0c6997..90e51a70 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -28,6 +28,7 @@ Create PDF from file… PDF létrehozása fájlból… Create PDF from images… PDF létrehozása képekből… Create PDF from multiple files… PDF létrehozása több fájlból… + Create separate PDFs… Külön PDF-ek létrehozása… Create PDF from clipboard PDF létrehozása a vágólapról Combine files… Fájlok egyesítése… Save Mentés @@ -317,6 +318,7 @@ Create from Létrehozás ebből Single file Egy fájl Multiple files Több fájl + Separate PDFs Külön PDF-ek Images Képek Clipboard Vágólap Blank page Üres oldal @@ -2266,6 +2268,11 @@ scroll speed Fast Gyors Tools panel side Az Eszközök panel oldala Add comment Megjegyzés hozzáadása Change tag properties Címke tulajdonságainak módosítása + Left out: {names} Kihagyva: {names} + already a PDF már PDF + no unused output name nincs szabad kimeneti név + no output folder was chosen nincs kiválasztva kimeneti mappa +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF letöltve|{n} PDF letöltve Scan Beolvasás Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Írja alá a nevét egy fehér papírlapon, és fényképezze le erős, egyenletes fényben (vakuval). Válassza ki a fényképet, vagy húzza ide: a PdfCraft megkeresi az aláírást, és eltávolítja a papírt. Choose photo… Fénykép kiválasztása… diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index e2b96ea9..22a808f9 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -54,6 +54,7 @@ Create PDF from file… Crea PDF da file… Create PDF from images… Crea PDF da immagini… Create PDF from multiple files… Crea PDF da più file… + Create separate PDFs… Crea PDF separati… Create PDF from clipboard Crea PDF dagli appunti Combine files… Combina file… Save Salva @@ -343,6 +344,7 @@ Create from Crea da Single file File singolo Multiple files Più file + Separate PDFs PDF separati Images Immagini Clipboard Appunti Blank page Pagina vuota @@ -2276,6 +2278,11 @@ scroll speed Fast Veloce Tools panel side Lato del pannello Strumenti Add comment Aggiungi commento Change tag properties Modifica proprietà del tag + Left out: {names} Esclusi: {names} + already a PDF è già un PDF + no unused output name nessun nome di output libero + no output folder was chosen nessuna cartella di output scelta +@plural Downloaded {n} PDF|Downloaded {n} PDFs Scaricato {n} PDF|Scaricati {n} PDF Scan Scansiona Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Firma un foglio di carta bianca e fotografalo con una luce intensa e uniforme (usa il flash). Scegli la foto o trascinala qui: PdfCraft trova la firma e rimuove la carta. Choose photo… Scegli foto… diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index c4dd2e3a..1216fa96 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -57,6 +57,7 @@ Create PDF from file… ファイルから PDF を作成… Create PDF from images… 画像から PDF を作成… Create PDF from multiple files… 複数のファイルから PDF を作成… + Create separate PDFs… 個別の PDF を作成… Create PDF from clipboard クリップボードから PDF を作成 Combine files… ファイルを結合… Save 保存 @@ -346,6 +347,7 @@ Create from 作成元 Single file 単一ファイル Multiple files 複数のファイル + Separate PDFs 個別の PDF Images 画像 Clipboard クリップボード Blank page 空白のページ @@ -2267,6 +2269,11 @@ scroll speed Fast 速い Tools panel side ツールパネルの位置 Add comment コメントを追加 Change tag properties タグのプロパティを変更 + Left out: {names} 除外: {names} + already a PDF すでに PDF です + no unused output name 使用可能な出力名がありません + no output folder was chosen 出力フォルダーが選択されていません +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} 個の PDF をダウンロードしました Scan スキャン Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. 白い紙に署名し、明るく均一な光の下で写真を撮ってください(フラッシュを使用)。写真を選択するか、ここにドロップしてください。PdfCraft が署名を見つけ、紙の部分を取り除きます。 Choose photo… 写真を選択… diff --git a/crates/ui-egui/src/i18n/kk.tsv b/crates/ui-egui/src/i18n/kk.tsv index edc66dc4..699bad71 100644 --- a/crates/ui-egui/src/i18n/kk.tsv +++ b/crates/ui-egui/src/i18n/kk.tsv @@ -307,6 +307,7 @@ Create from Мынадан жасау Single file Бір файл Multiple files Бірнеше файл + Separate PDFs Бөлек PDF файлдары Images Кескіндер Clipboard Алмасу буфері Blank page Бос бет @@ -1964,6 +1965,7 @@ @plural {n} page|{n} pages {n} бет|{n} бет @plural {n} field|{n} fields {n} өріс|{n} өріс Create PDF from multiple files… Бірнеше файлдан PDF жасау… + Create separate PDFs… Бөлек PDF файлдарын жасау… Optimizing… removing user data Оңтайландыру… пайдаланушы деректерін жою Optimizing… image {d} of {t} Оңтайландыру… сурет {d} / {t} Optimizing… cleaning up Оңтайландыру… тазарту @@ -2264,6 +2266,11 @@ scroll speed Fast Жылдам Tools panel side Құралдар панелінің жағы Add comment Түсініктеме қосу Change tag properties Тег қасиеттерін өзгерту + Left out: {names} Қалдырылды: {names} + already a PDF бұл қазірдің өзінде PDF + no unused output name бос шығыс атауы жоқ + no output folder was chosen шығыс қалтасы таңдалмады +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF жүктелді|{n} PDF жүктелді @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} {n} өріс атауы алдыңғы файлдармен қайшы келеді және қайта аталады: {list}|{n} өріс атауы алдыңғы файлдармен қайшы келеді және қайта аталады: {list} Scan Сканерлеу Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Ақ қағаз парағына қол қойып, оны жарық әрі біркелкі жарықта суретке түсіріңіз (жарқылды қосыңыз). Суретті таңдаңыз немесе осында тастаңыз: PdfCraft қолтаңбаны тауып, қағазды алып тастайды. diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index a14d9ccc..ae782496 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -54,6 +54,7 @@ Create PDF from file… Utwórz PDF z pliku… Create PDF from images… Utwórz PDF z obrazów… Create PDF from multiple files… Utwórz PDF z wielu plików… + Create separate PDFs… Utwórz osobne pliki PDF… Create PDF from clipboard Utwórz PDF ze schowka Combine files… Połącz pliki… Save Zapisz @@ -341,6 +342,7 @@ Create from Utwórz z Single file Pojedynczy plik Multiple files Wiele plików + Separate PDFs Osobne pliki PDF Images Obrazy Clipboard Schowek Blank page Pusta strona @@ -2247,6 +2249,11 @@ scroll speed Fast Szybka Tools panel side Strona panelu narzędzi Add comment Dodaj komentarz Change tag properties Zmień właściwości znacznika + Left out: {names} Pominięto: {names} + already a PDF to już jest PDF + no unused output name brak wolnej nazwy pliku wyjściowego + no output folder was chosen nie wybrano folderu wyjściowego +@plural Downloaded {n} PDF|Downloaded {n} PDFs Pobrano {n} plik PDF|Pobrano {n} pliki PDF|Pobrano {n} plików PDF Scan Skanuj Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Podpisz się na białej kartce i zrób jej zdjęcie przy jasnym, równomiernym świetle (użyj lampy błyskowej). Wybierz zdjęcie lub upuść je tutaj: PdfCraft znajdzie podpis i usunie papier. Choose photo… Wybierz zdjęcie… diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index f699896c..64d0f70d 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -35,6 +35,7 @@ Create PDF from file… Criar PDF a partir de arquivo… Create PDF from images… Criar PDF a partir de imagens… Create PDF from multiple files… Criar PDF a partir de vários arquivos… + Create separate PDFs… Criar PDFs separados… Create PDF from clipboard Criar PDF a partir da área de transferência Combine files… Combinar arquivos… Save Salvar @@ -895,6 +896,7 @@ Bring your own model (off by default) Traga seu próprio modelo (desativado por padrão) Single file Arquivo único Multiple files Vários arquivos + Separate PDFs PDFs separados Images Imagens Clipboard Área de transferência Blank page Página em branco @@ -2281,6 +2283,11 @@ scroll speed Fast Rápida Tools panel side Lado do painel Ferramentas Add comment Adicionar comentário Change tag properties Alterar propriedades da tag + Left out: {names} Deixados de fora: {names} + already a PDF já é um PDF + no unused output name nenhum nome de saída disponível + no output folder was chosen nenhuma pasta de saída foi escolhida +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF baixado|{n} PDFs baixados Scan Digitalizar Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Assine uma folha de papel branco e tire uma foto dela com luz forte e uniforme (use o flash). Escolha a foto ou solte-a aqui: o PdfCraft encontra a assinatura e remove o papel. Choose photo… Escolher foto… diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 752436ad..13edd469 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -340,6 +340,7 @@ Create from Создать из Single file Один файл Multiple files Несколько файлов + Separate PDFs Отдельные PDF Images Изображения Clipboard Буфер обмена Blank page Пустая страница @@ -2046,6 +2047,7 @@ @plural {n} field|{n} fields {n} поле|{n} поля|{n} полей @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} Имя {n} поля конфликтует с предыдущими файлами и будет переименовано: {list}|Названия {n} полей конфликтуют с предыдущими файлами и будут переименованы: {list}|Названия {n} полей конфликтуют с предыдущими файлами и будут переименованы: {list} Create PDF from multiple files… Создать PDF из нескольких файлов… + Create separate PDFs… Создать отдельные PDF… Optimizing… removing user data Оптимизация… удаление пользовательских данных Optimizing… image {d} of {t} Оптимизация… изображение {d} из {t} Optimizing… cleaning up Оптимизация… очистка @@ -2180,6 +2182,11 @@ scroll speed Fast Высокая Tools panel side Сторона панели инструментов Add comment Добавить комментарий Change tag properties Изменить свойства тега + Left out: {names} Пропущены: {names} + already a PDF уже PDF + no unused output name нет свободного имени для выходного файла + no output folder was chosen не выбрана папка для вывода +@plural Downloaded {n} PDF|Downloaded {n} PDFs Скачан {n} PDF-файл|Скачано {n} PDF-файла|Скачано {n} PDF-файлов Scan Сканировать Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Распишитесь на листе белой бумаги и сфотографируйте его при ярком равномерном освещении (со вспышкой). Выберите фото или перетащите его сюда: PdfCraft найдёт подпись и уберёт бумагу. Choose photo… Выбрать фото… diff --git a/crates/ui-egui/src/i18n/sl.tsv b/crates/ui-egui/src/i18n/sl.tsv index 2af7896c..d020247c 100644 --- a/crates/ui-egui/src/i18n/sl.tsv +++ b/crates/ui-egui/src/i18n/sl.tsv @@ -485,6 +485,7 @@ Create PDF from images Ustvari PDF iz slik Create PDF from images… Ustvari PDF iz slik… Create PDF from multiple files… Ustvari PDF iz več datotek… + Create separate PDFs… Ustvari ločene PDF-je… Create a PDF Ustvari PDF Create a new Digital ID (self-signed, saved to a password-protected file) Ustvari novo digitalno identiteto (samopodpisano, shranjeno v datoteko, zaščiteno z geslom) Create accessibility report Ustvari poročilo o dostopnosti @@ -1104,6 +1105,7 @@ Multi-line Večvrstično Multiple Več Multiple files Več datotek + Separate PDFs Ločeni PDF-ji Multiple selection Večkratna izbira Name Ime Name (A–Z) Ime (A–Ž) @@ -2271,6 +2273,11 @@ scroll speed Fast Hitro Tools panel side Stran podokna z orodji Add comment Dodaj komentar Change tag properties Spremeni lastnosti oznake + Left out: {names} Izpuščeno: {names} + already a PDF je že PDF + no unused output name ni prostega izhodnega imena + no output folder was chosen izhodna mapa ni bila izbrana +@plural Downloaded {n} PDF|Downloaded {n} PDFs Prenesen {n} PDF|Prenesena {n} PDF-ja|Preneseni {n} PDF-ji|Prenesenih {n} PDF-jev @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} {n} ime polja se ujema z imeni iz prejšnjih datotek in bo preimenovano: {list}|{n} imeni polj se ujemata z imeni iz prejšnjih datotek in bosta preimenovani: {list}|{n} imena polj se ujemajo z imeni iz prejšnjih datotek in bodo preimenovana: {list}|{n} imen polj se ujema z imeni iz prejšnjih datotek in bo preimenovanih: {list} Scan Skeniraj Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Podpišite se na list belega papirja in ga fotografirajte v močni, enakomerni svetlobi (uporabite bliskavico). Izberite fotografijo ali jo spustite sem: PdfCraft poišče podpis in odstrani papir. diff --git a/crates/ui-egui/src/i18n/te.tsv b/crates/ui-egui/src/i18n/te.tsv index ec554e8e..12cac9d8 100644 --- a/crates/ui-egui/src/i18n/te.tsv +++ b/crates/ui-egui/src/i18n/te.tsv @@ -31,6 +31,7 @@ comment menu Edit సవరించు New blank PDF కొత్త ఖాళీ PDF Create PDF from file… ఫైల్ నుండి PDF సృష్టించు… Create PDF from multiple files… అనేక ఫైల్‌ల నుండి PDF సృష్టించు… + Create separate PDFs… వేర్వేరు PDFలను సృష్టించు… Create PDF from images… చిత్రాల నుండి PDF సృష్టించు… Create PDF from clipboard క్లిప్‌బోర్డ్ నుండి PDF సృష్టించు Combine files… ఫైల్‌లను కలుపు… @@ -323,6 +324,7 @@ comment menu Edit సవరించు Create from సృష్టించే మూలం Single file ఒకే ఫైల్ Multiple files అనేక ఫైల్‌లు + Separate PDFs వేర్వేరు PDFలు Images చిత్రాలు Clipboard క్లిప్‌బోర్డ్ Blank page ఖాళీ పేజీ @@ -2180,6 +2182,11 @@ scroll speed Fast వేగంగా Tools panel side టూల్స్ ప్యానెల్ వైపు Add comment వ్యాఖ్యను జోడించు Change tag properties ట్యాగ్ లక్షణాలను మార్చు + Left out: {names} వదిలివేసినవి: {names} + already a PDF ఇప్పటికే PDF + no unused output name ఉపయోగించని అవుట్‌పుట్ పేరు లేదు + no output folder was chosen అవుట్‌పుట్ ఫోల్డర్ ఎంచుకోలేదు +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF డౌన్‌లోడ్ చేయబడింది|{n} PDFలు డౌన్‌లోడ్ చేయబడ్డాయి Scan స్కాన్ Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. తెల్ల కాగితంపై సంతకం చేసి, ప్రకాశవంతమైన, సమానమైన వెలుతురులో దాని ఫోటో తీయండి (ఫ్లాష్ ఉపయోగించండి). ఫోటోను ఎంచుకోండి లేదా ఇక్కడ వదలండి: PdfCraft సంతకాన్ని కనుగొని కాగితాన్ని తొలగిస్తుంది. Choose photo… ఫోటో ఎంచుకోండి… diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 1da95fcc..2f8e95bc 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -20,6 +20,7 @@ Create PDF from file… Dosyadan PDF oluştur… Create PDF from images… Görsellerden PDF oluştur… Create PDF from multiple files… Birden çok dosyadan PDF oluştur… + Create separate PDFs… Ayrı PDF'ler oluştur… Create PDF from clipboard Panodan PDF oluştur Combine files… Dosyaları birleştir… Save Kaydet @@ -304,6 +305,7 @@ Create from Şuradan oluştur Single file Tek dosya Multiple files Birden çok dosya + Separate PDFs Ayrı PDF'ler Images Resimler Clipboard Pano Blank page Boş sayfa @@ -2262,6 +2264,11 @@ scroll speed Fast Hızlı Tools panel side Araçlar panelinin yeri Add comment Yorum ekle Change tag properties Etiket özelliklerini değiştir + Left out: {names} Dışarıda bırakılanlar: {names} + already a PDF zaten bir PDF + no unused output name kullanılmayan çıktı adı yok + no output folder was chosen çıktı klasörü seçilmedi +@plural Downloaded {n} PDF|Downloaded {n} PDFs {n} PDF indirildi @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} {n} alan adı önceki dosyalarla çakışıyor ve yeniden adlandırılacak: {list} Scan Tara Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Beyaz bir kâğıda imzanızı atın ve parlak, eşit ışıkta fotoğrafını çekin (flaş kullanın). Fotoğrafı seçin veya buraya bırakın: PdfCraft imzayı bulur ve kâğıdı kaldırır. diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 7e46f2e1..5c3b6a74 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -345,6 +345,7 @@ Create from Створити з Single file Один файл Multiple files Кілька файлів + Separate PDFs Окремі PDF-файли Images Зображення Clipboard Буфер обміну Blank page Порожня сторінка @@ -2037,6 +2038,7 @@ @plural {n} field|{n} fields {n} поле|{n} поля|{n} полів @plural {n} field name collides with earlier files and will be renamed: {list}|{n} field names collide with earlier files and will be renamed: {list} Назва {n} поля збігається з попередніми файлами та буде перейменована: {list}|Назви {n} полів збігаються з попередніми файлами та будуть перейменовані: {list}|Назви {n} полів збігаються з попередніми файлами та будуть перейменовані: {list} Create PDF from multiple files… Створити PDF із кількох файлів… + Create separate PDFs… Створити окремі PDF-файли… Optimizing… removing user data Оптимізація… видалення даних користувача Optimizing… image {d} of {t} Оптимізація… зображення {d} із {t} Optimizing… cleaning up Оптимізація… очищення @@ -2289,6 +2291,11 @@ scroll speed Fast Швидка Tools panel side Бік панелі інструментів Add comment Додати коментар Change tag properties Змінити властивості тегу + Left out: {names} Пропущено: {names} + already a PDF вже PDF + no unused output name немає вільної назви для вихідного файлу + no output folder was chosen не вибрано теку для виводу +@plural Downloaded {n} PDF|Downloaded {n} PDFs Завантажено {n} PDF-файл|Завантажено {n} PDF-файли|Завантажено {n} PDF-файлів Scan Сканувати Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. Розпишіться на аркуші білого паперу та сфотографуйте його за яскравого рівномірного освітлення (зі спалахом). Виберіть фото або перетягніть його сюди: PdfCraft знайде підпис і прибере папір. Choose photo… Вибрати фото… diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 65fa12da..3e9850ac 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -94,6 +94,7 @@ Create PDF from file… 从文件创建 PDF… Create PDF from images… 从图像创建 PDF… Create PDF from multiple files… 从多个文件创建 PDF… + Create separate PDFs… 创建单独的 PDF… Create PDF from clipboard 从剪贴板创建 PDF Combine files… 合并文件… Save 保存 @@ -958,6 +959,7 @@ Bring your own model (off by default) 自备模型(默认关闭) Single file 单个文件 Multiple files 多个文件 + Separate PDFs 单独的 PDF Images 图像 Clipboard 剪贴板 Blank page 空白页 @@ -2231,6 +2233,11 @@ scroll speed Fast 快 Tools panel side 工具面板位置 Add comment 添加注释 Change tag properties 更改标签属性 + Left out: {names} 已略过:{names} + already a PDF 已经是 PDF + no unused output name 没有可用的输出文件名 + no output folder was chosen 未选择输出文件夹 +@plural Downloaded {n} PDF|Downloaded {n} PDFs 已下载 {n} 个 PDF Scan 扫描 Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. 在白纸上签名,并在明亮、均匀的光线下拍照(使用闪光灯)。选择照片或将其拖放到此处:PdfCraft 会找到签名并去除纸张背景。 Choose photo… 选择照片… diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 883c0f5e..40f4d9d2 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -53,6 +53,7 @@ Create PDF from file… 從檔案建立 PDF… Create PDF from images… 從圖片建立 PDF… Create PDF from multiple files… 從多個檔案建立 PDF… + Create separate PDFs… 建立個別 PDF… Create PDF from clipboard 從剪貼簿建立 PDF Combine files… 合併檔案… Save 儲存 @@ -903,6 +904,7 @@ Bring your own model (off by default) 使用自己的模型(預設關閉) Single file 單一檔案 Multiple files 多個檔案 + Separate PDFs 個別 PDF Images 圖片 Clipboard 剪貼簿 Blank page 空白頁面 @@ -2141,6 +2143,11 @@ scroll speed Fast 快 Tools panel side 工具面板位置 Add comment 新增註解 Change tag properties 變更標籤屬性 + Left out: {names} 已略過:{names} + already a PDF 已經是 PDF + no unused output name 沒有可用的輸出檔名 + no output folder was chosen 未選擇輸出資料夾 +@plural Downloaded {n} PDF|Downloaded {n} PDFs 已下載 {n} 個 PDF Scan 掃描 Sign a sheet of white paper and take a photo of it in bright, even light (use the flash). Choose the photo or drop it here: PdfCraft finds the signature and removes the paper. 在白紙上簽名,並在明亮、均勻的光線下拍照(使用閃光燈)。選擇相片或將其拖放到此處:PdfCraft 會找到簽名並去除紙張背景。 Choose photo… 選擇相片… diff --git a/crates/ui-egui/tests/create.rs b/crates/ui-egui/tests/create.rs index 36b5e97c..bfbba2e1 100644 --- a/crates/ui-egui/tests/create.rs +++ b/crates/ui-egui/tests/create.rs @@ -200,6 +200,53 @@ fn mixed_files(app: &PdfCraftApp) -> Vec<(String, Vec)> { ] } +#[test] +fn separate_batch_creates_one_pdf_per_source_without_replacing_existing_files() { + use pdfcraft_ui_egui::FilePurpose; + let dir = std::env::temp_dir().join(format!("pdfcraft-separate-batch-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + std::fs::write(dir.join("notes.pdf"), b"keep this file").unwrap(); + + let mut app = PdfCraftApp::new(); + app.set_option("language", "en").unwrap(); + app.export_dir_override = Some(dir.to_string_lossy().into_owned()); + let mut files = mixed_files(&app); + files.push(("notes.txt".into(), b"another text file".to_vec())); + app.use_files(FilePurpose::CreateMultipleSeparate, files); + + assert_eq!(std::fs::read(dir.join("notes.pdf")).unwrap(), b"keep this file"); + for name in ["notes (2).pdf", "notes (3).pdf", "photo.pdf"] { + assert!(std::fs::read(dir.join(name)).unwrap().starts_with(b"%PDF-"), "{name}"); + } + assert!(!dir.join("a (2).pdf").exists(), "an already-PDF input is skipped"); + assert!(!dir.join("report.pdf").exists(), "an invalid Office file is skipped"); + assert!(app.views.is_empty(), "batch conversion must not open PDF tabs"); + std::fs::remove_dir_all(dir).unwrap(); +} + +#[test] +fn separate_batch_command_picks_files_and_writes_to_the_chosen_folder() { + use egui_kittest::Harness; + let dir = std::env::temp_dir().join(format!("pdfcraft-separate-command-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let source = dir.join("letter.txt"); + std::fs::write(&source, b"A separate PDF").unwrap(); + let mut h = Harness::builder().with_size(egui::vec2(1000.0, 720.0)).build_eframe(|_cc| { + let mut app = PdfCraftApp::new(); + app.set_option("language", "en").unwrap(); + app.pick_override = Some(vec![source.to_string_lossy().into_owned()]); + app.export_dir_override = Some(dir.to_string_lossy().into_owned()); + app + }); + assert!(h.state_mut().execute("create.multiple_separate")); + h.run_steps(2); + assert!(std::fs::read(dir.join("letter.pdf")).unwrap().starts_with(b"%PDF-")); + assert!(h.state().views.is_empty()); + std::fs::remove_dir_all(dir).unwrap(); +} + #[test] fn multiple_files_open_as_one_document_in_the_page_grid() { use egui_kittest::{Harness, kittest::Queryable}; diff --git a/docs/file-format-parity.md b/docs/file-format-parity.md index aa44a00f..4d9494e5 100644 --- a/docs/file-format-parity.md +++ b/docs/file-format-parity.md @@ -73,7 +73,7 @@ features total). | PostScript / EPS (Distiller) | yes | no | none | `create.distiller` planned (P3) | | Markdown | no | no | none | `create.from-markdown` planned (P2; not an Acrobat feature) | | Scanner | yes | no | none | `ocr.scanner-acquire` planned | -| Several files at once | yes | yes (PDFs, images and text) | good | `create.create-multiple` | +| Several files at once | yes | yes: combine PDFs, images and text into one document, or create a separate PDF for each non-PDF source (GUI and `doc_create_multiple mode=separate`); existing outputs get numbered names | good for supported source types | `create.create-multiple`, `separate_batch_creates_one_pdf_per_source_without_replacing_existing_files` | ## Export PDF to