mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-14 19:26:56 -04:00
Align, Reflect and Shear: object.align needs a direction; unknown choices are errors
object.align with neither horizontal nor vertical returned success and moved nothing. The command palette, and a key bound to it in Keyboard Shortcuts, run it with no params. It now returns "give horizontal or vertical", as object.distribute already did. An action recorded while Align ran from the palette or a bound key contains an object.align step with no params. Playing that action now fails at that step, and command.batch rolls back the whole action. Values outside a parameter's choices were read as another choice or ignored. Align ignored an unknown horizontal or vertical and aligned to the selection for an unknown to value. Distribute read an unknown direction as center. Distribute Spacing and Shear read any axis other than "vertical" as horizontal, and Reflect read any axis other than "horizontal" or a number as vertical. A bounds or to value that was not a string fell back to the default, and a spacing that was not a number gave automatic spacing. The commands now return an error that names such a value, before they move anything or record an undo step. When a to, bounds, axis or spacing value is missing or null, the command uses the parameter's default: Distribute Spacing without an axis spaces the objects horizontally. The run_command description and docs/mcp.md showed object.align with an align param it does not have; they now use horizontal. The new status-bar messages have rows in the de, es, fr, it, ja, ru and uk catalogs. Docs: docs/mcp.md, docs/target-app-parity.md.
This commit is contained in:
1 parent
0ff9e35374
commit
a2abe63e8d
15 files changed
+231
-14
No files matched your search
@@ -363,7 +363,12 @@ fn reflect(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let t = -n.as_f64().unwrap_or(90.0).to_radians();
|
||||
Affine::rotate(t) * Affine::scale_non_uniform(1.0, -1.0) * Affine::rotate(-t)
|
||||
}
|
||||
_ => Affine::scale_non_uniform(-1.0, 1.0),
|
||||
None | Some(Value::Null) => Affine::scale_non_uniform(-1.0, 1.0),
|
||||
Some(Value::String(a)) if a == "vertical" => Affine::scale_non_uniform(-1.0, 1.0),
|
||||
Some(v) => {
|
||||
let given = v.as_str().map_or_else(|| v.to_string(), str::to_string);
|
||||
return Err(bad("object.reflect", format!("axis must be \"vertical\", \"horizontal\" or an angle in degrees, not `{given}`")));
|
||||
}
|
||||
};
|
||||
apply_transform(s, "Reflect", ids, about(o, m), p)
|
||||
}
|
||||
@@ -372,8 +377,8 @@ fn shear(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = selected_roots(s)?;
|
||||
let o = origin_of(s, p, &ids)?;
|
||||
let t = f64_or(p, "angle", 0.0).clamp(-89.0, 89.0).to_radians().tan();
|
||||
let m =
|
||||
if str_param(p, "axis") == Some("vertical") { Affine::new([1.0, t, 0.0, 1.0, 0.0, 0.0]) } else { Affine::new([1.0, 0.0, -t, 1.0, 0.0, 0.0]) };
|
||||
let vertical = choice(p, "object.shear", "axis", &["horizontal", "vertical"])? == Some("vertical");
|
||||
let m = if vertical { Affine::new([1.0, t, 0.0, 1.0, 0.0, 0.0]) } else { Affine::new([1.0, 0.0, -t, 1.0, 0.0, 0.0]) };
|
||||
apply_transform(s, "Shear", ids, about(o, m), p)
|
||||
}
|
||||
|
||||
@@ -936,14 +941,35 @@ impl Session {
|
||||
|
||||
/// Measure with preview (visual) bounds? The `bounds` param, else Use Preview Bounds.
|
||||
fn preview_bounds(s: &Session, p: &Value, cmd: &str) -> Result<bool> {
|
||||
match str_param(p, "bounds") {
|
||||
match choice(p, cmd, "bounds", &["preview", "geometric"])? {
|
||||
None => Ok(s.prefs.use_preview_bounds),
|
||||
Some("preview") => Ok(true),
|
||||
Some("geometric") => Ok(false),
|
||||
Some(b) => Err(bad(cmd, format!("bounds must be \"preview\" or \"geometric\", not `{b}`"))),
|
||||
Some(b) => Ok(b == "preview"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Param `key` of the Align commands and Shear: one of `values`, or `None` when it is missing or
|
||||
/// null. Any other value is an error that lists `values` and names the value given.
|
||||
fn choice<'a>(p: &'a Value, cmd: &str, key: &str, values: &[&str]) -> Result<Option<&'a str>> {
|
||||
let Some(v) = p.get(key).filter(|v| !v.is_null()) else { return Ok(None) };
|
||||
match v.as_str() {
|
||||
Some(s) if values.contains(&s) => Ok(Some(s)),
|
||||
s => {
|
||||
let quoted: Vec<String> = values.iter().map(|value| format!("\"{value}\"")).collect();
|
||||
let list = match quoted.split_last() {
|
||||
Some((last, rest)) if !rest.is_empty() => format!("{} or {last}", rest.join(", ")),
|
||||
_ => quoted.concat(),
|
||||
};
|
||||
let given = s.map_or_else(|| v.to_string(), str::to_string);
|
||||
Err(bad(cmd, format!("{key} must be {list}, not `{given}`")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `horizontal` and `vertical` of `object.align` and `object.distribute`, each checked by [`choice`].
|
||||
fn direction<'a>(p: &'a Value, cmd: &str) -> Result<(Option<&'a str>, Option<&'a str>)> {
|
||||
Ok((choice(p, cmd, "horizontal", &["left", "center", "right"])?, choice(p, cmd, "vertical", &["top", "center", "bottom"])?))
|
||||
}
|
||||
|
||||
/// `ids` with their bounds (`preview`: visual bounds).
|
||||
fn items_bounds(d: &Document, ids: &[NodeId], preview: bool) -> Vec<(NodeId, Rect)> {
|
||||
ids.iter().filter_map(|id| Some((*id, d.bounds_of(&[*id], preview)?))).collect()
|
||||
@@ -992,9 +1018,12 @@ fn key_root(s: &Session, ids: &[NodeId]) -> Option<NodeId> {
|
||||
fn align(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = selected_roots(s)?;
|
||||
let preview = preview_bounds(s, p, "object.align")?;
|
||||
let (h, v) = direction(p, "object.align")?;
|
||||
choice(p, "object.align", "to", &["selection", "artboard", "key"])?;
|
||||
if h.is_none() && v.is_none() {
|
||||
return Err(bad("object.align", "give horizontal or vertical"));
|
||||
}
|
||||
let r = reference_rect(s, p, &ids, preview)?;
|
||||
let h = str_param(p, "horizontal");
|
||||
let v = str_param(p, "vertical");
|
||||
let key = key_root(s, &ids);
|
||||
let moves: Vec<(NodeId, Vec2)> = {
|
||||
let d = &s.doc()?.doc;
|
||||
@@ -1037,7 +1066,7 @@ fn distribute(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = selected_roots(s)?;
|
||||
let preview = preview_bounds(s, p, "object.distribute")?;
|
||||
let mut items = items_bounds(&s.doc()?.doc, &ids, preview);
|
||||
let (horiz, key): (bool, fn(&Rect, bool) -> f64) = match (str_param(p, "horizontal"), str_param(p, "vertical")) {
|
||||
let (horiz, key): (bool, fn(&Rect, bool) -> f64) = match direction(p, "object.distribute")? {
|
||||
(Some(h), _) => (
|
||||
true,
|
||||
match h {
|
||||
@@ -1089,7 +1118,7 @@ fn distribute(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
fn distribute_spacing(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let ids = selected_roots(s)?;
|
||||
let horiz = str_param(p, "axis") != Some("vertical");
|
||||
let horiz = choice(p, "object.distributeSpacing", "axis", &["horizontal", "vertical"])? != Some("vertical");
|
||||
let preview = preview_bounds(s, p, "object.distributeSpacing")?;
|
||||
let mut items = items_bounds(&s.doc()?.doc, &ids, preview);
|
||||
items.sort_by(|a, b| if horiz { a.1.x0.total_cmp(&b.1.x0) } else { a.1.y0.total_cmp(&b.1.y0) });
|
||||
@@ -1099,7 +1128,11 @@ fn distribute_spacing(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
};
|
||||
let size = |r: &Rect| if horiz { r.width() } else { r.height() };
|
||||
let start = |r: &Rect| if horiz { r.x0 } else { r.y0 };
|
||||
let spacing = p.get("spacing").and_then(Value::as_f64).filter(|g| g.is_finite());
|
||||
let spacing = p
|
||||
.get("spacing")
|
||||
.filter(|v| !v.is_null())
|
||||
.map(|v| v.as_f64().filter(|g| g.is_finite()).ok_or_else(|| bad("object.distributeSpacing", format!("spacing must be a number, not `{v}`"))))
|
||||
.transpose()?;
|
||||
let gap = match spacing {
|
||||
Some(g) => g,
|
||||
None => {
|
||||
|
||||
@@ -381,6 +381,64 @@ fn clipping_and_compound() {
|
||||
assert_eq!(s.doc().unwrap().selection.objects, vec![b]);
|
||||
}
|
||||
|
||||
/// `object.align` without `horizontal` or `vertical` (an unknown key such as `align` counts as
|
||||
/// neither) returns an error: nothing moves, and the undo and redo stacks stay as they were.
|
||||
#[test]
|
||||
fn align_without_a_direction_is_refused() {
|
||||
let mut s = session();
|
||||
let a = rect(&mut s, 0.0, 0.0, 10.0, 10.0);
|
||||
let b = rect(&mut s, 50.0, 30.0, 10.0, 10.0);
|
||||
s.execute("select.set", &json!({"ids": [a.0, b.0]})).unwrap();
|
||||
s.execute("object.move", &json!({"dx": 5, "dy": 0})).unwrap();
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
let stacks = |s: &Session| (s.doc().unwrap().history.undo.len(), s.doc().unwrap().history.redo.len());
|
||||
let before = stacks(&s);
|
||||
for p in [json!({}), json!({"align": "left"}), json!({"to": "artboard"}), json!({"horizontal": null, "vertical": null})] {
|
||||
let e = s.execute("object.align", &p).expect_err(&p.to_string());
|
||||
assert_eq!(e.to_string(), "invalid parameters for `object.align`: give horizontal or vertical", "{p}");
|
||||
}
|
||||
assert_eq!(stacks(&s), before, "no undo step, and the redo step is kept");
|
||||
assert_eq!(s.doc().unwrap().doc.node(b).unwrap().geometric_bounds().unwrap().x0, 50.0, "nothing moved");
|
||||
}
|
||||
|
||||
/// Align, Distribute and Distribute Spacing return an error that names a value outside their
|
||||
/// choices: nothing moves and no undo step is recorded. A null value counts as not given, and
|
||||
/// Distribute Spacing without an `axis` spaces the objects horizontally.
|
||||
#[test]
|
||||
fn align_and_distribute_reject_bad_params_without_changing_state() {
|
||||
let mut s = session();
|
||||
let ids: Vec<NodeId> = [0.0, 50.0, 200.0].into_iter().map(|x| rect(&mut s, x, x / 2.0, 10.0, 10.0)).collect();
|
||||
s.execute("select.set", &json!({"ids": ids.iter().map(|id| id.0).collect::<Vec<_>>()})).unwrap();
|
||||
let bounds = |s: &Session| ids.iter().map(|id| s.doc().unwrap().doc.node(*id).unwrap().geometric_bounds().unwrap()).collect::<Vec<_>>();
|
||||
let before = bounds(&s);
|
||||
let undo = s.doc().unwrap().history.undo.len();
|
||||
let h = "horizontal must be \"left\", \"center\" or \"right\"";
|
||||
let v = "vertical must be \"top\", \"center\" or \"bottom\"";
|
||||
for (cmd, p, msg) in [
|
||||
("object.align", json!({"horizontal": "middle"}), format!("{h}, not `middle`")),
|
||||
("object.align", json!({"vertical": "centre"}), format!("{v}, not `centre`")),
|
||||
("object.align", json!({"horizontal": true}), format!("{h}, not `true`")),
|
||||
("object.align", json!({"horizontal": "left", "to": "page"}), "to must be \"selection\", \"artboard\" or \"key\", not `page`".into()),
|
||||
("object.align", json!({"horizontal": "left", "to": 0}), "to must be \"selection\", \"artboard\" or \"key\", not `0`".into()),
|
||||
("object.align", json!({"horizontal": "left", "bounds": false}), "bounds must be \"preview\" or \"geometric\", not `false`".into()),
|
||||
("object.align", json!({"horizontal": "left", "vertical": "middle"}), format!("{v}, not `middle`")),
|
||||
("object.distribute", json!({"horizontal": "middle"}), format!("{h}, not `middle`")),
|
||||
("object.distribute", json!({"vertical": "centre"}), format!("{v}, not `centre`")),
|
||||
("object.distribute", json!({"horizontal": "left", "vertical": "middle"}), format!("{v}, not `middle`")),
|
||||
("object.distributeSpacing", json!({"axis": "diagonal"}), "axis must be \"horizontal\" or \"vertical\", not `diagonal`".into()),
|
||||
("object.distributeSpacing", json!({"axis": "vertical", "spacing": "5"}), "spacing must be a number, not `\"5\"`".into()),
|
||||
] {
|
||||
let e = s.execute(cmd, &p).expect_err(&format!("{cmd} {p}"));
|
||||
assert_eq!(e.to_string(), format!("invalid parameters for `{cmd}`: {msg}"));
|
||||
}
|
||||
assert_eq!(bounds(&s), before, "nothing moved");
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), undo, "no undo step");
|
||||
s.execute("object.align", &json!({"horizontal": null, "vertical": "top", "to": null, "bounds": null})).unwrap();
|
||||
assert!(bounds(&s).iter().all(|b| b.y0 == 0.0), "aligned to the top");
|
||||
s.execute("object.distributeSpacing", &json!({"axis": null, "spacing": null})).unwrap();
|
||||
assert_eq!(bounds(&s).iter().map(|b| b.x0).collect::<Vec<_>>(), [0.0, 100.0, 200.0], "equal horizontal gaps");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn align_left() {
|
||||
let mut s = session();
|
||||
|
||||
@@ -104,6 +104,37 @@ fn reflect_and_shear_tools() {
|
||||
assert!((b.width() - 150.0).abs() < 1e-6, "{b:?}");
|
||||
}
|
||||
|
||||
/// Reflect and Shear return an error that names an `axis` they don't take (Reflect also takes an
|
||||
/// angle): nothing moves and no undo step is recorded. A null `axis` counts as not given: Reflect
|
||||
/// then reflects across the vertical axis and Shear shears along the horizontal one.
|
||||
#[test]
|
||||
fn reflect_and_shear_reject_unknown_axes_without_changing_state() {
|
||||
let mut s = session();
|
||||
let a = rect(&mut s, 10.0, 20.0, 30.0, 10.0);
|
||||
let n = undo_len(&s);
|
||||
let reflect = "axis must be \"vertical\", \"horizontal\" or an angle in degrees";
|
||||
let shear = "axis must be \"horizontal\" or \"vertical\"";
|
||||
for (cmd, p, msg) in [
|
||||
("object.reflect", json!({"axis": "diagonal", "origin": [0, 0]}), format!("{reflect}, not `diagonal`")),
|
||||
("object.reflect", json!({"axis": "45", "origin": [0, 0]}), format!("{reflect}, not `45`")),
|
||||
("object.reflect", json!({"axis": true, "origin": [0, 0]}), format!("{reflect}, not `true`")),
|
||||
("object.shear", json!({"angle": 30, "axis": "diagonal"}), format!("{shear}, not `diagonal`")),
|
||||
("object.shear", json!({"angle": 30, "axis": 90}), format!("{shear}, not `90`")),
|
||||
] {
|
||||
let e = s.execute(cmd, &p).expect_err(&format!("{cmd} {p}"));
|
||||
assert_eq!(e.to_string(), format!("invalid parameters for `{cmd}`: {msg}"));
|
||||
}
|
||||
assert!(close(bounds(&s, a), Rect::new(10.0, 20.0, 40.0, 30.0)), "nothing moved: {:?}", bounds(&s, a));
|
||||
assert_eq!(undo_len(&s), n, "no undo step");
|
||||
s.execute("object.reflect", &json!({"axis": null, "origin": [0, 0]})).unwrap();
|
||||
assert!(close(bounds(&s, a), Rect::new(-40.0, 20.0, -10.0, 30.0)), "across the vertical axis: {:?}", bounds(&s, a));
|
||||
s.execute("object.reflect", &json!({"axis": 0, "origin": [0, 0]})).unwrap();
|
||||
assert!(close(bounds(&s, a), Rect::new(-40.0, -30.0, -10.0, -20.0)), "an angle still reflects: {:?}", bounds(&s, a));
|
||||
s.execute("object.shear", &json!({"angle": 45, "axis": null, "origin": [0, 0]})).unwrap();
|
||||
let b = bounds(&s, a);
|
||||
assert!((b.y0 + 30.0).abs() < 1e-6 && (b.y1 + 20.0).abs() < 1e-6 && b.width() > 30.0, "along the horizontal axis: {b:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn distort_command_maps_corners() {
|
||||
let mut s = session();
|
||||
|
||||
@@ -321,6 +321,9 @@ fn structured_junk() {
|
||||
("object.setBounds", json!({"width": 0, "height": 0})),
|
||||
("object.setBounds", json!({"width": -10, "height": 1e308, "reference": 99})),
|
||||
("object.distributeSpacing", json!({"axis": "horizontal", "spacing": -1e308})),
|
||||
("object.distributeSpacing", json!({"axis": "vertical", "spacing": 0})),
|
||||
("object.align", json!({"horizontal": "center", "vertical": "center", "to": "artboard", "bounds": "preview"})),
|
||||
("object.distribute", json!({"vertical": "center", "bounds": "geometric"})),
|
||||
("artboard.setProps", json!({"index": 0, "width": -1, "height": 0})),
|
||||
("artboard.setProps", json!({"index": 0, "width": 1e300, "height": 1e-300, "scaleArt": true, "strokes": true, "corners": true})),
|
||||
("artboard.setProps", json!({"index": 0, "x": -1e308, "width": 0, "height": 1, "scaleArt": true, "patterns": true})),
|
||||
|
||||
@@ -138,7 +138,7 @@ pub fn tool_definitions() -> Vec<Value> {
|
||||
tool(
|
||||
"run_command",
|
||||
"Run command",
|
||||
"Execute any VectorCraft command by id with JSON params (see list_commands for ids and params). Examples: {\"command\":\"object.group\"}, {\"command\":\"object.align\",\"params\":{\"align\":\"left\"}}, {\"command\":\"file.new\",\"params\":{\"width\":800,\"height\":600}}. Returns the command's result (e.g. {id} for creation commands).",
|
||||
"Execute any VectorCraft command by id with JSON params (see list_commands for ids and params). Examples: {\"command\":\"object.group\"}, {\"command\":\"object.align\",\"params\":{\"horizontal\":\"left\"}}, {\"command\":\"file.new\",\"params\":{\"width\":800,\"height\":600}}. Returns the command's result (e.g. {id} for creation commands).",
|
||||
obj(
|
||||
json!({"command": string("Command id, e.g. shape.rectangle, object.group, paint.setFill"), "params": {"type": "object", "description": "Command parameters"}}),
|
||||
&["command"],
|
||||
|
||||
@@ -3384,6 +3384,8 @@ theme Appearance Erscheinungsbild
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}`: none, art oder type
|
||||
@msg artboard {0} does not exist Zeichenfläche {0} ist nicht vorhanden
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard in diesem Maßstab misst die Zeichnung {w} × {h} pt, mehr als die Arbeitsfläche fasst: Wählen Sie einen kleineren Maßstab oder passen Sie sie an die Zeichenfläche an
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis muss "horizontal" oder "vertical" sein, nicht `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis muss "vertical", "horizontal" oder ein Winkel in Grad sein, nicht `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" background {other}: transparent, white, black oder eine Farbe wie "#ff8800"
|
||||
@msg bad color {v} ungültige Farbe {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) ungültige Farbe `{hex}` (#rrggbb)
|
||||
@@ -3393,6 +3395,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg bad trailer fehlerhafter Trailer
|
||||
@msg balance must be between 0 and 100 balance muss zwischen 0 und 100 liegen
|
||||
@msg batch step {_1} (`{id}`) failed: {e} Stapelschritt {_1} (`{id}`) ist fehlgeschlagen: {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds muss "preview" oder "geometric" sein, nicht `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light brightness muss dark|mediumDark|mediumLight|light sein
|
||||
@msg can't encode the document: {0} das Dokument kann nicht kodiert werden: {0}
|
||||
@msg can't parse shortcut `{c}` Tastaturbefehl `{c}` kann nicht ausgewertet werden
|
||||
@@ -3426,8 +3429,10 @@ theme Appearance Erscheinungsbild
|
||||
@msg freeform line {i} must be an array of point indices Freiformlinie {i} muss ein Array von Punktindizes sein
|
||||
@msg give both `start` and `end` [x, y] (or neither) geben Sie sowohl `start` als auch `end` [x, y] an (oder keines von beiden)
|
||||
@msg give corners of the path: anchors between two straight sides geben Sie Ecken des Pfads an: Ankerpunkte zwischen zwei geraden Seiten
|
||||
@msg give horizontal or vertical geben Sie horizontal oder vertical an
|
||||
@msg give the path `id` and the width point `index` geben Sie die `id` des Pfads und den `index` des Breitenpunkts an
|
||||
@msg guides are locked die Hilfslinien sind gesperrt
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal muss "left", "center" oder "right" sein, nicht `{v}`
|
||||
@msg image '{key}' has no pixels and was left out das Bild '{key}' hat keine Pixel und wurde ausgelassen
|
||||
@msg image data `{_1}` is missing die Bilddaten `{_1}` fehlen
|
||||
@msg image would be too large; lower the resolution das Bild wäre zu groß; verringern Sie die Auflösung
|
||||
@@ -3628,6 +3633,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg shadings of more than 4096 patches or triangles were left out Schattierungen mit mehr als 4096 Teilflächen oder Dreiecken wurden ausgelassen
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour Schattierungen, deren Funktionen einen unbekannten Typ haben, werden mit ihrer mittleren Farbe gefüllt
|
||||
@msg shortcut for `{k}` must be a string der Tastaturbefehl für `{k}` muss eine Zeichenfolge sein
|
||||
@msg spacing must be a number, not `{v}` spacing muss eine Zahl sein, nicht `{v}`
|
||||
@msg stop {i} needs `offset` Farbstopp {i} braucht `offset`
|
||||
@msg stop {i} needs a valid `color` Farbstopp {i} braucht eine gültige `color`
|
||||
@msg stop {i}: `{k}` must be a number Farbstopp {i}: `{k}` muss eine Zahl sein
|
||||
@@ -3695,6 +3701,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that dies ist eine DWG-Zeichnung, die nicht gelesen werden kann: Speichern Sie sie in der CAD-App als ASCII-DXF und öffnen Sie diese Datei
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG dies ist eine PostScript-Datei (eine .ai-Datei in einem älteren Format oder ohne PDF-Kompatibilität oder eine EPS-Datei), die noch nicht geöffnet werden kann: Speichern Sie sie als PDF, als PDF-kompatible .ai-Datei oder als SVG
|
||||
@msg this is not a PostScript file dies ist keine PostScript-Datei
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to muss "selection", "artboard" oder "key" sein, nicht `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) Tastaturbefehle für Werkzeuge müssen aus einer einzelnen Taste bestehen (optional mit Shift)
|
||||
@msg truncated abgeschnitten
|
||||
@msg unknown command `{0}` unbekannter Befehl `{0}`
|
||||
@@ -3719,6 +3726,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg unknown workspace (one of {_1}) unbekannter Arbeitsbereich (einer von {_1})
|
||||
@msg unsupported: {0} nicht unterstützt: {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files Dateien der Version {0} können nicht komprimiert werden: Erst Version {COMPRESSED_SINCE} und neuer öffnen komprimierte Dateien
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical muss "top", "center" oder "bottom" sein, nicht `{v}`
|
||||
@msg width and height are at least 1 pixel Breite und Höhe betragen mindestens 1 Pixel
|
||||
@msg workspace name can't be empty der Name des Arbeitsbereichs darf nicht leer sein
|
||||
@msg {C}: no effect at index {from} {C}: kein Effekt bei Index {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3485,6 +3485,8 @@ axis Both Ambos
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}`: none, art o type
|
||||
@msg artboard {0} does not exist la mesa de trabajo {0} no existe
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard a esta escala el dibujo mide {w} × {h} pt, más de lo que cabe en el lienzo: elige una escala menor o ajústalo a la mesa de trabajo
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis debe ser "horizontal" o "vertical", no `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis debe ser "vertical", "horizontal" o un ángulo en grados, no `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" fondo {other}: transparent, white, black o un color como "#ff8800"
|
||||
@msg bad color {v} color no válido {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) color no válido `{hex}` (#rrggbb)
|
||||
@@ -3494,6 +3496,7 @@ axis Both Ambos
|
||||
@msg bad trailer trailer no válido
|
||||
@msg balance must be between 0 and 100 el equilibrio debe estar entre 0 y 100
|
||||
@msg batch step {_1} (`{id}`) failed: {e} falló el paso {_1} del lote (`{id}`): {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds debe ser "preview" o "geometric", no `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light el brillo debe ser dark|mediumDark|mediumLight|light
|
||||
@msg can't encode the document: {0} no se puede codificar el documento: {0}
|
||||
@msg can't parse shortcut `{c}` no se puede interpretar el atajo `{c}`
|
||||
@@ -3527,8 +3530,10 @@ axis Both Ambos
|
||||
@msg freeform line {i} must be an array of point indices la línea de forma libre {i} debe ser una lista de índices de puntos
|
||||
@msg give both `start` and `end` [x, y] (or neither) indica `start` y `end` [x, y] (o ninguno de los dos)
|
||||
@msg give corners of the path: anchors between two straight sides indica esquinas del trazado: puntos de ancla entre dos lados rectos
|
||||
@msg give horizontal or vertical indica horizontal o vertical
|
||||
@msg give the path `id` and the width point `index` indica el `id` del trazado y el `index` del punto de anchura
|
||||
@msg guides are locked las guías están bloqueadas
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal debe ser "left", "center" o "right", no `{v}`
|
||||
@msg image '{key}' has no pixels and was left out la imagen '{key}' no tiene píxeles y se omitió
|
||||
@msg image data `{_1}` is missing faltan los datos de imagen `{_1}`
|
||||
@msg image would be too large; lower the resolution la imagen sería demasiado grande; baja la resolución
|
||||
@@ -3728,6 +3733,7 @@ axis Both Ambos
|
||||
@msg shadings of more than 4096 patches or triangles were left out se omitieron los sombreados de más de 4096 parches o triángulos
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour los sombreados cuyas funciones son de tipo desconocido se rellenan con su color intermedio
|
||||
@msg shortcut for `{k}` must be a string el atajo de `{k}` debe ser un texto
|
||||
@msg spacing must be a number, not `{v}` spacing debe ser un número, no `{v}`
|
||||
@msg stop {i} needs `offset` la parada {i} necesita `offset`
|
||||
@msg stop {i} needs a valid `color` la parada {i} necesita un `color` válido
|
||||
@msg stop {i}: `{k}` must be a number parada {i}: `{k}` debe ser un número
|
||||
@@ -3795,6 +3801,7 @@ axis Both Ambos
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that este es un dibujo DWG, que no se puede leer: guárdalo desde la aplicación de CAD como DXF ASCII y abre ese archivo
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG este es un archivo PostScript (un .ai guardado en un formato antiguo o sin compatibilidad con PDF, o un archivo EPS), que todavía no se puede abrir: guárdalo como PDF, .ai compatible con PDF o SVG
|
||||
@msg this is not a PostScript file este no es un archivo PostScript
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to debe ser "selection", "artboard" o "key", no `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) los atajos de herramientas deben ser una sola tecla (opcionalmente con Shift)
|
||||
@msg truncated truncado
|
||||
@msg unknown command `{0}` comando desconocido `{0}`
|
||||
@@ -3819,6 +3826,7 @@ axis Both Ambos
|
||||
@msg unknown workspace (one of {_1}) espacio de trabajo desconocido (uno de estos: {_1})
|
||||
@msg unsupported: {0} no compatible: {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files los archivos de la versión {0} no se pueden comprimir: solo la versión {COMPRESSED_SINCE} y posteriores abren archivos comprimidos
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical debe ser "top", "center" o "bottom", no `{v}`
|
||||
@msg width and height are at least 1 pixel el ancho y el alto son de al menos 1 píxel
|
||||
@msg workspace name can't be empty el nombre del espacio de trabajo no puede estar vacío
|
||||
@msg {C}: no effect at index {from} {C}: no hay ningún efecto en el índice {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3482,6 +3482,8 @@ axis Both Les deux
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}` : none, art ou type
|
||||
@msg artboard {0} does not exist le plan de travail {0} n’existe pas
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard à cette échelle, le dessin mesure {w} × {h} pt, plus que ne peut contenir la zone de travail : choisissez une échelle plus petite ou ajustez-le au plan de travail
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis doit être "horizontal" ou "vertical", pas `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis doit être "vertical", "horizontal" ou un angle en degrés, pas `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" arrière-plan {other} : transparent, white, black ou une couleur comme "#ff8800"
|
||||
@msg bad color {v} couleur non valide {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) couleur non valide `{hex}` (#rrggbb)
|
||||
@@ -3491,6 +3493,7 @@ axis Both Les deux
|
||||
@msg bad trailer trailer non valide
|
||||
@msg balance must be between 0 and 100 l’équilibre doit être compris entre 0 et 100
|
||||
@msg batch step {_1} (`{id}`) failed: {e} l’étape {_1} du lot (`{id}`) a échoué : {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds doit être "preview" ou "geometric", pas `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light la luminosité doit valoir dark|mediumDark|mediumLight|light
|
||||
@msg can't encode the document: {0} impossible d’encoder le document : {0}
|
||||
@msg can't parse shortcut `{c}` impossible d’interpréter le raccourci `{c}`
|
||||
@@ -3524,8 +3527,10 @@ axis Both Les deux
|
||||
@msg freeform line {i} must be an array of point indices la ligne de forme libre {i} doit être un tableau d’indices de points
|
||||
@msg give both `start` and `end` [x, y] (or neither) indiquez à la fois `start` et `end` [x, y] (ou aucun des deux)
|
||||
@msg give corners of the path: anchors between two straight sides indiquez des angles du tracé : des points d’ancrage entre deux côtés droits
|
||||
@msg give horizontal or vertical indiquez horizontal ou vertical
|
||||
@msg give the path `id` and the width point `index` indiquez l’`id` du tracé et l’`index` du point de largeur
|
||||
@msg guides are locked les repères sont verrouillés
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal doit être "left", "center" ou "right", pas `{v}`
|
||||
@msg image '{key}' has no pixels and was left out l’image « {key} » n’a aucun pixel et a été ignorée
|
||||
@msg image data `{_1}` is missing les données d’image `{_1}` sont manquantes
|
||||
@msg image would be too large; lower the resolution l’image serait trop grande ; réduisez la résolution
|
||||
@@ -3725,6 +3730,7 @@ axis Both Les deux
|
||||
@msg shadings of more than 4096 patches or triangles were left out les ombrages de plus de 4096 carreaux ou triangles ont été ignorés
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour les ombrages dont les fonctions sont de type inconnu sont remplis de leur couleur médiane
|
||||
@msg shortcut for `{k}` must be a string le raccourci de `{k}` doit être une chaîne
|
||||
@msg spacing must be a number, not `{v}` spacing doit être un nombre, pas `{v}`
|
||||
@msg stop {i} needs `offset` le point de couleur {i} nécessite `offset`
|
||||
@msg stop {i} needs a valid `color` le point de couleur {i} nécessite une `color` valide
|
||||
@msg stop {i}: `{k}` must be a number point de couleur {i} : `{k}` doit être un nombre
|
||||
@@ -3792,6 +3798,7 @@ axis Both Les deux
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that c’est un dessin DWG, qui ne peut pas être lu : enregistrez-le depuis l’application de CAO au format DXF ASCII et ouvrez ce fichier
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG c’est un fichier PostScript (un .ai enregistré dans un ancien format ou sans compatibilité PDF, ou un fichier EPS), qui ne peut pas encore être ouvert : enregistrez-le au format PDF, .ai compatible PDF ou SVG
|
||||
@msg this is not a PostScript file ce n’est pas un fichier PostScript
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to doit être "selection", "artboard" ou "key", pas `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) les raccourcis d’outils doivent être une seule touche (éventuellement avec Maj)
|
||||
@msg truncated tronqué
|
||||
@msg unknown command `{0}` commande inconnue `{0}`
|
||||
@@ -3816,6 +3823,7 @@ axis Both Les deux
|
||||
@msg unknown workspace (one of {_1}) espace de travail inconnu (valeurs possibles : {_1})
|
||||
@msg unsupported: {0} non pris en charge : {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files les fichiers de version {0} ne peuvent pas être compressés : seules les versions {COMPRESSED_SINCE} et ultérieures ouvrent les fichiers compressés
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical doit être "top", "center" ou "bottom", pas `{v}`
|
||||
@msg width and height are at least 1 pixel la largeur et la hauteur valent au moins 1 pixel
|
||||
@msg workspace name can't be empty le nom de l’espace de travail ne peut pas être vide
|
||||
@msg {C}: no effect at index {from} {C} : aucun effet à l’indice {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3485,6 +3485,8 @@ axis Both Entrambi
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}`: none, art o type
|
||||
@msg artboard {0} does not exist la tavola da disegno {0} non esiste
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard a questa scala il disegno misura {w} × {h} pt, più di quanto possa contenere l'area di disegno: scegli una scala più piccola o adattalo alla tavola da disegno
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis deve essere "horizontal" o "vertical", non `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis deve essere "vertical", "horizontal" o un angolo in gradi, non `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" sfondo {other}: transparent, white, black o un colore come "#ff8800"
|
||||
@msg bad color {v} colore non valido {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) colore non valido `{hex}` (#rrggbb)
|
||||
@@ -3494,6 +3496,7 @@ axis Both Entrambi
|
||||
@msg bad trailer trailer non valido
|
||||
@msg balance must be between 0 and 100 il bilanciamento deve essere compreso tra 0 e 100
|
||||
@msg batch step {_1} (`{id}`) failed: {e} il passaggio {_1} del batch (`{id}`) non è riuscito: {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds deve essere "preview" o "geometric", non `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light la luminosità deve essere dark|mediumDark|mediumLight|light
|
||||
@msg can't encode the document: {0} impossibile codificare il documento: {0}
|
||||
@msg can't parse shortcut `{c}` impossibile interpretare la scelta rapida `{c}`
|
||||
@@ -3527,8 +3530,10 @@ axis Both Entrambi
|
||||
@msg freeform line {i} must be an array of point indices la linea a forma libera {i} deve essere un array di indici di punti
|
||||
@msg give both `start` and `end` [x, y] (or neither) specifica sia `start` sia `end` [x, y] (o nessuno dei due)
|
||||
@msg give corners of the path: anchors between two straight sides specifica angoli del tracciato: punti di ancoraggio tra due lati diritti
|
||||
@msg give horizontal or vertical specifica horizontal o vertical
|
||||
@msg give the path `id` and the width point `index` specifica l'`id` del tracciato e l'`index` del punto di larghezza
|
||||
@msg guides are locked le guide sono bloccate
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal deve essere "left", "center" o "right", non `{v}`
|
||||
@msg image '{key}' has no pixels and was left out l'immagine '{key}' non ha pixel ed è stata omessa
|
||||
@msg image data `{_1}` is missing mancano i dati immagine `{_1}`
|
||||
@msg image would be too large; lower the resolution l'immagine sarebbe troppo grande; riduci la risoluzione
|
||||
@@ -3728,6 +3733,7 @@ axis Both Entrambi
|
||||
@msg shadings of more than 4096 patches or triangles were left out le ombreggiature con più di 4096 patch o triangoli sono state omesse
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour le ombreggiature con funzioni di tipo sconosciuto vengono riempite con il loro colore intermedio
|
||||
@msg shortcut for `{k}` must be a string la scelta rapida per `{k}` deve essere una stringa
|
||||
@msg spacing must be a number, not `{v}` spacing deve essere un numero, non `{v}`
|
||||
@msg stop {i} needs `offset` il cursore colore {i} richiede `offset`
|
||||
@msg stop {i} needs a valid `color` il cursore colore {i} richiede un `color` valido
|
||||
@msg stop {i}: `{k}` must be a number cursore colore {i}: `{k}` deve essere un numero
|
||||
@@ -3795,6 +3801,7 @@ axis Both Entrambi
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that questo è un disegno DWG, che non può essere letto: salvalo dall'app CAD come DXF ASCII e apri quel file
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG questo è un file PostScript (un .ai salvato in un formato precedente o senza compatibilità PDF, oppure un file EPS), che non può ancora essere aperto: salvalo come PDF, .ai compatibile con PDF o SVG
|
||||
@msg this is not a PostScript file questo non è un file PostScript
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to deve essere "selection", "artboard" o "key", non `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) le scelte rapide degli strumenti devono essere un singolo tasto (eventualmente con Shift)
|
||||
@msg truncated troncato
|
||||
@msg unknown command `{0}` comando sconosciuto `{0}`
|
||||
@@ -3819,6 +3826,7 @@ axis Both Entrambi
|
||||
@msg unknown workspace (one of {_1}) area di lavoro sconosciuta (una delle seguenti: {_1})
|
||||
@msg unsupported: {0} non supportato: {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files i file della versione {0} non possono essere compressi: solo la versione {COMPRESSED_SINCE} e successive aprono file compressi
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical deve essere "top", "center" o "bottom", non `{v}`
|
||||
@msg width and height are at least 1 pixel larghezza e altezza sono di almeno 1 pixel
|
||||
@msg workspace name can't be empty il nome dell'area di lavoro non può essere vuoto
|
||||
@msg {C}: no effect at index {from} {C}: nessun effetto all'indice {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3528,6 +3528,14 @@ theme Appearance 外観
|
||||
@msg nothing to align 整列するものがありません
|
||||
@msg select a clip group クリップグループを選択してください
|
||||
@msg select two or more objects to distribute 分布させるオブジェクトを 2 つ以上選択してください
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis には "horizontal" または "vertical" を指定してください (`{v}` は指定できません)
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis には "vertical"、"horizontal"、度単位の角度のいずれかを指定してください (`{v}` は指定できません)
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds には "preview" または "geometric" を指定してください (`{v}` は指定できません)
|
||||
@msg give horizontal or vertical horizontal または vertical を指定してください
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal には "left"、"center"、"right" のいずれかを指定してください (`{v}` は指定できません)
|
||||
@msg spacing must be a number, not `{v}` spacing には数値を指定してください (`{v}` は指定できません)
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to には "selection"、"artboard"、"key" のいずれかを指定してください (`{v}` は指定できません)
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical には "top"、"center"、"bottom" のいずれかを指定してください (`{v}` は指定できません)
|
||||
@msg selection has no bounds 選択範囲に境界がありません
|
||||
@msg the top object must be a path, compound path or text object to use as a clipping mask クリッピングマスクとして使うには、最前面のオブジェクトがパス、複合パス、テキストオブジェクトのいずれかである必要があります
|
||||
@msg no target object has an opacity mask: select one or give `id` 不透明マスクのあるターゲットオブジェクトがありません: 該当するオブジェクトを選択するか、`id` を指定してください
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3481,6 +3481,8 @@ axis Both Оба
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}`: none, art или type
|
||||
@msg artboard {0} does not exist монтажная область {0} не существует
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard при этом масштабе рисунок имеет размер {w} × {h} пт, что больше холста: выберите меньший масштаб или впишите его в монтажную область
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis должно быть "horizontal" или "vertical", а не `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis должно быть "vertical", "horizontal" или углом в градусах, а не `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" фон {other}: transparent, white, black или цвет, например "#ff8800"
|
||||
@msg bad color {v} недопустимый цвет {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) недопустимый цвет `{hex}` (#rrggbb)
|
||||
@@ -3490,6 +3492,7 @@ axis Both Оба
|
||||
@msg bad trailer недопустимый трейлер
|
||||
@msg balance must be between 0 and 100 баланс должен быть от 0 до 100
|
||||
@msg batch step {_1} (`{id}`) failed: {e} шаг пакета {_1} (`{id}`) не выполнен: {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds должно быть "preview" или "geometric", а не `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light яркость должна быть dark|mediumDark|mediumLight|light
|
||||
@msg can't encode the document: {0} не удалось закодировать документ: {0}
|
||||
@msg can't parse shortcut `{c}` не удалось разобрать сочетание `{c}`
|
||||
@@ -3523,8 +3526,10 @@ axis Both Оба
|
||||
@msg freeform line {i} must be an array of point indices произвольная линия {i} должна быть массивом индексов точек
|
||||
@msg give both `start` and `end` [x, y] (or neither) укажите и `start`, и `end` [x, y] (или ни одного)
|
||||
@msg give corners of the path: anchors between two straight sides укажите углы контура: опорные точки между двумя прямыми сторонами
|
||||
@msg give horizontal or vertical укажите horizontal или vertical
|
||||
@msg give the path `id` and the width point `index` укажите `id` контура и `index` точки ширины
|
||||
@msg guides are locked направляющие заблокированы
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal должно быть "left", "center" или "right", а не `{v}`
|
||||
@msg image '{key}' has no pixels and was left out изображение '{key}' не имеет пикселей и было пропущено
|
||||
@msg image data `{_1}` is missing данные изображения `{_1}` отсутствуют
|
||||
@msg image would be too large; lower the resolution изображение было бы слишком большим; уменьшите разрешение
|
||||
@@ -3724,6 +3729,7 @@ axis Both Оба
|
||||
@msg shadings of more than 4096 patches or triangles were left out заливки с более чем 4096 фрагментов или треугольников были пропущены
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour заливки, функции которых имеют неизвестный тип, заполняются своим средним цветом
|
||||
@msg shortcut for `{k}` must be a string сочетание для `{k}` должно быть строкой
|
||||
@msg spacing must be a number, not `{v}` spacing должно быть числом, а не `{v}`
|
||||
@msg stop {i} needs `offset` точке перехода {i} нужен `offset`
|
||||
@msg stop {i} needs a valid `color` точке перехода {i} нужен допустимый `color`
|
||||
@msg stop {i}: `{k}` must be a number точка перехода {i}: `{k}` должно быть числом
|
||||
@@ -3791,6 +3797,7 @@ axis Both Оба
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that это чертёж DWG, который невозможно прочитать: сохраните его из приложения CAD как ASCII DXF и откройте его
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG это файл PostScript (.ai, сохранённый в старом формате или без совместимости с PDF, либо файл EPS), который пока невозможно открыть: сохраните его как PDF, .ai с совместимостью с PDF или SVG
|
||||
@msg this is not a PostScript file это не файл PostScript
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to должно быть "selection", "artboard" или "key", а не `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) сочетания инструментов должны быть одной клавишей (необязательно с Shift)
|
||||
@msg truncated усечено
|
||||
@msg unknown command `{0}` неизвестная команда `{0}`
|
||||
@@ -3815,6 +3822,7 @@ axis Both Оба
|
||||
@msg unknown workspace (one of {_1}) неизвестная рабочая среда (одна из: {_1})
|
||||
@msg unsupported: {0} не поддерживается: {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files файлы версии {0} не могут быть сжаты: только версия {COMPRESSED_SINCE} и новее открывают сжатые файлы
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical должно быть "top", "center" или "bottom", а не `{v}`
|
||||
@msg width and height are at least 1 pixel ширина и высота должны быть не менее 1 пикселя
|
||||
@msg workspace name can't be empty имя рабочей среды не может быть пустым
|
||||
@msg {C}: no effect at index {from} {C}: нет эффекта с индексом {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -923,6 +923,37 @@ fn complete_languages_translate_every_message() {
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameter errors of Align, Distribute Spacing, Reflect and Shear, whose text the scan above
|
||||
/// doesn't read, are translated whole in each language of [`COMPLETE_MESSAGES`].
|
||||
#[test]
|
||||
fn align_reflect_and_shear_param_errors_are_translated() {
|
||||
use serde_json::json;
|
||||
let mut s = vectorcraft_engine::Session::new();
|
||||
s.execute("file.new", &json!({})).unwrap();
|
||||
for x in [0, 50] {
|
||||
s.execute("shape.rectangle", &json!({"x": x, "y": 0, "width": 10, "height": 10})).unwrap();
|
||||
}
|
||||
s.execute("select.all", &json!({})).unwrap();
|
||||
for (cmd, p) in [
|
||||
("object.align", json!({})),
|
||||
("object.align", json!({"horizontal": "middle"})),
|
||||
("object.align", json!({"vertical": "centre"})),
|
||||
("object.align", json!({"horizontal": "left", "to": "page"})),
|
||||
("object.align", json!({"horizontal": "left", "bounds": "visual"})),
|
||||
("object.distributeSpacing", json!({"axis": "diagonal"})),
|
||||
("object.distributeSpacing", json!({"spacing": "5"})),
|
||||
("object.reflect", json!({"axis": "diagonal"})),
|
||||
("object.shear", json!({"axis": "diagonal"})),
|
||||
] {
|
||||
let e = s.execute(cmd, &p).unwrap_err();
|
||||
let vectorcraft_engine::EngineError::BadParams { msg, .. } = &e else { panic!("{cmd} {p}: {e}") };
|
||||
for code in COMPLETE_MESSAGES {
|
||||
let shown = message(Lang::from_code(code).unwrap(), &e.to_string());
|
||||
assert!(!shown.contains(msg.as_str()), "{code}: {shown}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Languages whose catalogs cover every status and error message.
|
||||
const COMPLETE_MESSAGES: &[&str] = &["de", "es", "fr", "it", "ja", "ru", "uk"];
|
||||
|
||||
|
||||
@@ -3468,6 +3468,8 @@ axis Both Обидві
|
||||
@msg antiAlias `{id}`: none, art or type antiAlias `{id}`: none, art або type
|
||||
@msg artboard {0} does not exist монтажна область {0} не існує
|
||||
@msg at this scale the drawing is {w} × {h} pt, more than the canvas holds: choose a smaller scale or fit it to the artboard при цьому масштабі малюнок має розмір {w} × {h} пт, що більше полотна: виберіть менший масштаб або впишіть його в монтажну область
|
||||
@msg axis must be "horizontal" or "vertical", not `{v}` axis має бути "horizontal" або "vertical", а не `{v}`
|
||||
@msg axis must be "vertical", "horizontal" or an angle in degrees, not `{v}` axis має бути "vertical", "horizontal" або кутом у градусах, а не `{v}`
|
||||
@msg background {other}: transparent, white, black or a colour such as "#ff8800" фон {other}: transparent, white, black або колір, наприклад "#ff8800"
|
||||
@msg bad color {v} неприпустимий колір {v}
|
||||
@msg bad colour `{hex}` (#rrggbb) неприпустимий колір `{hex}` (#rrggbb)
|
||||
@@ -3477,6 +3479,7 @@ axis Both Обидві
|
||||
@msg bad trailer неприпустимий трейлер
|
||||
@msg balance must be between 0 and 100 баланс має бути від 0 до 100
|
||||
@msg batch step {_1} (`{id}`) failed: {e} крок пакету {_1} (`{id}`) не виконано: {e}
|
||||
@msg bounds must be "preview" or "geometric", not `{v}` bounds має бути "preview" або "geometric", а не `{v}`
|
||||
@msg brightness must be dark|mediumDark|mediumLight|light яскравість має бути dark|mediumDark|mediumLight|light
|
||||
@msg can't encode the document: {0} не вдалося закодувати документ: {0}
|
||||
@msg can't parse shortcut `{c}` не вдалося розібрати поєднання `{c}`
|
||||
@@ -3510,8 +3513,10 @@ axis Both Обидві
|
||||
@msg freeform line {i} must be an array of point indices довільна лінія {i} має бути масивом індексів точок
|
||||
@msg give both `start` and `end` [x, y] (or neither) вкажіть `start`, `end` [x, y] (або жодного)
|
||||
@msg give corners of the path: anchors between two straight sides вкажіть кути контуру: опорні точки між двома прямими сторонами
|
||||
@msg give horizontal or vertical вкажіть horizontal або vertical
|
||||
@msg give the path `id` and the width point `index` вкажіть `id` контуру та `index` точки ширини
|
||||
@msg guides are locked напрямні заблоковані
|
||||
@msg horizontal must be "left", "center" or "right", not `{v}` horizontal має бути "left", "center" або "right", а не `{v}`
|
||||
@msg image '{key}' has no pixels and was left out зображення '{key}' не має пікселів і було пропущено
|
||||
@msg image data `{_1}` is missing дані зображення `{_1}` відсутні
|
||||
@msg image would be too large; lower the resolution зображення буде завеликим; зменште роздільну здатність
|
||||
@@ -3711,6 +3716,7 @@ axis Both Обидві
|
||||
@msg shadings of more than 4096 patches or triangles were left out заливки з більш ніж 4096 фрагментів або трикутників були пропущені
|
||||
@msg shadings whose functions are of an unknown type are filled with their middle colour заливки, функції яких мають невідомий тип, заповнюються своїм середнім кольором
|
||||
@msg shortcut for `{k}` must be a string поєднання для `{k}` має бути рядком
|
||||
@msg spacing must be a number, not `{v}` spacing має бути числом, а не `{v}`
|
||||
@msg stop {i} needs `offset` точці переходу {i} потрібен `offset`
|
||||
@msg stop {i} needs a valid `color` точці переходу {i} потрібен допустимий `color`
|
||||
@msg stop {i}: `{k}` must be a number точка переходу {i}: `{k}` має бути числом
|
||||
@@ -3778,6 +3784,7 @@ axis Both Обидві
|
||||
@msg this is a DWG drawing, which can't be read: save it from the CAD app as an ASCII DXF and open that це креслення DWG, яке неможливо прочитати: збережіть його з CAD як ASCII DXF і відкрийте його
|
||||
@msg this is a PostScript file (an .ai saved in an older format or without PDF compatibility, or an EPS file), which can't be opened yet: save it as PDF, PDF-compatible .ai or SVG це файл PostScript (.ai, збережений у старому форматі або без сумісності з PDF, або файл EPS), який поки неможливо відкрити: збережіть його як PDF, .ai із сумісністю з PDF або SVG
|
||||
@msg this is not a PostScript file це не файл PostScript
|
||||
@msg to must be "selection", "artboard" or "key", not `{v}` to має бути "selection", "artboard" або "key", а не `{v}`
|
||||
@msg tool shortcuts must be a single key (optionally with Shift) поєднання інструментів має бути однією клавішею (необов’язково з Shift)
|
||||
@msg truncated усічено
|
||||
@msg unknown command `{0}` невідома команда `{0}`
|
||||
@@ -3802,6 +3809,7 @@ axis Both Обидві
|
||||
@msg unknown workspace (one of {_1}) невідоме робоче середовище (одна з: {_1})
|
||||
@msg unsupported: {0} не підтримується: {0}
|
||||
@msg version {0} files can't be compressed: only version {COMPRESSED_SINCE} and later open compressed files файли версії {0} не можуть бути стиснуті: тільки версія {COMPRESSED_SINCE} і новіші відкривають стислі файли
|
||||
@msg vertical must be "top", "center" or "bottom", not `{v}` vertical має бути "top", "center" або "bottom", а не `{v}`
|
||||
@msg width and height are at least 1 pixel ширина та висота повинні бути не менше 1 пікселя
|
||||
@msg workspace name can't be empty ім’я робочого середовища не може бути порожнім
|
||||
@msg {C}: no effect at index {from} {C}: немає ефекту з індексом {from}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 659 and column 40.
|
+5
-1
@@ -435,7 +435,7 @@ Long-tail commands:
|
||||
```json
|
||||
{"name":"list_commands","arguments":{"filter":"align"}}
|
||||
{"name":"run_command","arguments":{"command":"select.all"}}
|
||||
{"name":"run_command","arguments":{"command":"object.align","params":{"align":"left"}}}
|
||||
{"name":"run_command","arguments":{"command":"object.align","params":{"horizontal":"left"}}}
|
||||
{"name":"run_command","arguments":{"command":"object.group"}}
|
||||
{"name":"run_command","arguments":{"command":"document.exportPdf","params":{"path":"/tmp/art.pdf","range":"1, 3","compatibility":"1.5"}}}
|
||||
{"name":"run_command","arguments":{"command":"document.pdfSettings","params":{"marks":{"trim":true},"includeDocument":true}}}
|
||||
@@ -1506,6 +1506,10 @@ Effects off a 100 pt wide rectangle with a 10 pt stroke set to `width: 220` gets
|
||||
{"name":"run_command","arguments":{"command":"object.align","params":{"horizontal":"left","bounds":"preview"}}}
|
||||
```
|
||||
|
||||
`object.align` needs `horizontal` or `vertical`. The three Align commands, `object.reflect` and `object.shear` return
|
||||
an error naming any `horizontal`, `vertical`, `to`, `axis` or `bounds` value outside the ones `list_commands` gives for
|
||||
that parameter, and any `spacing` that is not a number; nothing moves.
|
||||
|
||||
## Selection preferences
|
||||
|
||||
The Selection & Anchor Display and General preferences apply to `pointer_gesture` as they do to the mouse:
|
||||
|
||||
@@ -405,6 +405,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- **Shapes:** all shape tools (including Flare) and the line, arc, spiral and grid tools. Space held while dragging out a shape, line, arc, spiral or grid moves it at its current size. While a grid is dragged out, Up/Down change its rows (concentric dividers) and Left/Right its columns (radial dividers). An ellipse's Pie Start and End Angle and Invert Pie (Transform and Properties panels' Ellipse Properties, `object.setLiveShape {pieStart, pieEnd, invertPie}`) cut it as a pie (#812; the on-canvas pie widget is still to come). A live polygon's Polygon Properties there: side count, angle, corner type and radius, radius, side length and Make Sides Equal once an uneven scale has made its sides differ (`object.setLiveShape {sides, polygonAngle, polygonRadius, sideLength, makeSidesEqual}`, part of #812); a star is a plain path, as in Illustrator. The Flare Tool Options last as the tool's options: the next flare dragged out uses them, a click's dialog shows them and double-clicking the tool opens them (part of #812).
|
||||
- **Cutting:** Eraser, Scissors, Knife, Mirror & Cut, Line Cut and Rectangle Cut (real geometry, compound paths keep their holes).
|
||||
- **Transform:** Rotate, Reflect, Scale, Shear (click or Alt-click snaps the reference point to anchors and centres; Alt-click opens the tool's dialog, and a drag with Alt down at the release, from the press or pressed mid-drag, transforms a copy), Reshape, Free Transform (free and perspective distort and shear, switched by the keys held during a handle drag).
|
||||
Align, Distribute, Distribute Spacing, Reflect and Shear return an error naming any `horizontal`, `vertical`, `to`, `axis`, `bounds` or `spacing` value they don't take, and Align returns one when a call gives neither `horizontal` nor `vertical`; nothing moves and no undo step is recorded.
|
||||
- **Live Corners:** drag a live rectangle's corner widgets (Selection or Direct Selection) to round all corners, with a radius readout; with Direct Selection, select corner anchors to show and round just those corners (#381). Each corner keeps its own radius and kind (Round, Inverted Round, Chamfer): Alt-click a widget to cycle the kind, double-click it for the Corners dialog, and the Properties and Transform radius fields set the selected corners (`object.setLiveShape {corners, radius, kind}`). Corners stay circular when the rectangle is scaled unevenly or along its own sides when rotated (the radius keeps its size, or scales by the mean scale with Scale Corners on); only a shear distorts them. On a rectangle that isn't square every corner is the same circle: a radius past half the shorter side stops there for all of them, the widgets sit on the corners as drawn and turn the edited corners red at that limit, CSS export writes the drawn radii, and rectangles saved stretched by older versions get circular corners when their corners are next set (#442). Live Corners work on any path's corners too, as on a rectangle's (#511): a star's, a live polygon's (which also shows them to the Selection tool, has a Corner Radius field in the Properties and Transform panels and keeps its radius as its sides change) and a pen path's, wherever two straight sides meet at an anchor. Direct Selection shows the widgets of every corner, or of the corners holding selected anchors; each corner is a circle tangent to both sides, drawn no larger than takes its cut halfway along its shorter side; a path keeps its uncut outline so its corners stay editable, and the same command, dialog, angle preference and View › Hide Corner Widget apply.
|
||||
- **Pen:** Alt pressed in the middle of dragging out an anchor splits its handles and keeps the curve already shaped into it (only the outgoing handle follows the pointer); Space held while dragging out an anchor moves it, handles and all. A press on the first anchor of the path being drawn closes it whatever the drag then does: the drag shapes the closing curve (symmetric handles, Alt breaks them) and the release closes the path wherever it ends (#501). Clicking the last anchor of the path being drawn retracts its outgoing handle (convert cursor), and dragging from it pulls out a new one on its own. Auto Add/Delete: over a selected path, a click on a segment adds an anchor and a click on an anchor deletes it (add and delete cursors); Shift held, or Preferences › General › Disable Auto Add/Delete, starts a new path instead. Alt held over a handle end or an anchor of a selected path (the one being drawn too) works as the Anchor Point tool, with its convert cursor: dragging a handle moves it alone, clicking a smooth anchor makes it a corner, dragging an anchor pulls out new symmetric handles, dragging a segment reshapes it; drawing then goes on. Cmd (Ctrl) held drags with the selection tool chosen last, Direct Selection until one is (handles, anchors and segments of the path being drawn or another), and the Pen then goes on drawing its path while that stays selected; the pointer shows that tool's while Cmd is held. The same holds for agents (`pointer_gesture` with `mods.cmd`), as the borrowing now lives in the engine (#494).
|
||||
- **Path editing (#494):** the handles shown are the handles that drag: Direct Selection drags those of a path selected as a whole (as the Pen leaves it), the Anchor Point tool and Pen+Alt no longer grab handles that Show handles when multiple anchors are selected hides, a handle shorter than the tolerance leaves its anchor to be picked, and the anchor tools pick within Selection & Anchor Display › Tolerance. A dragged segment keeps a smooth anchor at either end smooth. With Direct Selection, the Pen, the Curvature and the anchor tools, a path selected as a whole shows all its anchors selected, and the Control bar and the Properties panel offer Convert (corner, smooth) for them too; Remove and Cut wait for anchors direct-selected (#504). A handle drag gathers its snap targets once per drag (it took 21 ms per pointer move on a 20,000-path document, now 1 ms; `vectorcraft-cli perf` measures handle and segment drags on a 5,000-anchor path).
|
||||
|
||||
Reference in new issue
Block a user