diff --git a/crates/engine/src/cmd/fileio.rs b/crates/engine/src/cmd/fileio.rs index 0c888d13c..ae2ecde66 100644 --- a/crates/engine/src/cmd/fileio.rs +++ b/crates/engine/src/cmd/fileio.rs @@ -54,6 +54,7 @@ pub mod zip; use serde_json::{Value, json}; +pub use action_batch::batch_overwrites_one_file; pub use dxf::{UNSUPPORTED, Unsupported, unsupported}; pub use encode::{ARTBOARD_PARAMS, ArtboardPick, Encoded, encode, encode_all, encode_with_warnings}; pub(crate) use encode::{anti_alias, background, with_single_artboard}; diff --git a/crates/engine/src/cmd/fileio/action_batch.rs b/crates/engine/src/cmd/fileio/action_batch.rs index c1b5ae016..26d6c476e 100644 --- a/crates/engine/src/cmd/fileio/action_batch.rs +++ b/crates/engine/src/cmd/fileio/action_batch.rs @@ -73,10 +73,6 @@ pub(super) fn action_batch(s: &mut Session, p: &Value) -> Result { if !matches!(destination, "none" | "saveAndClose" | "folder") { return Err(bad(C, "`destination` must be `none`, `saveAndClose` or `folder`")); } - // Data sets share one open document, so Save and Close would write every row over one file. - if source == "datasets" && destination == "saveAndClose" { - return Err(bad(C, "Save and Close cannot batch data sets: choose Folder to save each data set to its own file")); - } let dest_folder = str_param(p, "destinationFolder").map(absolute_path); if destination == "folder" { let Some(ref folder) = dest_folder else { @@ -99,11 +95,65 @@ pub(super) fn action_batch(s: &mut Session, p: &Value) -> Result { }; match source { "folder" => batch_folder(s, C, p, override_open, &run), - "datasets" => batch_datasets(s, C, &run), + "datasets" => { + let one_file = batch_overwrites_one_file(s, p); + let mut r = batch_datasets(s, C, &run)?; + if one_file { + r["warning"] = json!(ONE_FILE_WARNING); + } + Ok(r) + } _ => Err(bad(C, "`source` must be `folder` or `datasets`")), } } +/// The `warning` of a Data Sets batch for which [`batch_overwrites_one_file`] holds. +#[cfg(not(target_arch = "wasm32"))] +const ONE_FILE_WARNING: &str = "each data set saves over the same file, which keeps only the last data set"; + +/// Whether an `action.batch` with params `p` plays on data sets of the open document in `s` and +/// writes each data set to the same file. Save and Close saves the open document over its own file +/// after every data set. A step that the batch does not point into `destinationFolder` writes the +/// same file every time when it writes one: a Save, Save As, Save a Copy, Save as Template, Export +/// or Export Selection step that gives a `path`; a Save step without a `path` when the document has +/// a file of its own (saved, and not converted from an older version or restored by Data Recovery) +/// and the step gives no `format` or the document's own; an Export for Screens +/// step whose `folder`, given or from its `exportPreset`, names a folder, whatever the overrides. +/// Other steps return their data instead of writing a file. +pub fn batch_overwrites_one_file(s: &Session, p: &Value) -> bool { + if p.get("source").and_then(Value::as_str) != Some("datasets") { + return false; + } + if p.get("destination").and_then(Value::as_str) == Some("saveAndClose") { + return true; + } + let folder = p.get("destinationFolder").and_then(Value::as_str).is_some(); + let redirected = |key: &str| folder && p.get(key).and_then(Value::as_bool).unwrap_or(true); + let (save, export) = (redirected("overrideSave"), redirected("overrideExport")); + // The format of the open document's own file, which a Save step without a `path` writes. + let own_format = s.active().filter(|st| st.path.is_some() && !st.converted && !st.recovered).map(|st| st.format); + let names = |v: Option<&Value>| v.and_then(Value::as_str).is_some_and(|s| !s.is_empty()); + p.get("commands").and_then(Value::as_array).is_some_and(|cmds| { + cmds.iter().any(|c| { + let params = c.get("params").cloned().unwrap_or_else(|| Value::Object(Default::default())); + let path = names(params.get("path")); + let own_file = || match params.get("format").and_then(Value::as_str).filter(|f| !f.is_empty()) { + None => own_format.is_some(), + Some(f) => own_format.is_some_and(|own| super::format(f).is_some_and(|f| f.id == own)), + }; + match c.get("command").and_then(Value::as_str).unwrap_or("") { + "document.save" | "file.save" => !save && (path || own_file()), + "file.saveAs" => !save && path, + "file.saveCopy" | "file.saveAsTemplate" => path, + "document.export" | "document.exportSelection" => !export && path, + // Override Export sets `path`, which Export for Screens does not read: its `folder` stays. + "document.exportForScreens" => super::screens::with_preset(s, ¶ms).is_ok_and(|p| names(p.get("folder"))), + _ => false, + } + }) + }) +} + #[cfg(not(target_arch = "wasm32"))] fn batch_folder(s: &mut Session, cmd: &str, p: &Value, override_open: bool, run: &Run<'_>) -> Result { use super::{absolute_path, may_read}; @@ -149,6 +199,9 @@ fn batch_datasets(s: &mut Session, cmd: &str, run: &Run<'_>) -> Result { if names.len() > MAX_BATCH_FILES { return Err(bad(cmd, format!("more than {MAX_BATCH_FILES} data sets"))); } + if run.destination == "saveAndClose" && st.path.is_none() { + return Err(bad(cmd, "the document has never been saved")); + } let doc_stem = st.path.as_deref().and_then(|p| std::path::Path::new(p).file_stem().and_then(|s| s.to_str())).unwrap_or("Untitled").to_string(); let stems = dataset_stems(&names, &doc_stem, run.dataset_file_naming, run, &st.doc)?; let steps = filter_steps(run.steps, true, false); @@ -1318,21 +1371,76 @@ mod tests { } #[test] - fn batch_refuses_save_and_close_over_data_sets_before_writing() { + fn batch_save_and_close_over_data_sets_saves_each_over_the_template_and_warns() { let path = tmp("save-close-sets").join("template.vectorcraft"); let mut s = saved_with_two_data_sets(&path); - let bytes = std::fs::read(&path).unwrap(); - let (active, revision) = { - let st = s.doc().unwrap(); - (st.doc.variables.active_dataset.clone(), st.revision) - }; - let msg = save_and_close_over_data_sets(&mut s).unwrap_err().to_string(); - assert!(msg.contains("choose Folder"), "{msg}"); - assert_eq!(std::fs::read(&path).unwrap(), bytes, "the template is not written"); + std::fs::write(&path, b"stale").unwrap(); + let r = save_and_close_over_data_sets(&mut s).unwrap(); + assert_eq!((r["count"].as_u64(), r["failed"].as_u64()), (Some(2), Some(0)), "{r}"); + assert_eq!(r["warning"], ONE_FILE_WARNING, "{r}"); + assert_ne!(std::fs::read(&path).unwrap(), b"stale", "the template's file is saved over"); + assert_eq!(file_names(path.parent().unwrap()), ["template.vectorcraft"], "{r}"); let st = s.doc().unwrap(); - assert_eq!(st.doc.variables.active_dataset, active, "no data set is selected"); - assert_eq!(st.revision, revision, "no step runs"); + assert_eq!(st.doc.variables.active_dataset.as_deref(), Some("B"), "the last data set is applied"); assert_eq!(st.path.as_deref(), Some(path.to_string_lossy().as_ref()), "the template stays open"); + assert!(!st.is_dirty(), "the last data set is saved"); + } + + #[test] + fn batch_warns_when_a_recorded_save_writes_one_file_for_every_data_set() { + let path = tmp("recorded-save-sets").join("template.vectorcraft"); + let mut s = saved_with_two_data_sets(&path); + let save = json!([{"command": "document.save", "params": {}}]); + let r = s.execute("action.batch", &json!({"source": "datasets", "commands": save})).unwrap(); + assert_eq!(r["failed"], 0, "{r}"); + assert_eq!(r["warning"], ONE_FILE_WARNING, "{r}"); + let dest = tmp("recorded-save-dest"); + let p = json!({"source": "datasets", "destination": "folder", "destinationFolder": dest.to_string_lossy(), "commands": save}); + let r = s.execute("action.batch", &p).unwrap(); + assert!(r.get("warning").is_none(), "Override Save points each save into the folder: {r}"); + let unlock = json!({"source": "datasets", "commands": [{"command": "object.unlockAll", "params": {}}]}); + let r = s.execute("action.batch", &unlock).unwrap(); + assert!(r.get("warning").is_none(), "{r}"); + } + + #[test] + fn one_file_rule_covers_save_and_close_and_steps_left_in_place() { + let saved = saved_with_two_data_sets(&tmp("one-file-rule").join("template.vectorcraft")); + let unsaved = with_data_sets(&["a"]); + let with = |extra: Value| { + let mut p = json!({"source": "datasets", "commands": [{"command": "document.export", "params": {"path": "/x/a.png"}}]}); + for (k, v) in extra.as_object().unwrap() { + p[k] = v.clone(); + } + batch_overwrites_one_file(&saved, &p) + }; + assert!(with(json!({})), "an export with its own path"); + assert!(!with(json!({"destination": "folder", "destinationFolder": "/out"}))); + assert!(with(json!({"destination": "folder", "destinationFolder": "/out", "overrideExport": false}))); + assert!(!with(json!({"destination": "folder", "destinationFolder": "/out", "overrideSave": false}))); + assert!(!with(json!({"source": "folder"})), "a folder source opens a file per pass"); + assert!(with(json!({"destination": "saveAndClose", "commands": [{"command": "object.unlockAll"}]}))); + let saved_as = json!({"commands": [{"command": "file.saveAs", "params": {"path": "/x/a.svg"}}]}); + assert!(with(saved_as.clone())); + assert!(!with(json!({"destination": "folder", "destinationFolder": "/out", "commands": saved_as["commands"]}))); + assert!(!with(json!({"commands": [{"command": "file.saveAs", "params": {}}]})), "no path: the data comes back"); + assert!(!with(json!({"commands": [{"command": "document.export", "params": {"format": "png"}}]})), "no path: the data comes back"); + let copy = json!([{"command": "file.saveCopy", "params": {"path": "/x/a.vectorcraft"}}]); + assert!(with(json!({"destination": "folder", "destinationFolder": "/out", "commands": copy})), "Override Save leaves copies alone"); + let save = |format: Option<&str>| { + let params = format.map_or(json!({}), |f| json!({"format": f})); + json!({"source": "datasets", "commands": [{"command": "document.save", "params": params}]}) + }; + assert!(batch_overwrites_one_file(&saved, &save(None)), "the document's own file"); + assert!(batch_overwrites_one_file(&saved, &save(Some("vectorcraft"))), "the document's own format"); + assert!(!batch_overwrites_one_file(&unsaved, &save(None)), "a document never saved has no file to write"); + assert!(!batch_overwrites_one_file(&saved, &save(Some("svg"))), "another format without a path: the data comes back"); + assert!(!with(json!({"commands": [{"command": "file.saveCopy", "params": {"folder": "/x"}}]})), "a folder alone: the data comes back"); + let screens = json!([{"command": "document.exportForScreens", "params": {"folder": "/x"}}]); + assert!(with(json!({"destination": "folder", "destinationFolder": "/out", "commands": screens})), "Override Export leaves its folder"); + assert!(!with(json!({"commands": [{"command": "document.exportForScreens", "params": {}}]}))); + let preset = json!([{"command": "document.exportForScreens", "params": {"exportPreset": "Logo Package"}}]); + assert!(!with(json!({"commands": preset})), "a preset without a folder: the data comes back"); } #[test] @@ -1343,7 +1451,7 @@ mod tests { (st.doc.variables.active_dataset.clone(), st.revision) }; let msg = save_and_close_over_data_sets(&mut s).unwrap_err().to_string(); - assert!(msg.contains("choose Folder"), "{msg}"); + assert!(msg.ends_with("the document has never been saved"), "{msg}"); let st = s.doc().unwrap(); assert_eq!(st.doc.variables.active_dataset, active, "no data set is selected"); assert_eq!(st.revision, revision, "no step runs"); diff --git a/crates/engine/src/cmd/fileio/commands.rs b/crates/engine/src/cmd/fileio/commands.rs index 0c010de10..9b62a5342 100644 --- a/crates/engine/src/cmd/fileio/commands.rs +++ b/crates/engine/src/cmd/fileio/commands.rs @@ -117,7 +117,7 @@ pub fn specs() -> Vec { "Batch…", [], None, - "{commands: [{command, params}] (the action's steps), source?: folder (default) | datasets, folder? (required for folder: the source folder), includeSubdirs?: false, destination?: none (default: leave each file open) | saveAndClose (save over the source and close; refused for source datasets: use folder to save each data set to its own file) | folder (save or export into destinationFolder and close), destinationFolder? (required when destination is folder; also the folder Override Save/Export write into), datasetFileNaming?: fileNumber | fileDataSetName (default) | dataSetName (used only for source datasets; ignored for folder), overrideOpen?: true (skip document.open / file.open steps: the batch opens each source file), overrideSave?: true (point document.save / file.save / file.saveAs at destinationFolder/{stem}.{ext}), overrideExport?: true (point document.export / document.exportForScreens / document.exportSelection the same way), stopOnError?: true, label?} play the commands on every readable file in folder (and its subfolders when includeSubdirs), or on every data set of the open document. Data set names use the document stem plus a three-digit ordinal, the document stem and an underscore plus the data set name, or the data set name alone. Invalid file name characters become `-`; a name already used in the batch or whose output already exists in a destination folder the batch may read and write gets the next free `-2`, `-3` suffix before the format-derived extension. Caps: 500 files or data sets, 8 folder levels, 256 steps. Batches cannot nest. → {processed: [{path|dataset, result|error}…], count, failed, stopped}", + "{commands: [{command, params}] (the action's steps), source?: folder (default) | datasets, folder? (required for folder: the source folder), includeSubdirs?: false, destination?: none (default: leave each file open) | saveAndClose (save over the source and close; for source datasets, save the open document over its own file after each data set, and refuse a document that was never saved) | folder (save or export into destinationFolder and close), destinationFolder? (required when destination is folder; also the folder Override Save/Export write into), datasetFileNaming?: fileNumber | fileDataSetName (default) | dataSetName (used only for source datasets; ignored for folder), overrideOpen?: true (skip document.open / file.open steps: the batch opens each source file), overrideSave?: true (point document.save / file.save / file.saveAs at destinationFolder/{stem}.{ext}), overrideExport?: true (point document.export / document.exportForScreens / document.exportSelection the same way), stopOnError?: true, label?} play the commands on every readable file in folder (and its subfolders when includeSubdirs), or on every data set of the open document. Data set names use the document stem plus a three-digit ordinal, the document stem and an underscore plus the data set name, or the data set name alone. Invalid file name characters become `-`; a name already used in the batch or whose output already exists in a destination folder the batch may read and write gets the next free `-2`, `-3` suffix before the format-derived extension. Caps: 500 files or data sets, 8 folder levels, 256 steps. Batches cannot nest. → {processed: [{path|dataset, result|error}…], count, failed, stopped, warning?} (warning: for source datasets, when Save and Close, or a Save, Save a Copy, Save as Template or Export step that writes a file and is not pointed into destinationFolder, saves every data set over the same file)", always, action_batch::action_batch ), diff --git a/crates/engine/src/cmd/fileio/screens.rs b/crates/engine/src/cmd/fileio/screens.rs index 201a4b479..11e878bc1 100644 --- a/crates/engine/src/cmd/fileio/screens.rs +++ b/crates/engine/src/cmd/fileio/screens.rs @@ -670,7 +670,7 @@ fn find_preset(s: &Session, name: &str) -> Option { } /// `p` over the settings of its `exportPreset`, when it names one (its own keys win). -fn with_preset(s: &Session, p: &Value) -> Result { +pub(super) fn with_preset(s: &Session, p: &Value) -> Result { let Some(name) = str_param(p, "exportPreset") else { return Ok(p.clone()) }; let preset = find_preset(s, name).ok_or_else(|| bad(C, format!("no export preset `{name}` (see document.exportPresets.list)")))?; let mut merged = preset.settings; diff --git a/crates/ui-egui/src/dialogs/action_batch.rs b/crates/ui-egui/src/dialogs/action_batch.rs index 36369132a..4e8a3bfae 100644 --- a/crates/ui-egui/src/dialogs/action_batch.rs +++ b/crates/ui-egui/src/dialogs/action_batch.rs @@ -77,12 +77,7 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool { } ui.add_space(8.0); - let choices = destinations(&source); - let destination = d.str("destination"); - if !choices.iter().any(|(value, _)| *value == destination) { - d.fields.insert("destination".into(), json!("folder")); - } - form::choice(ui, d, "destination", "Destination:", (LABEL, 200.0), choices); + form::choice(ui, d, "destination", "Destination:", (LABEL, 200.0), &[("none", "None"), ("saveAndClose", "Save and Close"), ("folder", "Folder")]); if d.str("destination") == "folder" { widgets::label_row(ui, tl!("Destination Folder:"), LABEL, |ui| { form::text(ui, d, "destinationFolder", 200.0); @@ -97,17 +92,21 @@ fn body(app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool { form::check(ui, d, "overrideSave", "Override Action \"Save\" Commands"); form::check(ui, d, "overrideExport", "Override Action \"Export\" Commands"); form::check(ui, d, "stopOnError", "Stop on Errors"); + if overwrites_one_file(app, d) { + ui.add_space(6.0); + ui.label(egui::RichText::new(tl!("Each data set saves over the same file, which keeps only the last data set.")).size(11.5).color(t.warning)); + } false } -/// The Destination choices for `source`. Data sets share one open document, so Save and Close is -/// offered for a Folder source only. -fn destinations(source: &str) -> &'static [(&'static str, &'static str)] { - if source == "datasets" { - &[("none", "None"), ("folder", "Folder")] - } else { - &[("none", "None"), ("saveAndClose", "Save and Close"), ("folder", "Folder")] - } +/// Whether the batch the dialog would run saves every data set over the same file +/// ([`vectorcraft_engine::cmd::fileio::batch_overwrites_one_file`]). +fn overwrites_one_file(app: &VectorcraftApp, d: &Dialog) -> bool { + let set = d.fields.get("set").and_then(Value::as_u64).unwrap_or(0) as usize; + let action = d.fields.get("action").and_then(Value::as_u64).unwrap_or(0) as usize; + let steps = app.ui.action_sets.get(set).and_then(|s| s.actions.get(action)).map_or(&[][..], |a| &a.steps[..]); + let commands = steps.iter().map(|(c, p)| json!({"command": c, "params": p})).collect(); + vectorcraft_engine::cmd::fileio::batch_overwrites_one_file(&app.session, ¶ms(d, "", commands)) } fn confirm(app: &mut VectorcraftApp, d: &Dialog) -> Result { @@ -183,6 +182,11 @@ mod tests { /// Draws `d` once and returns the texts it shows. fn render(d: &mut Dialog) -> Vec { + render_in(&mut VectorcraftApp::new(Session::new(), Default::default()), d) + } + + /// Draws `d` once over `app` and returns the texts it shows. + fn render_in(app: &mut VectorcraftApp, d: &mut Dialog) -> Vec { fn collect(shape: &egui::Shape, out: &mut Vec) { match shape { egui::Shape::Text(t) => out.push(t.galley.text().to_string()), @@ -190,11 +194,10 @@ mod tests { _ => {} } } - let mut app = VectorcraftApp::new(Session::new(), Default::default()); let ctx = egui::Context::default(); crate::theme::install_fonts(&ctx); let mut frame = ctx.run_ui(Default::default(), |ui| { - body(&mut app, ui, d); + body(app, ui, d); }); frame.textures_delta.clear(); let mut labels = vec![]; @@ -241,17 +244,36 @@ mod tests { assert!(params(&d, "Test", vec![]).get("datasetFileNaming").is_none()); } + const ONE_FILE: &str = "Each data set saves over the same file, which keeps only the last data set."; + #[test] - fn data_sets_do_not_offer_save_and_close() { - assert!(!destinations("datasets").iter().any(|(value, _)| *value == "saveAndClose")); - assert!(destinations("folder").iter().any(|(value, _)| *value == "saveAndClose")); + fn data_sets_offer_save_and_close_with_a_warning() { let mut d = Dialog::new(KIND, initial_fields(0, 0, "Test")); d.fields["destination"] = json!("saveAndClose"); - assert!(render(&mut d).iter().any(|label| label == "Save and Close")); + let labels = render(&mut d); + assert!(labels.iter().any(|label| label == "Save and Close"), "{labels:?}"); + assert!(!labels.iter().any(|label| label == ONE_FILE), "a folder source opens a file per pass: {labels:?}"); d.fields["source"] = json!("datasets"); let labels = render(&mut d); - assert!(!labels.iter().any(|label| label == "Save and Close"), "{labels:?}"); - assert!(labels.iter().any(|label| label == "Destination Folder:"), "{labels:?}"); - assert_eq!(params(&d, "Test", vec![])["destination"], "folder"); + assert!(labels.iter().any(|label| label == "Save and Close"), "{labels:?}"); + assert!(labels.iter().any(|label| label == ONE_FILE), "{labels:?}"); + assert_eq!(params(&d, "Test", vec![])["destination"], "saveAndClose"); + d.fields["destination"] = json!("folder"); + assert!(!render(&mut d).iter().any(|label| label == ONE_FILE)); + } + + #[test] + fn data_sets_warn_about_a_recorded_save_left_in_place() { + let mut app = VectorcraftApp::new(Session::new(), Default::default()); + app.ui.action_sets[0].actions[0].steps.push(("document.save".into(), json!({"path": "/x/a.vectorcraft"}))); + let mut d = Dialog::new(KIND, initial_fields(0, 0, "Test")); + d.fields["source"] = json!("datasets"); + d.fields["destinationFolder"] = json!("/out"); + assert!(!render_in(&mut app, &mut d).iter().any(|label| label == ONE_FILE), "Override Save points the save into the folder"); + d.fields["overrideSave"] = json!(false); + assert!(render_in(&mut app, &mut d).iter().any(|label| label == ONE_FILE)); + d.fields["overrideSave"] = json!(true); + d.fields["destination"] = json!("none"); + assert!(render_in(&mut app, &mut d).iter().any(|label| label == ONE_FILE)); } } diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 85c714b78..b94e7895c 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -6099,7 +6099,7 @@ breakText Glyphs Глифи File + Data Set Name Файл + име на набора от данни Data Set Name Име на набора от данни @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` трябва да е `fileNumber`, `fileDataSetName` или `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „Запазване и затваряне“ не може да обработва набори от данни: изберете „Папка“, за да запишете всеки набор от данни в отделен файл + Each data set saves over the same file, which keeps only the last data set. Всеки набор от данни се записва върху същия файл, в който остава само последният набор от данни. @msg no free data set file name in destination folder Няма свободно име за файл на набор от данни в целевата папка # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/bs.tsv b/crates/ui-egui/src/i18n/bs.tsv index edd42d7c4..176aafe80 100644 --- a/crates/ui-egui/src/i18n/bs.tsv +++ b/crates/ui-egui/src/i18n/bs.tsv @@ -6111,7 +6111,7 @@ shape Open Otvoren File + Data Set Name Datoteka + naziv skupa podataka Data Set Name Naziv skupa podataka @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` mora biti `fileNumber`, `fileDataSetName` ili `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „Sačuvaj i zatvori“ ne može obraditi skupove podataka: odaberite „Folder“ da biste svaki skup podataka sačuvali u zasebnu datoteku + Each data set saves over the same file, which keeps only the last data set. Svaki skup podataka se sačuva preko iste datoteke, u kojoj ostaje samo posljednji skup podataka. @msg no free data set file name in destination folder Nema slobodnog naziva datoteke skupa podataka u odredišnoj mapi # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/ca.tsv b/crates/ui-egui/src/i18n/ca.tsv index f2b00581a..2efc35f97 100644 --- a/crates/ui-egui/src/i18n/ca.tsv +++ b/crates/ui-egui/src/i18n/ca.tsv @@ -6255,7 +6255,7 @@ breakText Glyphs Glifs File + Data Set Name Fitxer + nom del conjunt de dades Data Set Name Nom del conjunt de dades @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` ha de ser `fileNumber`, `fileDataSetName` o `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file «Desa i tanca» no pot processar conjunts de dades: trieu «Carpeta» per desar cada conjunt de dades en un fitxer propi + Each data set saves over the same file, which keeps only the last data set. Cada conjunt de dades es desa sobre el mateix fitxer, que només conserva l'últim conjunt de dades. @msg no free data set file name in destination folder No hi ha cap nom de fitxer de conjunt de dades lliure a la carpeta de destinació # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 66aaefa8e..5e72b3e66 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -6274,7 +6274,7 @@ breakText Glyphs Glyfy File + Data Set Name Soubor + název sady dat Data Set Name Název sady dat @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` musí být `fileNumber`, `fileDataSetName` nebo `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „Uložit a zavřít“ nelze použít pro sady dat: zvolte „Složka“, aby se každá sada dat uložila do vlastního souboru + Each data set saves over the same file, which keeps only the last data set. Každá sada dat se uloží přes stejný soubor, ve kterém zůstane jen poslední sada dat. @msg no free data set file name in destination folder V cílové složce není volný název souboru sady dat # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/da.tsv b/crates/ui-egui/src/i18n/da.tsv index 3e9389579..516fada6e 100644 --- a/crates/ui-egui/src/i18n/da.tsv +++ b/crates/ui-egui/src/i18n/da.tsv @@ -6114,7 +6114,7 @@ breakText Glyphs Glyffer File + Data Set Name Fil + datasætnavn Data Set Name Datasætnavn @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` skal være `fileNumber`, `fileDataSetName` eller `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file "Gem og luk" kan ikke køre på datasæt: vælg "Mappe" for at gemme hvert datasæt i sin egen fil + Each data set saves over the same file, which keeps only the last data set. Hvert datasæt gemmes oven i den samme fil, som kun beholder det sidste datasæt. @msg no free data set file name in destination folder Intet ledigt filnavn til datasættet i destinationsmappen # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 75345b1f7..73217a465 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -5859,7 +5859,7 @@ breakText Glyphs Glyphen File + Data Set Name Datei + Datensatzname Data Set Name Datensatzname @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` muss `fileNumber`, `fileDataSetName` oder `dataSetName` sein -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „Speichern und schließen“ kann nicht auf Datensätze angewendet werden: Wählen Sie „Ordner“, um jeden Datensatz in einer eigenen Datei zu speichern + Each data set saves over the same file, which keeps only the last data set. Jeder Datensatz wird über dieselbe Datei gespeichert, die nur den letzten Datensatz behält. @msg no free data set file name in destination folder Kein freier Dateiname für den Datensatz im Zielordner # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index cf071420c..1a703f159 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -6225,7 +6225,7 @@ breakText Glyphs Γλύφοι File + Data Set Name Αρχείο + όνομα συνόλου δεδομένων Data Set Name Όνομα συνόλου δεδομένων @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` Το `datasetFileNaming` πρέπει να είναι `fileNumber`, `fileDataSetName` ή `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file Η «Αποθήκευση και κλείσιμο» δεν μπορεί να εφαρμοστεί σε σύνολα δεδομένων: επιλέξτε «Φάκελος» για να αποθηκευτεί κάθε σύνολο δεδομένων σε δικό του αρχείο + Each data set saves over the same file, which keeps only the last data set. Κάθε σύνολο δεδομένων αποθηκεύεται πάνω στο ίδιο αρχείο, το οποίο κρατά μόνο το τελευταίο σύνολο δεδομένων. @msg no free data set file name in destination folder Δεν υπάρχει διαθέσιμο όνομα αρχείου συνόλου δεδομένων στον φάκελο προορισμού # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 29d345748..0e4df7790 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -6216,7 +6216,7 @@ breakText Glyphs Glifos File + Data Set Name Archivo + nombre del conjunto de datos Data Set Name Nombre del conjunto de datos @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` debe ser `fileNumber`, `fileDataSetName` o `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file «Guardar y cerrar» no puede procesar conjuntos de datos: elija «Carpeta» para guardar cada conjunto de datos en su propio archivo + Each data set saves over the same file, which keeps only the last data set. Cada conjunto de datos se guarda sobre el mismo archivo, que solo conserva el último conjunto de datos. @msg no free data set file name in destination folder No hay un nombre de archivo libre para el conjunto de datos en la carpeta de destino # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index 7e0695592..8d1fe5f74 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -6304,7 +6304,7 @@ breakText Glyphs Merkit File + Data Set Name Tiedosto + tietojoukon nimi Data Set Name Tietojoukon nimi @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming`-arvon on oltava `fileNumber`, `fileDataSetName` tai `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file ”Tallenna ja sulje” ei voi käsitellä tietojoukkoja: valitse ”Kansio”, niin jokainen tietojoukko tallennetaan omaan tiedostoonsa + Each data set saves over the same file, which keeps only the last data set. Jokainen tietojoukko tallennetaan saman tiedoston päälle, johon jää vain viimeinen tietojoukko. @msg no free data set file name in destination folder Kohdekansiossa ei ole vapaata tietojoukon tiedostonimeä # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index e814e8378..6f1bc1715 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -6269,7 +6269,7 @@ breakText Glyphs Glyphes File + Data Set Name Fichier + nom du jeu de données Data Set Name Nom du jeu de données @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` doit être `fileNumber`, `fileDataSetName` ou `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file « Enregistrer et fermer » ne peut pas traiter les jeux de données : choisissez « Dossier » pour enregistrer chaque jeu de données dans son propre fichier + Each data set saves over the same file, which keeps only the last data set. Chaque jeu de données est enregistré sur le même fichier, qui ne conserve que le dernier jeu de données. @msg no free data set file name in destination folder Aucun nom de fichier libre pour le jeu de données dans le dossier de destination # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index f33c5d7d6..b52b62022 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -6258,7 +6258,7 @@ breakText Glyphs Glifák File + Data Set Name Fájl + adatkészlet neve Data Set Name Adatkészlet neve @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` A `datasetFileNaming` értéke `fileNumber`, `fileDataSetName` vagy `dataSetName` lehet -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file A „Mentés és bezárás” nem dolgozhat fel adatkészleteket: válassza a „Mappa” lehetőséget, hogy minden adatkészlet külön fájlba kerüljön + Each data set saves over the same file, which keeps only the last data set. Minden adatkészlet ugyanabba a fájlba mentődik, amely csak az utolsó adatkészletet őrzi meg. @msg no free data set file name in destination folder Nincs szabad adatkészlet-fájlnév a célmappában # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/id.tsv b/crates/ui-egui/src/i18n/id.tsv index e7b1655d6..176e1da88 100644 --- a/crates/ui-egui/src/i18n/id.tsv +++ b/crates/ui-egui/src/i18n/id.tsv @@ -6114,7 +6114,7 @@ breakText Glyphs Glif File + Data Set Name File + nama set data Data Set Name Nama set data @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` harus `fileNumber`, `fileDataSetName`, atau `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file "Simpan dan tutup" tidak dapat memproses set data: pilih "Folder" untuk menyimpan setiap set data ke file tersendiri + Each data set saves over the same file, which keeps only the last data set. Setiap set data disimpan menimpa file yang sama, sehingga hanya set data terakhir yang tersisa. @msg no free data set file name in destination folder Tidak ada nama file set data yang tersedia di folder tujuan # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 231ed0230..c9d316985 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -5893,7 +5893,7 @@ breakText Glyphs Glifi File + Data Set Name File + nome set di dati Data Set Name Nome set di dati @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` deve essere `fileNumber`, `fileDataSetName` o `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file «Salva e chiudi» non può elaborare i set di dati: scegli «Cartella» per salvare ogni set di dati in un file a sé + Each data set saves over the same file, which keeps only the last data set. Ogni set di dati viene salvato sullo stesso file, che conserva solo l'ultimo set di dati. @msg no free data set file name in destination folder Nessun nome file libero per il set di dati nella cartella di destinazione # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index ac6bb51bc..6dfa754c7 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -5958,7 +5958,7 @@ breakText Glyphs 字形 File + Data Set Name ファイル名 + データセット名 Data Set Name データセット名 @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` は `fileNumber`、`fileDataSetName`、`dataSetName` のいずれかである必要があります -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file 「保存して閉じる」ではデータセットをバッチ処理できません:各データセットを個別のファイルに保存するには「フォルダー」を選択してください + Each data set saves over the same file, which keeps only the last data set. 各データセットが同じファイルに上書き保存されるため、最後のデータセットだけが残ります。 @msg no free data set file name in destination folder 保存先フォルダーに使用可能なデータセットのファイル名がありません # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/ka.tsv b/crates/ui-egui/src/i18n/ka.tsv index a0b1d42a6..fb53b753d 100644 --- a/crates/ui-egui/src/i18n/ka.tsv +++ b/crates/ui-egui/src/i18n/ka.tsv @@ -6271,7 +6271,7 @@ breakText Glyphs გლიფები File + Data Set Name ფაილი + მონაცემთა ნაკრების სახელი Data Set Name მონაცემთა ნაკრების სახელი @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` უნდა იყოს `fileNumber`, `fileDataSetName` ან `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „შენახვა და დახურვა“ ვერ ამუშავებს მონაცემთა ნაკრებებს: აირჩიეთ „საქაღალდე“, რომ თითოეული მონაცემთა ნაკრები ცალკე ფაილში შეინახოთ + Each data set saves over the same file, which keeps only the last data set. თითოეული მონაცემთა ნაკრები ერთსა და იმავე ფაილზე ინახება, რომელშიც მხოლოდ ბოლო მონაცემთა ნაკრები რჩება. @msg no free data set file name in destination folder დანიშნულების საქაღალდეში მონაცემთა ნაკრებისთვის თავისუფალი ფაილის სახელი არ არის # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index c083822b2..81e98bb47 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -5854,7 +5854,7 @@ breakText Glyphs 글리프 File + Data Set Name 파일 + 데이터 세트 이름 Data Set Name 데이터 세트 이름 @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming`은 `fileNumber`, `fileDataSetName` 또는 `dataSetName`이어야 합니다 -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file '저장 후 닫기'로는 데이터 세트를 일괄 처리할 수 없습니다: 각 데이터 세트를 별도의 파일로 저장하려면 '폴더'를 선택하세요 + Each data set saves over the same file, which keeps only the last data set. 각 데이터 세트가 같은 파일에 덮어써지므로 마지막 데이터 세트만 남습니다. @msg no free data set file name in destination folder 대상 폴더에 사용할 수 있는 데이터 세트 파일 이름이 없습니다 # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/nl.tsv b/crates/ui-egui/src/i18n/nl.tsv index 5c9bd74f1..345d7918e 100644 --- a/crates/ui-egui/src/i18n/nl.tsv +++ b/crates/ui-egui/src/i18n/nl.tsv @@ -6160,7 +6160,7 @@ breakText Glyphs Glyphs File + Data Set Name Bestand + naam gegevensset Data Set Name Naam gegevensset @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` moet `fileNumber`, `fileDataSetName` of `dataSetName` zijn -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file 'Opslaan en sluiten' kan geen gegevenssets verwerken: kies 'Map' om elke gegevensset in een eigen bestand op te slaan + Each data set saves over the same file, which keeps only the last data set. Elke gegevensset wordt over hetzelfde bestand opgeslagen, dat alleen de laatste gegevensset bewaart. @msg no free data set file name in destination folder Geen vrije bestandsnaam voor de gegevensset in de doelmap # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index cb934d784..1290a0f79 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -6128,7 +6128,7 @@ breakText Glyphs Glify File + Data Set Name Plik + nazwa zestawu danych Data Set Name Nazwa zestawu danych @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` musi mieć wartość `fileNumber`, `fileDataSetName` lub `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file „Zapisz i zamknij” nie może przetwarzać zestawów danych: wybierz „Folder”, aby zapisać każdy zestaw danych w osobnym pliku + Each data set saves over the same file, which keeps only the last data set. Każdy zestaw danych jest zapisywany w tym samym pliku, który zachowuje tylko ostatni zestaw danych. @msg no free data set file name in destination folder Brak wolnej nazwy pliku zestawu danych w folderze docelowym # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 8ac21f8e9..ab767fcc2 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -6190,7 +6190,7 @@ breakText Glyphs Glifos File + Data Set Name Arquivo + nome do conjunto de dados Data Set Name Nome do conjunto de dados @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` deve ser `fileNumber`, `fileDataSetName` ou `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file "Salvar e fechar" não pode processar conjuntos de dados: escolha "Pasta" para salvar cada conjunto de dados em um arquivo próprio + Each data set saves over the same file, which keeps only the last data set. Cada conjunto de dados é salvo sobre o mesmo arquivo, que mantém apenas o último conjunto de dados. @msg no free data set file name in destination folder Não há nome de arquivo livre para o conjunto de dados na pasta de destino # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index d436e1b7e..d126c5dab 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -6251,7 +6251,7 @@ breakText Glyphs Глифы File + Data Set Name Файл + имя набора данных Data Set Name Имя набора данных @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` должно быть `fileNumber`, `fileDataSetName` или `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file «Сохранить и закрыть» не работает с наборами данных: выберите «Папка», чтобы сохранить каждый набор данных в отдельный файл + Each data set saves over the same file, which keeps only the last data set. Каждый набор данных сохраняется поверх одного и того же файла, в котором остаётся только последний набор данных. @msg no free data set file name in destination folder В папке назначения нет свободного имени файла для набора данных # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 4438027d8..4d9e8da51 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -6326,7 +6326,7 @@ breakText Glyphs Glyfer File + Data Set Name Fil + datauppsättningens namn Data Set Name Datauppsättningens namn @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` måste vara `fileNumber`, `fileDataSetName` eller `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file ”Spara och stäng” kan inte köras på datauppsättningar: välj ”Mapp” för att spara varje datauppsättning i en egen fil + Each data set saves over the same file, which keeps only the last data set. Varje datauppsättning sparas över samma fil, som bara behåller den sista datauppsättningen. @msg no free data set file name in destination folder Inget ledigt filnamn för datauppsättningen i målmappen # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 5157d5bf3..ec0c64cd1 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -6231,7 +6231,7 @@ breakText Glyphs Glifler File + Data Set Name Dosya + veri kümesi adı Data Set Name Veri kümesi adı @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` değeri `fileNumber`, `fileDataSetName` veya `dataSetName` olmalıdır -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file "Kaydet ve Kapat" veri kümelerini toplu işleyemez: her veri kümesini ayrı bir dosyaya kaydetmek için "Klasör" seçeneğini seçin + Each data set saves over the same file, which keeps only the last data set. Her veri kümesi aynı dosyanın üzerine kaydedilir ve dosyada yalnızca son veri kümesi kalır. @msg no free data set file name in destination folder Hedef klasörde veri kümesi için boş bir dosya adı yok # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index db7e9ccd2..014ee77f0 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -5873,7 +5873,7 @@ breakText Glyphs Гліфи File + Data Set Name Файл + назва набору даних Data Set Name Назва набору даних @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` має бути `fileNumber`, `fileDataSetName` або `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file «Зберегти й закрити» не працює з наборами даних: виберіть «Папка», щоб зберегти кожен набір даних в окремий файл + Each data set saves over the same file, which keeps only the last data set. Кожен набір даних зберігається поверх того самого файлу, у якому лишається тільки останній набір даних. @msg no free data set file name in destination folder У папці призначення немає вільного імені файлу набору даних # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index f59304809..f79734084 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -5874,7 +5874,7 @@ breakText Glyphs Glyph File + Data Set Name Tệp + tên tập dữ liệu Data Set Name Tên tập dữ liệu @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` phải là `fileNumber`, `fileDataSetName` hoặc `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file "Lưu và đóng" không thể xử lý các tập dữ liệu: chọn "Thư mục" để lưu mỗi tập dữ liệu vào một tệp riêng + Each data set saves over the same file, which keeps only the last data set. Mỗi tập dữ liệu được lưu đè lên cùng một tệp, nên tệp chỉ giữ lại tập dữ liệu cuối cùng. @msg no free data set file name in destination folder Không có tên tệp tập dữ liệu còn trống trong thư mục đích # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index 379f4dc23..2c6da8373 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -6115,7 +6115,7 @@ breakText Glyphs 字形 File + Data Set Name 文件 + 数据集名称 Data Set Name 数据集名称 @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` 必须是 `fileNumber`、`fileDataSetName` 或 `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file “存储并关闭”无法批处理数据集:请选择“文件夹”,将每个数据集存储为单独的文件 + Each data set saves over the same file, which keeps only the last data set. 每个数据集都会存储到同一个文件并覆盖它,该文件只保留最后一个数据集。 @msg no free data set file name in destination folder 目标文件夹中没有可用的数据集文件名 # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 46c332bd4..096e8602a 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -5911,7 +5911,7 @@ breakText Glyphs 字符 File + Data Set Name 檔案 + 資料集名稱 Data Set Name 資料集名稱 @msg `datasetFileNaming` must be `fileNumber`, `fileDataSetName` or `dataSetName` `datasetFileNaming` 必須是 `fileNumber`、`fileDataSetName` 或 `dataSetName` -@msg Save and Close cannot batch data sets: choose Folder to save each data set to its own file 「儲存並關閉」無法批次處理資料集:請選擇「資料夾」,將每個資料集儲存為個別檔案 + Each data set saves over the same file, which keeps only the last data set. 每個資料集都會儲存到同一個檔案並覆寫它,該檔案只保留最後一個資料集。 @msg no free data set file name in destination folder 目的地資料夾中沒有可用的資料集檔案名稱 # Path Precision Tools add-on: Path Effects (Effect › Path Effects). diff --git a/docs/mcp.md b/docs/mcp.md index 41d518456..78c3082cd 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -3514,9 +3514,12 @@ Actions panel plays an action as a `command.batch`, omitting steps whose playbac cleared. An action set saved as `.vcactions` keeps each excluded step with `excluded: true`; loading an earlier version 1 set without that flag includes every step. The Actions panel menu's Batch… runs `action.batch`: the same steps on every readable file in a folder (or every data set of the open document), with -destination `none` | `saveAndClose` | `folder` and Override Open / Save / Export. A Data Sets source does not -take `saveAndClose`: `action.batch` refuses it before it selects a data set or runs a step, and the dialog offers -None and Folder only. For a Data Sets source, +destination `none` | `saveAndClose` | `folder` and Override Open / Save / Export. With a Data Sets source, +`saveAndClose` saves the open document over its own file after each data set, so the file keeps only the last one, +and a document that was never saved is refused before a data set is selected. The result carries `warning` when +every data set saves over the same file: with `saveAndClose`, or with a Save, Save a Copy, Save as Template or +Export step that writes a file and that the batch does not point into `destinationFolder`. The dialog shows the same +warning. For a Data Sets source, `datasetFileNaming?: fileNumber | fileDataSetName | dataSetName` chooses File + Number (`source001`), File + Data Set Name (`source_Alpha`), or Data Set Name (`Alpha`). An omitted parameter keeps File + Data Set Name for existing callers; the dialog starts with File + Number. A folder source ignores this parameter. The folder diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index 470d36886..ac4da65b5 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -643,7 +643,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - Actions panel: the panel menu's Duplicate copies the selected action, else the current action set with all its actions ([Actions panel overview](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/actions-panel-overview.html); `ui.actionSet.duplicate`). VectorCraft's own rules, which the overview does not cover: the copy goes right after the original, is named after it with " copy" added and is selected. - Batch… over data sets names each file after the document and the data set (`action.batch`). It writes `/`, `\`, `:`, `<`, `>`, `"`, `|`, `?`, `*` and control characters in the data set's name as `-`, and adds `-2`, `-3`… to a name an earlier data set used. - Batch… offers File + Number, File + Data Set Name, and Data Set Name for a Data Sets source. The dialog defaults to File + Number; `action.batch` without `datasetFileNaming` keeps File + Data Set Name. An output already in a destination folder the batch may read and write gets the next free `-2`, `-3` suffix. [Batch options](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/batch-options.html). - - Batch… over data sets offers None and Folder as the destination, and `action.batch` refuses Save and Close for a Data Sets source before it runs a step, so the batch does not save every data set over the open document's file. This is VectorCraft's own rule: [Play actions on a batch of files](https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/play-actions-on-a-batch-of-files.html) describes Save and Close as saving "the file in their current location" and does not say what it does over data sets. + - Batch… over data sets offers None, Save and Close and Folder as the destination, as for a folder source. Save and Close saves the open document over its own file after each data set, so the file keeps only the last data set. A recorded Save, Save a Copy, Save as Template or Export step that writes a file and that the batch does not point into the destination folder (destination None, Override Save or Override Export off, or a copy or template step) also writes the same file for every data set. In either case the dialog shows a warning and `action.batch` returns a `warning`. `action.batch` refuses Save and Close over the data sets of a document that was never saved. - Export for Screens: the dialog's Example line shows the path of the file the export writes first, sub-folder included, named as the export names it, for the first chosen artboard, asset, layer or object (`document.exportForScreens`). - Export presets: the Asset Export panel menu lists the export presets of Export for Screens, with Import Preset… and Export Preset…, which read and write `.vcexportpresets` files (`document.exportPresets.import`, `document.exportPresets.export`). An imported preset whose name is taken gets a number. In the panel, a preset applies to the shared export settings (`assets.settings.set {exportPreset}`), and Save Preset… saves them. With Create Sub-folders off, the panel's Export writes every file into the folder itself, mobile and density rows included. - Export for Screens is laid out as the reference app's dialog: on the left the Artboards and Assets tabs (thumbnails with their checkboxes, number and name, in a grid or a list), Clear Selection and Prefix; on the right Select (All, Range, Include Bleed, Include Artboard Fill, Full Document), Export to, Open Location after Export, Create Sub-folders by Scale or by Format (on by default), Export PDFs As (Single File writes the chosen artboards as the pages of one PDF named after the document, `pdfs: "single"`), and the format rows with the iOS and Android buttons, the format presets (☰) and Format Settings; under them, how many items are selected and how many files the export writes. File name patterns, the Layers and Selection sources and per-item folders stay available through `document.exportForScreens` (scripts and MCP). Tests: `dialogs::tests_screens` (layout, iOS/Android, Clear Selection, sub-folders, Single File) and `fileio::tests_screens::single_file_pdfs_hold_every_chosen_artboard`.