mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-13 21:17:48 +00:00
Merge main into feat/guides-layer-rows
This commit is contained in:
@@ -17,25 +17,25 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
affinity3:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
env:
|
||||
AFFINITY_CORPUS_REQUIRED: "1"
|
||||
CARGO_PROFILE_DEV_DEBUG: "0"
|
||||
CARGO_PROFILE_TEST_DEBUG: "0"
|
||||
steps:
|
||||
- name: Harden runner
|
||||
uses: step-security/harden-runner@1d88384fd173af6ecb012dfd0264a306b711241a # v2.22.4
|
||||
with:
|
||||
egress-policy: audit
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Install Rust
|
||||
uses: step-security/dtolnay-rust-toolchain@8dd607977d06adf4ed49b190381e74c17a9dd25f # v1.0.0
|
||||
with:
|
||||
toolchain: "1.95"
|
||||
- name: Fetch pinned and checksum-verified corpus
|
||||
run: cargo xtask corpus --affinity
|
||||
- name: Parse every file and freeze actual Affinity 3 feature retention
|
||||
run: cargo test -p vectorcraft-affinity --all-features -- --nocapture
|
||||
- name: Check every artboard, native save, SVG, PDF and PSD exports
|
||||
run: cargo test -p vectorcraft-engine --test affinity_artboards --test affinity_text --test affinity_corpus -- --nocapture
|
||||
# Tracks @main so suite-wide CI fixes reach every app without a PR in each repository.
|
||||
uses: storytold/craft-common-actions/.github/workflows/gate.yml@main
|
||||
with:
|
||||
timeout-minutes: 30
|
||||
toolchain: "1.95"
|
||||
# As before: no craft-fonts, apt packages, wasm target or nextest.
|
||||
craft-fonts-ref: ""
|
||||
targets: ""
|
||||
tools: ""
|
||||
dev-debug: "0"
|
||||
env: |
|
||||
AFFINITY_CORPUS_REQUIRED=1
|
||||
CARGO_PROFILE_TEST_DEBUG=0
|
||||
# Its own cache, apart from ci.yml's gate.
|
||||
cache-version: v1-affinity
|
||||
command: |
|
||||
# Pinned and checksum-verified corpus.
|
||||
cargo xtask corpus --affinity
|
||||
# Parse every file and freeze actual Affinity 3 feature retention.
|
||||
cargo test -p vectorcraft-affinity --all-features -- --nocapture
|
||||
# Every artboard, native save, SVG, PDF and PSD export.
|
||||
cargo test -p vectorcraft-engine --test affinity_artboards --test affinity_text --test affinity_corpus -- --nocapture
|
||||
|
||||
@@ -30,51 +30,9 @@ jobs:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
uses: storytold/craft-common-actions/.github/workflows/refresh-contributors.yml@main
|
||||
git-sources:
|
||||
name: Git dependencies come from storytold
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Harden runner
|
||||
uses: step-security/harden-runner@1d88384fd173af6ecb012dfd0264a306b711241a # v2.22.4
|
||||
with:
|
||||
egress-policy: audit
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Git dependencies come from storytold
|
||||
run: |
|
||||
set -euo pipefail
|
||||
test -f Cargo.lock || { echo "Cargo.lock is missing"; exit 1; }
|
||||
# Source replacement, patches and path overrides in cargo config never show up
|
||||
# in Cargo.lock. Parsed rather than grepped: TOML has many spellings of one key.
|
||||
# Cargo still reads the legacy .cargo/config.
|
||||
python3 - <<'PY'
|
||||
import os, sys, tomllib
|
||||
for path in (".cargo/config", ".cargo/config.toml"):
|
||||
if not os.path.exists(path):
|
||||
continue
|
||||
config = tomllib.load(open(path, "rb"))
|
||||
replaced = [name for name, source in config.get("source", {}).items()
|
||||
if isinstance(source, dict) and "replace-with" in source]
|
||||
if replaced or "patch" in config or "paths" in config:
|
||||
print(f"{path} replaces, patches or overrides a source")
|
||||
sys.exit(1)
|
||||
PY
|
||||
# Fails when Cargo.lock is out of date with the manifests.
|
||||
cargo metadata --locked --format-version 1 > /dev/null
|
||||
python3 - <<'PY'
|
||||
import sys, tomllib
|
||||
lock = tomllib.load(open("Cargo.lock", "rb"))
|
||||
bad = sorted({p["source"] for p in lock.get("package", [])
|
||||
if p.get("source", "").startswith("git+")
|
||||
and not p["source"].startswith("git+https://github.com/storytold/")})
|
||||
if bad:
|
||||
print("Git dependencies outside github.com/storytold:", *bad, sep="\n")
|
||||
sys.exit(1)
|
||||
PY
|
||||
|
||||
release:
|
||||
needs: [git-sources, credits]
|
||||
needs: credits
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
@@ -167,9 +167,13 @@ pub(super) fn smooth_region(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
return Ok(json!({ "ids": [], "before": 0, "after": 0 }));
|
||||
}
|
||||
let ids: Vec<NodeId> = plan.iter().map(|(id, _)| *id).collect();
|
||||
s.edit("Smooth", |d, _| {
|
||||
s.edit("Smooth", |d, sel| {
|
||||
for (id, np) in plan {
|
||||
*path_mut(d, id)? = np;
|
||||
// The smoothed path has new anchors, so the old anchor and segment indices are
|
||||
// dropped and the path stays selected whole.
|
||||
sel.anchors.remove(&id);
|
||||
sel.segments.remove(&id);
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
@@ -346,6 +346,36 @@ impl Library {
|
||||
}
|
||||
}
|
||||
|
||||
/// Name item `r` `name`, in its place in its kind's list; an item keyed by its name keeps its
|
||||
/// group under the new name (a graphic is keyed by its id, which stays).
|
||||
fn rename_item(&mut self, r: &ItemRef, name: &str) {
|
||||
fn set<'a>(mut names: impl Iterator<Item = &'a mut String>, from: &str, to: &str) {
|
||||
if let Some(n) = names.find(|n| n.as_str() == from) {
|
||||
*n = to.to_string();
|
||||
}
|
||||
}
|
||||
let from = r.item.as_str();
|
||||
match r.kind {
|
||||
ItemKind::Color => set(self.colors.iter_mut().map(|c| &mut c.name), from, name),
|
||||
ItemKind::Gradient => set(self.gradients.iter_mut().map(|g| &mut g.name), from, name),
|
||||
ItemKind::Pattern => set(self.patterns.iter_mut().map(|p| &mut p.name), from, name),
|
||||
ItemKind::CharStyle => set(self.char_styles.iter_mut().map(|t| &mut t.name), from, name),
|
||||
ItemKind::ParaStyle => set(self.para_styles.iter_mut().map(|t| &mut t.name), from, name),
|
||||
ItemKind::Graphic => {
|
||||
if let Some(g) = self.graphics.iter_mut().find(|g| g.id == from) {
|
||||
g.name = name.to_string();
|
||||
}
|
||||
return;
|
||||
}
|
||||
ItemKind::Unknown => return,
|
||||
}
|
||||
for x in self.groups.iter_mut().flat_map(|g| g.items.iter_mut()) {
|
||||
if x == r {
|
||||
x.item = name.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Move item `r` next to `to`, an item of its kind: just before it, or just after it when
|
||||
/// `after`, in their kind's list (the order the panel shows them in).
|
||||
fn place_next_to(&mut self, r: &ItemRef, to: &ItemRef, after: bool) {
|
||||
@@ -683,7 +713,7 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
"Use Library Item",
|
||||
[],
|
||||
None,
|
||||
"{library?, kind, item: name (graphic: id or name), center?: [x, y] (graphic; default: the first artboard's centre), to?: fill|stroke (colors, gradients, patterns; default: the kind's), recorded?: the item as it was when used (recorded in the journal so a replay matches)} graphic: place a copy centred on `center`, its resources pasted along, selected, one undo step; colors and gradients: paint the selection (and the defaults) as paint.setFill/paint.setStroke, a gradient fitting each object; a spot color links to the document's spot swatch of its ink's name, added when the document has none of that colour (a name taken by another colour gets a number), one undo step; patterns: add the pattern and its swatch to the document (a name the document gives another pattern gets a number; the same pattern is reused) and paint the selection (and the defaults) with it, one undo step; charStyle/paraStyle: add the style to the document (a name taken by different attributes gets a number) and apply it to the selected text, one undo step → {kind, ids?, style?}",
|
||||
"{library?, kind, item: name (graphic: id or name), center?: [x, y] (graphic; default: the first artboard's centre), to?: fill|stroke (colors, gradients, patterns; default: the kind's), recorded?: the item as it was when used (recorded in the journal so a replay matches)} graphic: place a copy centred on `center`, its resources pasted along, selected, one undo step; colors and gradients: paint the selection (and the defaults) as paint.setFill/paint.setStroke, a gradient fitting each object; a spot color links to the document's spot swatch of its ink's name, added when the document has none of that colour (a name taken by another colour gets a number), one undo step; patterns: add the pattern and its swatch to the document (a name the document gives another pattern gets a number; the same pattern is reused) and paint the selection (and the defaults) with it, one undo step; charStyle/paraStyle: add the style to the document (a name taken by different attributes gets a number; a character style's color linked to a swatch that isn't a global or spot swatch of the document keeps the color it shows, unlinked) and apply it to the selected text, one undo step → {kind, ids?, style?}",
|
||||
has_doc,
|
||||
use_item
|
||||
),
|
||||
@@ -696,6 +726,24 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
always,
|
||||
remove_item
|
||||
),
|
||||
cmd!(
|
||||
"library.renameItem",
|
||||
"Rename Library Item",
|
||||
[],
|
||||
None,
|
||||
"{library?, kind, item: name (graphic: id or name), name: string (trimmed; 1 to 256 characters)} rename an item; it keeps its place and its group; another item of its kind with that name is an error, and its own name changes nothing; not undoable → {library, kind, item: its key now (graphic: its id), name}",
|
||||
always,
|
||||
rename_item
|
||||
),
|
||||
cmd!(
|
||||
"library.addToCharacterStyles",
|
||||
"Add to Character Styles",
|
||||
[],
|
||||
None,
|
||||
"{library?, item: a character style's name, recorded?: the style as it was when added (recorded in the journal so a replay matches)} add a library character style to the document's character styles without applying it (no text needs to be selected): a document style of that name with the same attributes is reused, a name taken by different attributes gets a number; a color linked to a swatch that isn't a global or spot swatch of the document keeps the color it shows, unlinked; a new style is one undo step, a reused one none → {style: its name in the document, existing: bool}",
|
||||
has_doc,
|
||||
add_to_char_styles
|
||||
),
|
||||
cmd!(
|
||||
"library.createGroup",
|
||||
"New Library Group",
|
||||
@@ -1231,8 +1279,13 @@ fn use_item(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
Kind::CharStyle | Kind::ParaStyle => {
|
||||
let para = kind == Kind::ParaStyle;
|
||||
let name = data.get("name").and_then(Value::as_str).map(str::trim).filter(|n| !n.is_empty()).unwrap_or("Style").to_string();
|
||||
let attrs = data.get("attrs").and_then(Value::as_object).cloned().unwrap_or_default();
|
||||
let mut attrs = data.get("attrs").and_then(Value::as_object).cloned().unwrap_or_default();
|
||||
let doc = &s.doc()?.doc;
|
||||
if !para {
|
||||
unlink_missing_swatches(doc, &mut attrs);
|
||||
}
|
||||
// Compared in the form the document stores them in.
|
||||
let attrs = super::textstyles::stored_style_attrs(doc, para, &attrs).unwrap_or(attrs);
|
||||
// The document's style of that name when it is the same; else a new one.
|
||||
let same = super::textstyles::style_attrs(doc, para, &name).is_some_and(|a| a == attrs);
|
||||
let style = if same { name } else { unique(&name, |n| super::textstyles::style_attrs(doc, para, n).is_some()) };
|
||||
@@ -1361,6 +1414,109 @@ fn remove_item(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
ok()
|
||||
}
|
||||
|
||||
fn rename_item(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "library.renameItem";
|
||||
let (id, kind, item) = item_param(s, p, C)?;
|
||||
let name = match p.get("name") {
|
||||
None | Some(Value::Null) => return Err(bad(C, "missing `name`")),
|
||||
Some(Value::String(n)) => n.trim().to_string(),
|
||||
Some(_) => return Err(bad(C, "`name` must be a string")),
|
||||
};
|
||||
if name.is_empty() {
|
||||
return Err(bad(C, "missing `name`"));
|
||||
}
|
||||
if name.chars().count() > MAX_NAME {
|
||||
let (label, max) = ("`name`", MAX_NAME);
|
||||
return Err(bad(C, format!("{label} must be at most {max} characters")));
|
||||
}
|
||||
let lib = s.libraries.get(&id).ok_or_else(|| bad(C, format!("no library `{id}`")))?;
|
||||
let r = lib.item_ref(kind.item_kind(), item).ok_or_else(|| bad(C, format!("the library has no item `{item}`")))?;
|
||||
// The item's name now, and whether another item of its kind has the new one.
|
||||
let mut same = false;
|
||||
let mut taken = false;
|
||||
for (_, key, shown) in lib.items().filter(|(k, ..)| *k == r.kind) {
|
||||
if key == r.item {
|
||||
same = shown == name;
|
||||
} else if shown == name {
|
||||
taken = true;
|
||||
}
|
||||
}
|
||||
let key = if r.kind == ItemKind::Graphic { r.item.clone() } else { name.clone() };
|
||||
let out = json!({ "library": id, "kind": str_param(p, "kind"), "item": key, "name": name });
|
||||
if same {
|
||||
return Ok(out);
|
||||
}
|
||||
if taken {
|
||||
return Err(bad(C, format!("the library has another item of that kind named `{name}`")));
|
||||
}
|
||||
s.libraries.change(&id, |lib| {
|
||||
lib.rename_item(&r, &name);
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn add_to_char_styles(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "library.addToCharacterStyles";
|
||||
// A replay (the journal) carries what the style was, so it doesn't depend on the library.
|
||||
let data = match p.get("recorded").cloned() {
|
||||
Some(r) => r,
|
||||
None => {
|
||||
let id = library_id(s, p, C)?;
|
||||
let item = str_param(p, "item").ok_or_else(|| bad(C, "missing `item`"))?;
|
||||
let lib = s.libraries.get(&id).ok_or_else(|| bad(C, format!("no library `{id}`")))?;
|
||||
let t = lib.char_styles.iter().find(|t| t.name == item).ok_or_else(|| bad(C, format!("the library has no item `{item}`")))?;
|
||||
let data = json!({ "name": t.name, "attrs": t.attrs });
|
||||
s.note_journal("recorded", data.clone());
|
||||
data
|
||||
}
|
||||
};
|
||||
let name = data.get("name").and_then(Value::as_str).map(str::trim).filter(|n| !n.is_empty()).unwrap_or("Style").to_string();
|
||||
let mut attrs = data.get("attrs").and_then(Value::as_object).cloned().ok_or_else(|| bad(C, "the library item is damaged"))?;
|
||||
let doc = &s.doc()?.doc;
|
||||
unlink_missing_swatches(doc, &mut attrs);
|
||||
// Compared in the form the document stores them in.
|
||||
let attrs = super::textstyles::stored_style_attrs(doc, false, &attrs).unwrap_or(attrs);
|
||||
// The document's style of that name when it is the same; else a new one, which isn't applied.
|
||||
if super::textstyles::style_attrs(doc, false, &name).is_some_and(|a| a == attrs) {
|
||||
return Ok(json!({ "style": name, "existing": true }));
|
||||
}
|
||||
let style = unique(&name, |n| super::textstyles::style_attrs(doc, false, n).is_some());
|
||||
s.execute("charStyle.new", &json!({ "name": style, "attrs": attrs }))?;
|
||||
Ok(json!({ "style": style, "existing": false }))
|
||||
}
|
||||
|
||||
/// Unlink a library character style's `fill` and `stroke` colors (solid, and each gradient stop)
|
||||
/// from swatches that are not global or spot swatches of `doc`: an unlinked color keeps the color
|
||||
/// it shows at full tint, as [`clean_gradient`] keeps a library gradient's stops. A link to a
|
||||
/// global or spot swatch `doc` has stays, and takes that swatch's color.
|
||||
fn unlink_missing_swatches(doc: &vectorcraft_doc::Document, attrs: &mut Map<String, Value>) {
|
||||
let keep = |name: &str| doc.global_color(name).is_some();
|
||||
for key in ["fill", "stroke"] {
|
||||
let Some(mut paint) = attrs.get(key).and_then(|v| serde_json::from_value::<Paint>(v.clone()).ok()) else { continue };
|
||||
let mut changed = false;
|
||||
let mut unlink = |swatch: &mut Option<String>, tint: &mut f32| {
|
||||
if swatch.as_deref().is_some_and(|n| !keep(n)) {
|
||||
*swatch = None;
|
||||
*tint = 1.0;
|
||||
changed = true;
|
||||
}
|
||||
};
|
||||
match &mut paint {
|
||||
Paint::Solid { swatch, tint, .. } => unlink(swatch, tint),
|
||||
Paint::Gradient(g) => {
|
||||
for st in &mut g.gradient.stops {
|
||||
unlink(&mut st.swatch, &mut st.tint);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if changed && let Ok(v) = serde_json::to_value(&paint) {
|
||||
attrs.insert(key.to_string(), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `p`'s `name`, trimmed and clipped, else `default`.
|
||||
fn name_param(p: &Value, default: &str) -> String {
|
||||
let mut name = str_param(p, "name").map(str::trim).filter(|n| !n.is_empty()).unwrap_or(default).to_string();
|
||||
|
||||
@@ -506,6 +506,13 @@ pub(crate) fn style_attrs(d: &Document, para: bool, name: &str) -> Option<Map<St
|
||||
if para { Kind::Para } else { Kind::Char }.attrs(d, name)
|
||||
}
|
||||
|
||||
/// `attrs` in the form `charStyle.new` (`para`: `paraStyle.new`) stores them in `d`, or `None`
|
||||
/// when they don't pass its checks.
|
||||
pub(crate) fn stored_style_attrs(d: &Document, para: bool, attrs: &Map<String, Value>) -> Option<Map<String, Value>> {
|
||||
let kind = if para { Kind::Para } else { Kind::Char };
|
||||
attrs_param(d, &json!({ "attrs": attrs }), kind, "new", None).ok().flatten()
|
||||
}
|
||||
|
||||
/// The name `charStyle.new` (`para`: `paraStyle.new`) gives a style when it is given none: the
|
||||
/// first "Character Style N" ("Paragraph Style N") that no character style (paragraph style) of the
|
||||
/// document has.
|
||||
|
||||
@@ -1367,6 +1367,28 @@ fn smooth_tool_reduces_jagged_path() {
|
||||
assert_eq!(p.subpaths[0].anchors[0].p, Point::new(100.0, 200.0));
|
||||
}
|
||||
|
||||
/// Smoothing a path with direct-selected anchors leaves the path selected whole: the selection no
|
||||
/// longer names anchors by indices into the anchors the smooth replaced. A selected path the drag
|
||||
/// does not reach keeps its anchors selected, and undo brings the old selection back.
|
||||
#[test]
|
||||
fn smoothing_a_path_drops_its_direct_selected_anchors() {
|
||||
let mut s = session();
|
||||
let anchors: Vec<_> = (0..=40).map(|i| json!({"x": 100.0 + i as f64 * 5.0, "y": 200.0 + if i % 2 == 0 { 0.0 } else { 1.5 }})).collect();
|
||||
let r = s.execute("path.create", &json!({"anchors": anchors})).unwrap();
|
||||
let id = NodeId(r["id"].as_u64().unwrap());
|
||||
let other = line(&mut s, 100.0, 500.0, 300.0, 500.0);
|
||||
s.execute("select.anchors", &json!({"id": id.0, "anchors": [[0, 38]], "mode": "set"})).unwrap();
|
||||
s.execute("select.anchors", &json!({"id": other.0, "anchors": [[0, 1]], "mode": "add"})).unwrap();
|
||||
drag(&mut s, "smooth", &[(90.0, 200.0), (200.0, 200.0), (310.0, 200.0)], Mods::default());
|
||||
assert!(path(&s, id).anchor_count() < 20, "the path is smoothed");
|
||||
let sel = s.doc().unwrap().selection.clone();
|
||||
assert!(sel.contains(id) && sel.contains(other), "{sel:?}");
|
||||
assert!(!sel.anchors.contains_key(&id) && !sel.segments.contains_key(&id), "{sel:?}");
|
||||
assert_eq!(sel.anchors.get(&other), Some(&[(0, 1)].into()), "the path out of reach keeps its anchor");
|
||||
s.execute("edit.undo", &json!({})).unwrap();
|
||||
assert_eq!(s.doc().unwrap().selection.anchors.get(&id), Some(&[(0, 38)].into()));
|
||||
}
|
||||
|
||||
/// #1512: a short drag over a small bump smooths the stretch of path under it. The long straight
|
||||
/// sides next to the bump stay straight lines from their far ends, which keep their place.
|
||||
#[test]
|
||||
|
||||
@@ -635,6 +635,210 @@ fn a_library_style_named_with_spaces_comes_in_trimmed() {
|
||||
assert_eq!((text.runs[0].style.size, text.runs[0].style.style_name.as_deref()), (31.0, Some("Body")));
|
||||
}
|
||||
|
||||
/// The size of the first run of text object `id`.
|
||||
fn run_size(s: &Session, id: &Value) -> f64 {
|
||||
match &s.doc().unwrap().doc.node(NodeId(id.as_u64().unwrap())).unwrap().kind {
|
||||
vectorcraft_doc::NodeKind::Text(t) => t.runs[0].style.size,
|
||||
_ => 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add to Character Styles puts a library character style into the document's character styles
|
||||
/// without applying it, with or without type selected, in one undo step; the same style there is
|
||||
/// reused without a step, and a name taken by other attributes gets a number. A bad call changes
|
||||
/// nothing.
|
||||
#[test]
|
||||
fn a_library_character_style_is_added_to_the_document_without_applying_it() {
|
||||
let mut s = session();
|
||||
let data = json!({"name": "Kept", "charStyles": [{"name": "Headline", "attrs": {"size": 31.0}}, {"name": "Broken", "attrs": {"size": "big"}}]});
|
||||
let lib = run(&mut s, "library.import", json!({"data": data.to_string()}))["id"].as_str().unwrap().to_string();
|
||||
let styles = |s: &Session| s.doc().unwrap().doc.char_styles.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
|
||||
let undo = |s: &Session| s.doc().unwrap().history.undo.len();
|
||||
// Nothing selected.
|
||||
let before = undo(&s);
|
||||
let r = run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Headline"}));
|
||||
assert_eq!((r["style"].as_str(), r["existing"].as_bool()), (Some("Headline"), Some(false)));
|
||||
assert_eq!(styles(&s), ["Headline"]);
|
||||
assert_eq!(undo(&s), before + 1, "one undo step");
|
||||
let attrs = &s.doc().unwrap().doc.char_styles[0].attrs;
|
||||
assert_eq!(attrs.get("size"), Some(&json!(31.0)));
|
||||
// Selected type keeps its look.
|
||||
let t = run(&mut s, "text.create", json!({"x": 10, "y": 50, "text": "Body", "size": 9}))["id"].clone();
|
||||
run(&mut s, "select.set", json!({"ids": [t]}));
|
||||
let before = undo(&s);
|
||||
let r = run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Headline"}));
|
||||
assert_eq!((r["style"].as_str(), r["existing"].as_bool()), (Some("Headline"), Some(true)));
|
||||
assert_eq!((undo(&s), run_size(&s, &t), styles(&s).len()), (before, 9.0, 1), "reused: no step, the type unchanged");
|
||||
// Another style of that name: numbered, still not applied.
|
||||
run(&mut s, "charStyle.setAttrs", json!({"name": "Headline", "attrs": {"size": 5}}));
|
||||
let r = run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Headline"}));
|
||||
assert_eq!((r["style"].as_str(), r["existing"].as_bool()), (Some("Headline 2"), Some(false)));
|
||||
assert_eq!(run_size(&s, &t), 9.0);
|
||||
let vectorcraft_doc::NodeKind::Text(text) = &s.doc().unwrap().doc.node(NodeId(t.as_u64().unwrap())).unwrap().kind else { panic!("not text") };
|
||||
assert_eq!(text.runs[0].style.style_name, None, "no style applied");
|
||||
// Undo takes the added style back alone.
|
||||
run(&mut s, "edit.undo", json!({}));
|
||||
assert_eq!(styles(&s), ["Headline"]);
|
||||
// Bad calls: nothing changes.
|
||||
let before = (undo(&s), styles(&s));
|
||||
for bad in [
|
||||
json!({"library": lib}),
|
||||
json!({"library": lib, "item": 3}),
|
||||
json!({"library": lib, "item": "Nope"}),
|
||||
json!({"library": "Nope", "item": "Headline"}),
|
||||
json!({"library": lib, "item": "Broken"}),
|
||||
json!({"recorded": {"name": "X", "attrs": "damaged"}}),
|
||||
] {
|
||||
assert!(s.execute("library.addToCharacterStyles", &bad).is_err(), "{bad}");
|
||||
assert_eq!((undo(&s), styles(&s)), before, "{bad}");
|
||||
}
|
||||
// Without a document it isn't available.
|
||||
run(&mut s, "file.close", json!({}));
|
||||
assert!(s.active().is_none());
|
||||
assert!(s.execute("library.addToCharacterStyles", &json!({"library": lib, "item": "Headline"})).is_err());
|
||||
}
|
||||
|
||||
/// A library character style whose fill links to a swatch the document lacks is added and applied
|
||||
/// with the color it shows, unlinked at full tint; a global swatch of that name in the document
|
||||
/// keeps the link and gives its color.
|
||||
#[test]
|
||||
fn a_library_character_style_linked_to_a_missing_swatch_is_added_unlinked() {
|
||||
let base = vectorcraft_color::Color::rgb(0.2, 0.4, 0.6);
|
||||
let shown = base.tinted(0.5);
|
||||
let linked = vectorcraft_color::Paint::Solid { color: shown, swatch: Some("Brand".into()), tint: 0.5 };
|
||||
let data = json!({"name": "Kept", "charStyles": [{"name": "Accent", "attrs": {"size": 20.0, "fill": linked}}]});
|
||||
let mut s = session();
|
||||
let lib = run(&mut s, "library.import", json!({"data": data.to_string()}))["id"].as_str().unwrap().to_string();
|
||||
let fill = |s: &Session, name: &str| {
|
||||
let st = s.doc().unwrap().doc.char_styles.iter().find(|c| c.name == name).map(|c| c.attrs.clone()).unwrap();
|
||||
serde_json::from_value::<vectorcraft_color::Paint>(st["fill"].clone()).unwrap()
|
||||
};
|
||||
run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Accent"}));
|
||||
assert_eq!(fill(&s, "Accent"), vectorcraft_color::Paint::Solid { color: shown, swatch: None, tint: 1.0 });
|
||||
// Apply as well, on selected type.
|
||||
let t = run(&mut s, "text.create", json!({"x": 10, "y": 50, "text": "Body", "size": 9}))["id"].clone();
|
||||
run(&mut s, "select.set", json!({"ids": [t]}));
|
||||
let r = run(&mut s, "library.use", json!({"library": lib, "kind": "charStyle", "item": "Accent"}));
|
||||
assert_eq!(r["style"], "Accent", "the added style is reused");
|
||||
assert_eq!(run_size(&s, &t), 20.0);
|
||||
// A document with a global swatch of that name keeps the link.
|
||||
run(&mut s, "file.new", json!({"width": 200, "height": 200}));
|
||||
let other = vectorcraft_color::Color::rgb(0.8, 0.1, 0.1);
|
||||
run(&mut s, "swatch.new", json!({"name": "Brand", "color": other, "global": true}));
|
||||
run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Accent"}));
|
||||
let vectorcraft_color::Paint::Solid { swatch, tint, .. } = fill(&s, "Accent") else { panic!("not a solid fill") };
|
||||
assert_eq!((swatch.as_deref(), tint), (Some("Brand"), 0.5));
|
||||
// The style with the document's swatch color is the same style: added again, it is reused.
|
||||
let r = run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Accent"}));
|
||||
assert_eq!((r["style"].as_str(), r["existing"].as_bool()), (Some("Accent"), Some(true)));
|
||||
}
|
||||
|
||||
/// A library style is compared with the document's in the form the document stores it in, so a
|
||||
/// style whose file writes a size as a whole number is reused, by Add to Character Styles and by a
|
||||
/// click alike.
|
||||
#[test]
|
||||
fn a_library_style_is_reused_whatever_form_its_file_writes_it_in() {
|
||||
let data = json!({"name": "Kept", "charStyles": [{"name": "Whole", "attrs": {"size": 31}}], "paraStyles": [{"name": "Para", "attrs": {"left_indent": 4}}]});
|
||||
let mut s = session();
|
||||
let lib = run(&mut s, "library.import", json!({"data": data.to_string()}))["id"].as_str().unwrap().to_string();
|
||||
run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Whole"}));
|
||||
let r = run(&mut s, "library.addToCharacterStyles", json!({"library": lib, "item": "Whole"}));
|
||||
assert_eq!((r["style"].as_str(), r["existing"].as_bool()), (Some("Whole"), Some(true)));
|
||||
let t = run(&mut s, "text.create", json!({"x": 10, "y": 50, "text": "Body", "size": 9}))["id"].clone();
|
||||
run(&mut s, "select.set", json!({"ids": [t]}));
|
||||
for (kind, item) in [("charStyle", "Whole"), ("paraStyle", "Para"), ("paraStyle", "Para")] {
|
||||
assert_eq!(run(&mut s, "library.use", json!({"library": lib, "kind": kind, "item": item}))["style"], item);
|
||||
}
|
||||
let d = &s.doc().unwrap().doc;
|
||||
assert_eq!((d.char_styles.len(), d.para_styles.iter().filter(|p| p.name.starts_with("Para")).count()), (1, 1));
|
||||
}
|
||||
|
||||
/// Rename gives a library item a new name, trimmed, in its place and its group; a character style
|
||||
/// keeps its attributes, a graphic its id. Another item of its kind with that name, an empty or
|
||||
/// too long name, a name that isn't text and an unknown item or library are errors that change
|
||||
/// nothing; a name with path characters is a name like any other; the item's own name writes
|
||||
/// nothing; and the document's history is not touched.
|
||||
#[test]
|
||||
fn library_items_are_renamed_in_place() {
|
||||
let (mut s, g, c, st) = brand();
|
||||
let t = run(&mut s, "text.create", json!({"x": 10, "y": 120, "text": "Body", "size": 9}))["id"].clone();
|
||||
run(&mut s, "select.set", json!({"ids": [t]}));
|
||||
let other = run(&mut s, "library.add", json!({"kind": "charStyle", "name": "Body"}))["name"].as_str().unwrap().to_string();
|
||||
run(&mut s, "library.createGroup", json!({"name": "Brand", "items": [{"kind": "charStyle", "item": st}, {"kind": "fillColor", "item": c}]}));
|
||||
let undo = s.doc().unwrap().history.undo.len();
|
||||
let attrs = run(&mut s, "library.get", json!({}))["charStyles"][0]["attrs"].clone();
|
||||
let r = run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": st, "name": " Title "}));
|
||||
assert_eq!((r["item"].as_str(), r["name"].as_str()), (Some("Title"), Some("Title")));
|
||||
let got = run(&mut s, "library.get", json!({}));
|
||||
assert_eq!(got["charStyles"][0], json!({"name": "Title", "attrs": attrs}), "first still, the attributes kept");
|
||||
assert_eq!(got["charStyles"][1]["name"], other.as_str());
|
||||
assert_eq!(groups(&mut s), [("Brand".into(), refs(&[("charStyle", "Title"), ("color", &c)]))]);
|
||||
// A colour keeps its group under its new name; a graphic keeps its id.
|
||||
run(&mut s, "library.renameItem", json!({"kind": "strokeColor", "item": c, "name": "Navy"}));
|
||||
assert_eq!(groups(&mut s), [("Brand".into(), refs(&[("charStyle", "Title"), ("color", "Navy")]))]);
|
||||
let r = run(&mut s, "library.renameItem", json!({"kind": "graphic", "item": "Logo", "name": "Mark"}));
|
||||
assert_eq!(r["item"], g.as_str());
|
||||
let graphic = run(&mut s, "library.get", json!({}))["graphics"][0].clone();
|
||||
assert_eq!((graphic["id"].as_str(), graphic["name"].as_str()), (Some(g.as_str()), Some("Mark")));
|
||||
// Path characters are kept.
|
||||
run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": "Title", "name": "a/b\\c:d"}));
|
||||
assert_eq!(style_order_of(&mut s)[0], "a/b\\c:d");
|
||||
// Errors change nothing.
|
||||
let before = run(&mut s, "library.get", json!({}));
|
||||
let long = "x".repeat(257);
|
||||
for bad in [
|
||||
json!({"kind": "charStyle", "item": "a/b\\c:d", "name": other}),
|
||||
json!({"kind": "charStyle", "item": "a/b\\c:d", "name": " "}),
|
||||
json!({"kind": "charStyle", "item": "a/b\\c:d", "name": long}),
|
||||
json!({"kind": "charStyle", "item": "a/b\\c:d", "name": 5}),
|
||||
json!({"kind": "charStyle", "item": "a/b\\c:d"}),
|
||||
json!({"kind": "charStyle", "item": "Nope", "name": "X"}),
|
||||
json!({"kind": "paraStyle", "item": "a/b\\c:d", "name": "X"}),
|
||||
json!({"kind": "brush", "item": "a/b\\c:d", "name": "X"}),
|
||||
json!({"library": "Nope", "kind": "charStyle", "item": "a/b\\c:d", "name": "X"}),
|
||||
] {
|
||||
assert!(s.execute("library.renameItem", &bad).is_err(), "{bad}");
|
||||
assert_eq!(run(&mut s, "library.get", json!({})), before, "{bad}");
|
||||
}
|
||||
// A style of another kind may have the name, and 256 characters are allowed.
|
||||
run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": "a/b\\c:d", "name": "Navy"}));
|
||||
run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": "Navy", "name": "y".repeat(256)}));
|
||||
assert_eq!(s.doc().unwrap().history.undo.len(), undo, "no document undo step");
|
||||
}
|
||||
|
||||
/// The current library's character style names, in order.
|
||||
fn style_order_of(s: &mut Session) -> Vec<String> {
|
||||
order(s, "charStyles", "name")
|
||||
}
|
||||
|
||||
/// A rename is kept in the library's file; renaming an item to its own name writes nothing; and a
|
||||
/// rename whose file can't be written is taken back.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[test]
|
||||
fn a_library_item_rename_is_saved_or_taken_back() {
|
||||
let dir = vectorcraft_testkit::temp_dir("library-rename-item");
|
||||
let folder = dir.to_string_lossy().to_string();
|
||||
let mut s = session();
|
||||
s.libraries.set_dir(Some(folder.clone()));
|
||||
let lib = run(&mut s, "library.create", json!({"name": "Kept"}))["id"].as_str().unwrap().to_string();
|
||||
let t = run(&mut s, "text.create", json!({"x": 10, "y": 50, "text": "Body", "size": 12}))["id"].clone();
|
||||
run(&mut s, "select.set", json!({"ids": [t]}));
|
||||
run(&mut s, "library.add", json!({"kind": "charStyle", "name": "Body"}));
|
||||
run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": "Body", "name": "Text"}));
|
||||
let mut t2 = session();
|
||||
t2.libraries.set_dir(Some(folder.clone()));
|
||||
assert_eq!(style_order_of(&mut t2), ["Text"], "kept in the file");
|
||||
// The file can't be written (a folder stands where it goes): its own name still succeeds, as
|
||||
// it writes nothing; a new name fails and is taken back.
|
||||
let file = dir.join(format!("{lib}.vclibrary"));
|
||||
std::fs::remove_file(&file).unwrap();
|
||||
std::fs::create_dir(&file).unwrap();
|
||||
run(&mut s, "library.renameItem", json!({"kind": "charStyle", "item": "Text", "name": " Text "}));
|
||||
assert!(s.execute("library.renameItem", &json!({"kind": "charStyle", "item": "Text", "name": "Copy"})).is_err());
|
||||
assert_eq!(style_order_of(&mut s), ["Text"], "taken back");
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[test]
|
||||
fn libraries_are_kept_in_files_across_sessions() {
|
||||
|
||||
@@ -296,7 +296,7 @@ pub static LANGUAGES: [LangInfo; 28] = [
|
||||
plural: plural_none,
|
||||
complete_menus: true,
|
||||
catalog: OnceLock::new(),
|
||||
}, // Dutch; every `nl-*` locale (`nl-NL`, `nl-BE`, `nl_NL.UTF-8`…) resolves here.
|
||||
}, // Dutch: the whole interface and the status and error messages; every `nl-*` locale (`nl-NL`, `nl-BE`, `nl_NL.UTF-8`…) resolves here.
|
||||
LangInfo {
|
||||
code: "nl",
|
||||
name: "Nederlands",
|
||||
|
||||
@@ -3491,6 +3491,8 @@ digits Malayalam Малаялам
|
||||
Rename Library Group Преименуване на библиотечна група
|
||||
Delete Library Group Изтриване на библиотечна група
|
||||
Move Library Item to Group Преместване на библиотечен елемент в група
|
||||
Rename Library Item Преименуване на елемент от библиотека
|
||||
Add to Character Styles Добавяне към стилове на знаци
|
||||
Library Библиотека
|
||||
Rename Library Преименуване на библиотека
|
||||
Show Library Показване на библиотека
|
||||
@@ -4064,6 +4066,7 @@ axis Both И двете
|
||||
Drag to the window's left or right edge to dock Плъзнете до левия или десния ръб на прозореца за закотвяне
|
||||
Float Tool Group Плаваща група инструменти
|
||||
@msg no library `{id}` няма библиотека `{id}`
|
||||
@msg the library has another item of that kind named `{name}` библиотеката вече има друг елемент от този вид с име `{name}`
|
||||
@msg select some type first първо изберете текст
|
||||
@msg kerning must be a number, "auto", or "optical" kerning трябва да е число, „auto“ или „optical“
|
||||
@msg {_1} has no {_2} style {_1} няма стил {_2}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3550,6 +3550,8 @@ theme Appearance Izgled
|
||||
Rename Library Group Preimenuj grupu biblioteke
|
||||
Delete Library Group Izbriši grupu biblioteke
|
||||
Move Library Item to Group Premjesti stavku biblioteke u grupu
|
||||
Rename Library Item Preimenuj stavku biblioteke
|
||||
Add to Character Styles Dodaj u stilove znakova
|
||||
Rename Library Preimenuj biblioteku
|
||||
Show Library Prikaži biblioteku
|
||||
Use Library Item Koristi stavku biblioteke
|
||||
@@ -4416,6 +4418,7 @@ imageTrace Outline Obris
|
||||
@plural {n} step|{n} steps {n} korak|{n} koraka|{n} koraka
|
||||
@plural {n} stroke|{n} strokes {n} potez|{n} poteza|{n} poteza
|
||||
@msg no library `{id}` nema biblioteke `{id}`
|
||||
@msg the library has another item of that kind named `{name}` biblioteka već ima drugu stavku te vrste s imenom `{name}`
|
||||
@msg select some type first prvo odaberite tekst
|
||||
@msg kerning must be a number, "auto", or "optical" kerning mora biti broj, „auto” ili „optical”
|
||||
@msg the selection has no gradient fill odabir nema ispunu gradijentom
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2634,6 +2634,8 @@ digits Malayalam Malaiàlam
|
||||
Move in Perspective Mou en perspectiva
|
||||
Move Library Group Mou el grup de la biblioteca
|
||||
Move Library Item to Group Mou l’element de la biblioteca al grup
|
||||
Rename Library Item Canvia el nom de l’element de la biblioteca
|
||||
Add to Character Styles Afegeix als estils de caràcter
|
||||
Move Locked and Hidden Artwork with Artboard Mou la il·lustració bloquejada i oculta amb el tauler
|
||||
Move Mesh Point Mou el punt de malla
|
||||
Move Mesh Points Mou els punts de malla
|
||||
@@ -5730,6 +5732,7 @@ digits Malayalam Malaiàlam
|
||||
@msg no interaction in progress no hi ha cap interacció en curs
|
||||
@msg no key object no hi ha objecte clau
|
||||
@msg no library `{id}` no hi ha la biblioteca `{id}`
|
||||
@msg the library has another item of that kind named `{name}` la biblioteca ja té un altre element d’aquest tipus anomenat `{name}`
|
||||
@msg no library `{key}` (see {list}) no hi ha la biblioteca `{key}` (vegeu {list})
|
||||
@msg No linked files to look for No hi ha fitxers enllaçats per buscar
|
||||
@msg no Live Paint edge near that point no hi ha cap aresta de pintura interactiva a prop d’aquell punt
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3604,6 +3604,8 @@ theme Appearance Motiv
|
||||
Rename Library Group Přejmenovat skupinu knihovny
|
||||
Delete Library Group Odstranit skupinu knihovny
|
||||
Move Library Item to Group Přesunout položku knihovny do skupiny
|
||||
Rename Library Item Přejmenovat položku knihovny
|
||||
Add to Character Styles Přidat do stylů znaků
|
||||
Rename Library Přejmenovat knihovnu
|
||||
Show Library Zobrazit knihovnu
|
||||
Use Library Item Použít položku knihovny
|
||||
@@ -4477,6 +4479,7 @@ imageTrace Outline Obrys
|
||||
|
||||
# Status and error messages
|
||||
@msg no library `{id}` knihovna `{id}` neexistuje
|
||||
@msg the library has another item of that kind named `{name}` knihovna už má jinou položku tohoto druhu s názvem `{name}`
|
||||
@msg select some type first nejprve vyberte text
|
||||
@msg kerning must be a number, "auto", or "optical" kerning musí být číslo, „auto“ nebo „optical“
|
||||
@msg the selection has no gradient fill výběr nemá přechodovou výplň
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3337,6 +3337,8 @@ theme Appearance Udseende
|
||||
Rename Library Group Omdøb biblioteksgruppe
|
||||
Delete Library Group Slet biblioteksgruppe
|
||||
Move Library Item to Group Flyt bibliotekselement til gruppe
|
||||
Rename Library Item Omdøb bibliotekselement
|
||||
Add to Character Styles Føj til tegnstile
|
||||
Rename Library Omdøb bibliotek
|
||||
Show Library Vis bibliotek
|
||||
Use Library Item Brug bibliotekselement
|
||||
@@ -4183,6 +4185,7 @@ imageTrace Outline Kontur
|
||||
@plural {n} step|{n} steps {n} trin|{n} trin
|
||||
@plural {n} stroke|{n} strokes {n} kontur|{n} konturer
|
||||
@msg no library `{id}` intet bibliotek `{id}`
|
||||
@msg the library has another item of that kind named `{name}` biblioteket har allerede et andet element af den type med navnet `{name}`
|
||||
@msg select some type first markér først noget tekst
|
||||
@msg kerning must be a number, "auto", or "optical" kerning skal være et tal, „auto“ eller „optical“
|
||||
@msg {_1} has no {_2} style {_1} har ingen {_2}-stil
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4091,6 +4091,7 @@ theme Appearance Erscheinungsbild
|
||||
# (`untranslated_report` lists any that are missing). Command ids, parameter
|
||||
# names and values in backticks or code (`colorModel rgb`, `document.export`) stay as they are.
|
||||
@msg no library `{id}` keine Bibliothek `{id}`
|
||||
@msg the library has another item of that kind named `{name}` die Bibliothek hat bereits ein anderes Element dieser Art namens `{name}`
|
||||
@msg select some type first wählen Sie zuerst Text aus
|
||||
@msg kerning must be a number, "auto", or "optical" kerning muss eine Zahl, „auto“ oder „optical“ sein
|
||||
@msg the selection has no gradient fill die Auswahl hat keinen Flächenverlauf
|
||||
@@ -5124,6 +5125,8 @@ theme Appearance Erscheinungsbild
|
||||
Rename Library Group Bibliotheksgruppe umbenennen
|
||||
Delete Library Group Bibliotheksgruppe löschen
|
||||
Move Library Item to Group Bibliothekselement in Gruppe verschieben
|
||||
Rename Library Item Bibliothekselement umbenennen
|
||||
Add to Character Styles Zu Zeichenformaten hinzufügen
|
||||
Import Library Bibliothek importieren
|
||||
Export Library Bibliothek exportieren
|
||||
New Group Neue Gruppe
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2266,6 +2266,7 @@ axis Both Και τα δύο
|
||||
Document Options Επιλογές εγγράφου
|
||||
Dock Control Bar Αγκύρωση γραμμής ελέγχου
|
||||
@msg no library `{id}` Δεν υπάρχει βιβλιοθήκη με αναγνωριστικό `{id}`
|
||||
@msg the library has another item of that kind named `{name}` η βιβλιοθήκη έχει ήδη άλλο στοιχείο αυτού του είδους με όνομα `{name}`
|
||||
@msg select some type first Επιλέξτε πρώτα κάποιο κείμενο
|
||||
@msg kerning must be a number, "auto", or "optical" το kerning πρέπει να είναι αριθμός, «auto» ή «optical»
|
||||
@msg the selection has no gradient fill η επιλογή δεν έχει ντεγκραντέ γεμίσματος
|
||||
@@ -4051,6 +4052,8 @@ digits Malayalam Μαλαγιάλαμ
|
||||
Rename Library Group Μετονομασία ομάδας βιβλιοθήκης
|
||||
Delete Library Group Διαγραφή ομάδας βιβλιοθήκης
|
||||
Move Library Item to Group Μετακίνηση στοιχείου βιβλιοθήκης σε ομάδα
|
||||
Rename Library Item Μετονομασία στοιχείου βιβλιοθήκης
|
||||
Add to Character Styles Προσθήκη στα στυλ χαρακτήρων
|
||||
Rename Library Μετονομασία βιβλιοθήκης
|
||||
Show Library Εμφάνιση βιβλιοθήκης
|
||||
Use Library Item Χρήση στοιχείου βιβλιοθήκης
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -3583,6 +3583,8 @@ digits Malayalam Malayálam
|
||||
Rename Library Group Cambiar nombre del grupo de biblioteca
|
||||
Delete Library Group Eliminar grupo de biblioteca
|
||||
Move Library Item to Group Mover elemento de la biblioteca al grupo
|
||||
Rename Library Item Cambiar nombre del elemento de la biblioteca
|
||||
Add to Character Styles Agregar a estilos de carácter
|
||||
Library Biblioteca
|
||||
Rename Library Cambiar nombre de la biblioteca
|
||||
Show Library Mostrar biblioteca
|
||||
@@ -4167,6 +4169,7 @@ axis Both Ambos
|
||||
# (`untranslated_report` lists any that are missing). Command ids, parameter
|
||||
# names and values in backticks or code (`colorModel rgb`, `document.export`) stay as they are.
|
||||
@msg no library `{id}` no hay ninguna biblioteca `{id}`
|
||||
@msg the library has another item of that kind named `{name}` la biblioteca ya tiene otro elemento de ese tipo llamado `{name}`
|
||||
@msg select some type first selecciona primero algún texto
|
||||
@msg kerning must be a number, "auto", or "optical" kerning debe ser un número, «auto» u «optical»
|
||||
@msg the selection has no gradient fill la selección no tiene un degradado de relleno
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3542,6 +3542,8 @@ theme Appearance Ulkoasu
|
||||
Rename Library Group Nimeä kirjastoryhmä uudelleen
|
||||
Delete Library Group Poista kirjastoryhmä
|
||||
Move Library Item to Group Siirrä kirjaston kohde ryhmään
|
||||
Rename Library Item Nimeä kirjaston kohde uudelleen
|
||||
Add to Character Styles Lisää merkkityyleihin
|
||||
Rename Library Nimeä kirjasto uudelleen
|
||||
Show Library Näytä kirjasto
|
||||
Use Library Item Käytä kirjaston kohdetta
|
||||
@@ -4392,6 +4394,7 @@ imageTrace Outline Ääriviiva
|
||||
@plural {n} step|{n} steps {n} vaihe|{n} vaihetta
|
||||
@plural {n} stroke|{n} strokes {n} viiva|{n} viivaa
|
||||
@msg no library `{id}` ei kirjastoa `{id}`
|
||||
@msg the library has another item of that kind named `{name}` kirjastossa on jo toinen samanlainen kohde nimeltä `{name}`
|
||||
@msg select some type first valitse ensin tekstiä
|
||||
@msg kerning must be a number, "auto", or "optical" kerning-arvon on oltava luku, ”auto” tai ”optical”
|
||||
@msg the selection has no gradient fill valinnalla ei ole liukuväritäyttöä
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3575,6 +3575,8 @@ digits Malayalam Malayalam
|
||||
Rename Library Group Renommer le groupe de bibliothèque
|
||||
Delete Library Group Supprimer le groupe de bibliothèque
|
||||
Move Library Item to Group Déplacer l’élément de la bibliothèque vers un groupe
|
||||
Rename Library Item Renommer l’élément de la bibliothèque
|
||||
Add to Character Styles Ajouter aux styles de caractère
|
||||
Library Bibliothèque
|
||||
Rename Library Renommer la bibliothèque
|
||||
Show Library Afficher la bibliothèque
|
||||
@@ -4156,6 +4158,7 @@ axis Both Les deux
|
||||
# (`untranslated_report` lists any that are missing). Command ids, parameter
|
||||
# names and values in backticks or code (`colorModel rgb`, `document.export`) stay as they are.
|
||||
@msg no library `{id}` aucune bibliothèque `{id}`
|
||||
@msg the library has another item of that kind named `{name}` la bibliothèque a déjà un autre élément de ce type nommé `{name}`
|
||||
@msg select some type first sélectionnez d’abord du texte
|
||||
@msg kerning must be a number, "auto", or "optical" kerning doit être un nombre, « auto » ou « optical »
|
||||
@msg the selection has no gradient fill la sélection n’a pas de dégradé de fond
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2873,6 +2873,8 @@ antiAlias Sharp शार्प
|
||||
Move in Perspective पर्सपेक्टिव में मूव करें
|
||||
Move Library Group लाइब्रेरी ग्रुप मूव करें
|
||||
Move Library Item to Group लाइब्रेरी आइटम को ग्रुप में मूव करें
|
||||
Rename Library Item लाइब्रेरी आइटम का नाम बदलें
|
||||
Add to Character Styles कैरेक्टर स्टाइल्स में जोड़ें
|
||||
Move Locked and Hidden Artwork with Artboard आर्टबोर्ड के साथ लॉक्ड और छिपा हुआ आर्टवर्क मूव करें
|
||||
Move Mesh Point मेश पॉइंट मूव करें
|
||||
Move Mesh Points मेश पॉइंट मूव करें
|
||||
@@ -7234,6 +7236,7 @@ antiAlias Sharp शार्प
|
||||
@msg no layer {id} (see layer.list) कोई लेयर {id} (layer.list देखें)
|
||||
@msg no layers to export निर्यात करने के लिए कोई लेयरें नहीं
|
||||
@msg no library `{id}` नहीं लाइब्रेरी `{id}`
|
||||
@msg the library has another item of that kind named `{name}` लाइब्रेरी में इस प्रकार का एक और आइटम `{name}` नाम से पहले से है
|
||||
@msg no library `{key}` नहीं लाइब्रेरी `{key}`
|
||||
@msg no library `{key}` (see {list}) कोई लाइब्रेरी `{key}` ({list} देखें)
|
||||
@msg No line breaks to remove हटाने के लिए कोई लाइन ब्रेक नहीं
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -2605,6 +2605,8 @@ file-filter Templates Sablonok
|
||||
Move Guide to Layer Segédvonal áthelyezése rétegre
|
||||
Move in Perspective Áthelyezés perspektívában
|
||||
Move Library Item to Group Könyvtárelem áthelyezése csoportba
|
||||
Rename Library Item Könyvtárelem átnevezése
|
||||
Add to Character Styles Hozzáadás a karakterstílusokhoz
|
||||
Move Locked and Hidden Artwork with Artboard Zárolt és rejtett grafika mozgatása a rajztáblával
|
||||
Move Mesh Point Hálópont áthelyezése
|
||||
Move Mesh Points Hálópontok áthelyezése
|
||||
@@ -5314,6 +5316,7 @@ imageTrace Outline Körvonal
|
||||
@msg no interaction in progress nincs folyamatban lévő művelet
|
||||
@msg no key object nincs kulcsobjektum
|
||||
@msg no library `{id}` nincs ilyen könyvtár: `{id}`
|
||||
@msg the library has another item of that kind named `{name}` a könyvtárban már van egy másik ilyen fajta elem `{name}` néven
|
||||
@msg no library `{key}` (see {list}) nincs ilyen könyvtár: `{key}` (lásd: {list})
|
||||
@msg no Live Paint edge near that point annál a pontnál nincs élőfestés-él
|
||||
@msg no Live Paint face at that point annál a pontnál nincs élőfestés-felület
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3337,6 +3337,8 @@ theme Appearance Tampilan
|
||||
Rename Library Group Ganti nama grup pustaka
|
||||
Delete Library Group Hapus grup pustaka
|
||||
Move Library Item to Group Pindahkan item pustaka ke grup
|
||||
Rename Library Item Ganti nama item pustaka
|
||||
Add to Character Styles Tambahkan ke gaya karakter
|
||||
Rename Library Ganti nama pustaka
|
||||
Show Library Tampilkan pustaka
|
||||
Use Library Item Gunakan item pustaka
|
||||
@@ -4183,6 +4185,7 @@ imageTrace Outline Kontur
|
||||
@plural {n} step|{n} steps {n} langkah
|
||||
@plural {n} stroke|{n} strokes {n} goresan
|
||||
@msg no library `{id}` tidak ada pustaka `{id}`
|
||||
@msg the library has another item of that kind named `{name}` pustaka sudah memiliki item lain dari jenis itu bernama `{name}`
|
||||
@msg select some type first pilih beberapa teks terlebih dahulu
|
||||
@msg kerning must be a number, "auto", or "optical" kerning harus berupa angka, “auto”, atau “optical”
|
||||
@msg {_1} has no {_2} style {_1} tidak memiliki gaya {_2}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2418 and column 5.
|
@@ -3628,6 +3628,8 @@ digits Malayalam Malayalam
|
||||
Rename Library Group Rinomina gruppo di libreria
|
||||
Delete Library Group Elimina gruppo di libreria
|
||||
Move Library Item to Group Sposta elemento della libreria nel gruppo
|
||||
Rename Library Item Rinomina elemento della libreria
|
||||
Add to Character Styles Aggiungi agli stili carattere
|
||||
Library Libreria
|
||||
Rename Library Rinomina libreria
|
||||
Show Library Mostra libreria
|
||||
@@ -4218,6 +4220,7 @@ axis Both Entrambi
|
||||
# (`untranslated_report` lists any that are missing). Command ids, parameter
|
||||
# names and values in backticks or code (`colorModel rgb`, `document.export`) stay as they are.
|
||||
@msg no library `{id}` nessuna libreria `{id}`
|
||||
@msg the library has another item of that kind named `{name}` la libreria ha già un altro elemento di questo tipo chiamato `{name}`
|
||||
@msg select some type first seleziona prima del testo
|
||||
@msg kerning must be a number, "auto", or "optical" kerning deve essere un numero, «auto» o «optical»
|
||||
@msg the selection has no gradient fill la selezione non ha una sfumatura di riempimento
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3364,6 +3364,8 @@ mark-style Japanese 日本式
|
||||
Rename Library Group ライブラリグループ名を変更
|
||||
Delete Library Group ライブラリグループを削除
|
||||
Move Library Item to Group ライブラリ項目をグループに移動
|
||||
Rename Library Item ライブラリ項目名を変更
|
||||
Add to Character Styles 文字スタイルに追加
|
||||
Library ライブラリ
|
||||
Rename Library ライブラリ名を変更
|
||||
Show Library ライブラリを表示
|
||||
@@ -4491,6 +4493,7 @@ swatch Bright Violet ビビッドバイオレット
|
||||
@msg the layer to flatten into is hidden 統合先のレイヤーが非表示になっています
|
||||
@msg there are no objects to release レイヤーに分配するオブジェクトがありません
|
||||
@msg no library `{id}` ライブラリ `{id}` が見つかりません
|
||||
@msg the library has another item of that kind named `{name}` ライブラリには同じ種類の項目 `{name}` がすでにあります
|
||||
@msg {path}: not a file {path}: ファイルではありません
|
||||
@msg {path}: {e} {path}: {e}
|
||||
@msg can't write .{ext} images .{ext} 画像は書き出せません
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3183,6 +3183,8 @@ theme Appearance იერსახე
|
||||
Rename Library Group ბიბლიოთეკის ჯგუფის სახელის შეცვლა
|
||||
Delete Library Group ბიბლიოთეკის ჯგუფის წაშლა
|
||||
Move Library Item to Group ბიბლიოთეკის ელემენტის ჯგუფში გადატანა
|
||||
Rename Library Item ბიბლიოთეკის ელემენტის სახელის შეცვლა
|
||||
Add to Character Styles სიმბოლოს სტილებში დამატება
|
||||
Rename Library ბიბლიოთეკის სახელის შეცვლა
|
||||
Show Library ბიბლიოთეკის ჩვენება
|
||||
Use Library Item ბიბლიოთეკის ელემენტის გამოყენება
|
||||
@@ -3986,6 +3988,7 @@ font-technology Variable ცვლადი
|
||||
@plural {n} step|{n} steps ნაბიჯი: {n}
|
||||
@plural {n} stroke|{n} strokes კონტური: {n}
|
||||
@msg no library `{id}` ბიბლიოთეკა `{id}` არ არსებობს
|
||||
@msg the library has another item of that kind named `{name}` ბიბლიოთეკას უკვე აქვს ამ ტიპის სხვა ელემენტი სახელით `{name}`
|
||||
@msg select some type first ჯერ მონიშნეთ ტექსტი
|
||||
@msg kerning must be a number, "auto", or "optical" kerning უნდა იყოს რიცხვი, „auto“ ან „optical“
|
||||
@msg the selection has no gradient fill მონიშნულს შევსების გრადიენტი არ აქვს
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -3353,6 +3353,8 @@ mark-style Japanese 일본식
|
||||
Rename Library Group 라이브러리 그룹 이름 바꾸기
|
||||
Delete Library Group 라이브러리 그룹 삭제
|
||||
Move Library Item to Group 라이브러리 항목을 그룹으로 이동
|
||||
Rename Library Item 라이브러리 항목 이름 바꾸기
|
||||
Add to Character Styles 문자 스타일에 추가
|
||||
Library 라이브러리
|
||||
Rename Library 라이브러리 이름 바꾸기
|
||||
Show Library 라이브러리 표시
|
||||
@@ -4418,6 +4420,7 @@ theme Appearance 외관
|
||||
@msg the layer to flatten into is hidden 병합 대상 레이어가 숨겨져 있습니다
|
||||
@msg there are no objects to release 해제할 개체가 없습니다
|
||||
@msg no library `{id}` `{id}` 라이브러리가 없습니다
|
||||
@msg the library has another item of that kind named `{name}` 라이브러리에 같은 종류의 다른 항목 `{name}`이(가) 이미 있습니다
|
||||
@msg {path}: not a file {path}: 파일이 아닙니다
|
||||
@msg {path}: {e} {path}: {e}
|
||||
@msg can't write .{ext} images .{ext} 이미지는 쓸 수 없습니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -25,6 +25,507 @@
|
||||
@msg {key} must be [x, y] with finite coordinates {key} moet [x, y] met eindige coördinaten zijn
|
||||
@msg ids must contain 1–10000 object ids ids moet 1–10000 object-id’s bevatten
|
||||
|
||||
# Status and error messages: 3D assets, type on a path, scripts and their File and $ objects, presets,
|
||||
# PDF page sizes, Objects on Path, plug-ins, file readers and data sets. Names in backticks, command ids,
|
||||
# double-quoted values and bare true, false and null stay as the English writes them; names the user
|
||||
# gave are quoted „…”, and numbers use a period between thousands (2.048).
|
||||
@msg {what} can't be exported in 3D: {e} {what} kan niet in 3D worden geëxporteerd: {e}
|
||||
@msg asset {id} isn't a 3D asset asset {id} is geen 3D-asset
|
||||
@msg asset {id} is a 3D asset: assets.export3D writes it asset {id} is een 3D-asset: assets.export3D schrijft het weg
|
||||
@msg no 3D assets yet: collect an object with a 3D effect first (assets.add3D) nog geen 3D-assets: verzamel eerst een object met een 3D-effect (assets.add3D)
|
||||
@msg select an object with a 3D effect (or give its ids) selecteer een object met een 3D-effect (of geef de id’s ervan)
|
||||
@msg select point type or type on a path selecteer punttekst of tekst op een pad
|
||||
@msg type on a path in a thread cannot use Dynamic Text: {frames} tekst op een pad in gekoppelde tekst kan geen dynamische tekst gebruiken: {frames}
|
||||
@msg type on an open or compound path cannot be centered on its top or bottom: {open} tekst op een open of samengesteld pad kan niet op de boven- of onderkant worden gecentreerd: {open}
|
||||
@msg type on a path with no length or no height cannot be centered: {flat} tekst op een pad zonder lengte of hoogte kan niet worden gecentreerd: {flat}
|
||||
@msg type on a path in a thread cannot be centered on its top or bottom: {frames} tekst op een pad in gekoppelde tekst kan niet op de boven- of onderkant worden gecentreerd: {frames}
|
||||
@msg select type on a closed path selecteer tekst op een gesloten pad
|
||||
@msg `Custom` stands for changed settings: save the preset under another name `Custom` staat voor gewijzigde instellingen: sla de voorinstelling onder een andere naam op
|
||||
@msg the selection has no gradient fill de selectie heeft geen verloopvulling
|
||||
@msg the selection has no gradient stroke de selectie heeft geen verloopcontour
|
||||
@msg the selection has no pattern fill de selectie heeft geen patroonvulling
|
||||
@msg the selection has no pattern stroke de selectie heeft geen patrooncontour
|
||||
@msg no gradient swatch `{name}` geen verloopstaal `{name}`
|
||||
@msg no pattern swatch `{name}` geen patroonstaal `{name}`
|
||||
@msg the library item is damaged het bibliotheekitem is beschadigd
|
||||
@msg its zlib compression is damaged de zlib-compressie ervan is beschadigd
|
||||
@msg its Zstandard compression is damaged de Zstandard-compressie ervan is beschadigd
|
||||
@msg it decompresses to more than {_1} MB gedecomprimeerd is het groter dan {_1} MB
|
||||
@msg its editing data is for a different page zijn bewerkingsgegevens horen bij een andere pagina
|
||||
@msg `fontHeightReference` must be "emBox", "capHeight", "xHeight" or "icfBox" `fontHeightReference` moet "emBox", "capHeight", "xHeight" of "icfBox" zijn
|
||||
@msg Choose a .js or .jsx script Kies een .js- of .jsx-script
|
||||
@msg Ran {name} {name} uitgevoerd
|
||||
@msg The script was stopped and its changes were undone Het script is gestopt en de wijzigingen ervan zijn ongedaan gemaakt
|
||||
@msg a script is running: stop it or wait for it to finish er wordt een script uitgevoerd: stop het of wacht tot het klaar is
|
||||
@msg this is a compiled script, which cannot be run; use its source text dit is een gecompileerd script, dat niet kan worden uitgevoerd; gebruik de brontekst ervan
|
||||
@msg the script is not UTF-8 text het script is geen UTF-8-tekst
|
||||
@msg the script is too large to run het script is te groot om uit te voeren
|
||||
@msg a drag or an undo group is open; finish it before running a script er is nog een sleepbeweging of een groep voor ongedaan maken open; rond die af voordat je een script uitvoert
|
||||
@msg the script left a document that cannot be kept het script heeft een document achtergelaten dat niet kan worden behouden
|
||||
@msg the script is no longer in the Scripts folder het script staat niet meer in de map Scripts
|
||||
@msg the script's run is no longer available de uitvoering van het script is niet meer beschikbaar
|
||||
@msg a failed command changed undo steps that could not be put back, so the script was stopped een mislukte opdracht heeft stappen voor ongedaan maken gewijzigd die niet konden worden teruggezet, dus is het script gestopt
|
||||
@msg a recovery copy could not be written, so the script was not run er kon geen herstelkopie worden geschreven, dus is het script niet uitgevoerd
|
||||
@msg Script file access denied Toegang tot het scriptbestand geweigerd
|
||||
@msg Script file exceeds 8 MiB Het scriptbestand is groter dan 8 MiB
|
||||
@msg Script file is not open Het scriptbestand is niet geopend
|
||||
@msg Script file cannot be decoded Het scriptbestand kan niet worden gedecodeerd
|
||||
@msg Script file is not a regular file Het scriptbestand is geen gewoon bestand
|
||||
@msg Script file does not exist Het scriptbestand bestaat niet
|
||||
@msg Script file could not be read Het scriptbestand kon niet worden gelezen
|
||||
@msg Script folder has more than 2,048 entries De scriptmap bevat meer dan 2.048 items
|
||||
@msg Script file open mode must be r, w, e or a De openmodus van een scriptbestand moet r, w, e of a zijn
|
||||
@msg Script file writing is not available Schrijven naar scriptbestanden is niet beschikbaar
|
||||
@msg Script file dialogs are not available Dialoogvensters voor scriptbestanden zijn niet beschikbaar
|
||||
@msg Script files cannot be opened in another application Scriptbestanden kunnen niet in een andere toepassing worden geopend
|
||||
@msg Script file access is unavailable on the web Toegang tot scriptbestanden is niet beschikbaar op het web
|
||||
@msg Script has 256 files open Het script heeft 256 bestanden geopend
|
||||
@msg Script file path exceeds 32,767 characters Het pad van het scriptbestand is langer dan 32.767 tekens
|
||||
@msg Script folder mask takes too many steps to match Het masker van de scriptmap vraagt te veel stappen om te vergelijken
|
||||
@msg the script opened more file data than one run may open (32 MiB) het script heeft meer bestandsgegevens geopend dan één uitvoering mag openen (32 MiB)
|
||||
@msg File.seek: takes a position and a mode File.seek: verwacht een positie en een modus
|
||||
@msg vc.run: give a command id, as a string vc.run: geef een opdracht-id, als string
|
||||
@msg vc.run: takes a command id and an object of parameters vc.run: verwacht een opdracht-id en een object met parameters
|
||||
@msg vc.run: the parameters must be an object vc.run: de parameters moeten een object zijn
|
||||
@msg vc.run: the result{place} is too large for a script vc.run: het resultaat{place} is te groot voor een script
|
||||
@msg $.evalFile requires a file path $.evalFile vereist een bestandspad
|
||||
@msg $.evalFile: the timeout must be a finite number of milliseconds, 0 or more $.evalFile: de time-out moet een eindig aantal milliseconden zijn, 0 of meer
|
||||
@msg $.evalFile: takes a file path and a timeout $.evalFile: verwacht een bestandspad en een time-out
|
||||
@msg {name}: line {line}, column {column} of {file}: {e} (thrown) {name}: regel {line}, kolom {column} van {file}: {e} (opgeworpen)
|
||||
@msg {name}: line {line}, column {column}: {e} (thrown) {name}: regel {line}, kolom {column}: {e} (opgeworpen)
|
||||
@msg {name}: {e} (thrown) {name}: {e} (opgeworpen)
|
||||
@msg {name}: line {line}, column {column} of {file}: {e} (limit) {name}: regel {line}, kolom {column} van {file}: {e} (limiet)
|
||||
@msg {name}: line {line}, column {column}: {e} (limit) {name}: regel {line}, kolom {column}: {e} (limiet)
|
||||
@msg {name}: {e} (limit) {name}: {e} (limiet)
|
||||
@msg {name}: line {line}, column {column} of {file}: {e} (syntax) {name}: regel {line}, kolom {column} van {file}: {e} (syntaxisfout)
|
||||
@msg {name}: line {line}, column {column}: {e} (syntax) {name}: regel {line}, kolom {column}: {e} (syntaxisfout)
|
||||
@msg {name}: {e} (syntax) {name}: {e} (syntaxisfout)
|
||||
@msg {name}: line {line}, column {column} of {file}: {e} (stopped) {name}: regel {line}, kolom {column} van {file}: {e} (gestopt)
|
||||
@msg {name}: line {line}, column {column}: {e} (stopped) {name}: regel {line}, kolom {column}: {e} (gestopt)
|
||||
@msg {name}: {e} (stopped) {name}: {e} (gestopt)
|
||||
@msg {name}: line {line}, column {column} of {file}: {e} (internal) {name}: regel {line}, kolom {column} van {file}: {e} (interne fout)
|
||||
@msg {name}: line {line}, column {column}: {e} (internal) {name}: regel {line}, kolom {column}: {e} (interne fout)
|
||||
@msg {name}: {e} (internal) {name}: {e} (interne fout)
|
||||
@msg {e} (these files stay written: {paths}) {e} (deze bestanden blijven geschreven: {paths})
|
||||
@msg $.{name}: give a name, as a string $.{name}: geef een naam, als string
|
||||
@msg $.locale: give a locale such as "en" or "de_DE", or null for the interface's $.locale: geef een landinstelling zoals "en" of "de_DE", of null voor die van de interface
|
||||
@msg $.localize: give true or false $.localize: geef true of false
|
||||
@msg $.flags: only 512, which turns localization on, or 0 can be set $.flags: alleen 512, dat lokalisatie inschakelt, of 0 kan worden ingesteld
|
||||
@msg $.flags: give a number $.flags: geef een getal
|
||||
@msg $.appEncoding: scripts here read and write UTF-8 only $.appEncoding: scripts lezen en schrijven hier alleen UTF-8
|
||||
@msg $.appEncoding: give an encoding's name, as a string $.appEncoding: geef de naam van een codering, als string
|
||||
@msg $.memCache: the memory cache size cannot be set $.memCache: de grootte van de geheugencache kan niet worden ingesteld
|
||||
@msg $.setenv: give a value, as a string $.setenv: geef een waarde, als string
|
||||
@msg $.setenv: only {_1} can be set $.setenv: alleen {_1} kan worden ingesteld
|
||||
@msg $.setenv: a value has at most {MAX_ENV_BYTES} letters, digits and _ . - @ $.setenv: een waarde heeft maximaal {MAX_ENV_BYTES} letters, cijfers en _ . - @
|
||||
@msg $.sleep: give a number of milliseconds from 0 to {MAX_SLEEP_MS} $.sleep: geef een aantal milliseconden van 0 tot {MAX_SLEEP_MS}
|
||||
@msg $.sleep: give a number of milliseconds $.sleep: geef een aantal milliseconden
|
||||
@msg $.sleep: a run cannot wait inside a callback of a built-in function, a getter, a conversion or a file $.evalFile runs; call it from the script's own code $.sleep: een uitvoering kan niet wachten binnen een callback van een ingebouwde functie, een getter, een conversie of een bestand dat $.evalFile uitvoert; roep het aan vanuit de eigen code van het script
|
||||
@msg $.bp: scripts here have no debugger $.bp: scripts hebben hier geen debugger
|
||||
@msg $.colorPicker: scripts cannot show a dialog yet $.colorPicker: scripts kunnen nog geen dialoogvenster tonen
|
||||
@msg {name}: give a message {name}: geef een bericht
|
||||
@msg {name}: give the text the field starts with {name}: geef de tekst waarmee het veld begint
|
||||
@msg {name}: the message is longer than 16 KiB {name}: het bericht is langer dan 16 KiB
|
||||
@msg {name}: the title is longer than 256 bytes {name}: de titel is langer dan 256 bytes
|
||||
@msg {name}: the text the field starts with is longer than 16 KiB {name}: de tekst waarmee het veld begint is langer dan 16 KiB
|
||||
@msg {name}: a dialog cannot open inside a callback of a built-in function, a getter, a conversion or a file $.evalFile runs; call it from the script's own code {name}: een dialoogvenster kan niet openen binnen een callback van een ingebouwde functie, een getter, een conversie of een bestand dat $.evalFile uitvoert; roep het aan vanuit de eigen code van het script
|
||||
@msg {name}: the next answer in `answers` is for {_1}, not {name} {name}: het volgende antwoord in `answers` is voor {_1}, niet voor {name}
|
||||
@msg {name}: `answers` has no answer left for this dialog {name}: `answers` heeft geen antwoord meer voor dit dialoogvenster
|
||||
@msg vc.document{place} is too large for a script vc.document{place} is te groot voor een script
|
||||
@msg vc.log: the log of this run is full vc.log: het logboek van deze uitvoering is vol
|
||||
@msg this function's script run has ended de scriptuitvoering van deze functie is beëindigd
|
||||
@msg the script made more host calls than one run may make het script heeft meer hostaanroepen gedaan dan één uitvoering mag doen
|
||||
@msg the script passed more data to and from commands than one run may pass het script heeft meer gegevens van en naar opdrachten doorgegeven dan één uitvoering mag doorgeven
|
||||
@msg the script added more objects and data to the documents than one run may add het script heeft meer objecten en gegevens aan de documenten toegevoegd dan één uitvoering mag toevoegen
|
||||
@msg {what}: the object is not a File or a Folder {what}: het object is geen File of Folder
|
||||
@msg {what}: the count must be a finite number, 0 or more {what}: het aantal moet een eindig getal zijn, 0 of meer
|
||||
@msg File.seek: the position must be a finite number File.seek: de positie moet een eindig getal zijn
|
||||
@msg File.seek: the mode must be 0, 1 or 2 File.seek: de modus moet 0, 1 of 2 zijn
|
||||
@msg script file is compiled: {value} het scriptbestand is gecompileerd: {value}
|
||||
@msg `name` must be the name of a script engine `name` moet de naam van een scriptengine zijn
|
||||
@msg the main script engine is new for each run and is never kept, so it cannot be dropped de hoofdscriptengine is bij elke uitvoering nieuw en wordt nooit bewaard, dus kan hij niet worden verwijderd
|
||||
@msg there is no script engine named {name} er is geen scriptengine met de naam {name}
|
||||
@msg Running a script Er wordt een script uitgevoerd
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Gegevensherstel kan geen kopieën bewaren in {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Plug-ins kunnen niet worden geladen uit {path}: {e}
|
||||
@msg aiVersion 7 writes legacy .ai files, not .ait templates aiVersion 7 schrijft verouderde .ai-bestanden, geen .ait-sjablonen
|
||||
@msg `groupColors` must be an array `groupColors` moet een array zijn
|
||||
@msg `preserve` must be an object `preserve` moet een object zijn
|
||||
@msg `{key}` must be an array `{key}` moet een array zijn
|
||||
@msg `{key}` must be a profile name or null `{key}` moet een profielnaam of null zijn
|
||||
@msg `top` and `below` can't both be true `top` en `below` kunnen niet allebei true zijn
|
||||
@msg `select` must be true or false `select` moet true of false zijn
|
||||
@msg `minAnchors` and `maxAnchors` must be whole numbers `minAnchors` en `maxAnchors` moeten gehele getallen zijn
|
||||
@msg `{key}` must be a number not below 0 `{key}` moet een getal van minstens 0 zijn
|
||||
@msg `{key}` must be [x, y, width, height]: four finite numbers, width and height not negative `{key}` moet [x, y, width, height] zijn: vier eindige getallen, width en height niet negatief
|
||||
@msg `{min_key}` is greater than `{max_key}` `{min_key}` is groter dan `{max_key}`
|
||||
@msg give at least one of `name`, `kind`, `text`, `within`, `intersects`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`, `minThickness`, `maxThickness`, `minArea`, `maxArea`, `minAnchors`, `maxAnchors` geef minstens een van `name`, `kind`, `text`, `within`, `intersects`, `minWidth`, `maxWidth`, `minHeight`, `maxHeight`, `minThickness`, `maxThickness`, `minArea`, `maxArea`, `minAnchors`, `maxAnchors`
|
||||
@msg a process color can't colorize a grayscale image with transparency: use a spot color, black or white een proceskleur kan een grijswaardenafbeelding met transparantie niet inkleuren: gebruik een steunkleur, zwart of wit
|
||||
@msg `name` is empty `name` is leeg
|
||||
@msg `newName` is empty `newName` is leeg
|
||||
@msg `{name}` is a built-in preset and can't change: save it under another name `{name}` is een ingebouwde voorinstelling en kan niet worden gewijzigd: sla hem onder een andere naam op
|
||||
@msg `{name}` is a built-in preset and stays `{name}` is een ingebouwde voorinstelling en blijft bestaan
|
||||
@msg `guideLabel` is null, a layer color's name or #rrggbb `guideLabel` is null, de naam van een laagkleur of #rrggbb
|
||||
@msg the Simplify slider is not open de schuifregelaar Vereenvoudigen is niet geopend
|
||||
@msg the Smooth slider is not open de schuifregelaar Gladmaken is niet geopend
|
||||
@msg the page of artboard {n} is {size}, longer than PDF's page limit of 14,400 pt (200 in): it is written with a UserUnit of {unit}, so apps that ignore UserUnit show it that many times smaller de pagina van tekengebied {n} is {size}, langer dan de paginalimiet van PDF van 14.400 pt (200 in): hij wordt geschreven met een UserUnit van {unit}, dus apps die UserUnit negeren tonen hem zoveel keer kleiner
|
||||
@msg the page of artboard {n} is {size}, longer than PDF's page limit of 14,400 pt (200 in): {label} pages are written without a UserUnit, in points, and apps that keep to the limit cut the page to 200 in de pagina van tekengebied {n} is {size}, langer dan de paginalimiet van PDF van 14.400 pt (200 in): {label}-pagina’s worden zonder UserUnit in punten geschreven, en apps die zich aan de limiet houden snijden de pagina af op 200 in
|
||||
@msg PDF 1.5 has no UserUnit, which a page longer than 14,400 pt (200 in) needs to keep its size: the file is written as PDF 1.6 PDF 1.5 heeft geen UserUnit, die een pagina langer dan 14.400 pt (200 in) nodig heeft om zijn formaat te behouden: het bestand wordt geschreven als PDF 1.6
|
||||
@msg PDF 1.4 has no UserUnit, which a page longer than 14,400 pt (200 in) needs to stay within PDF/A-2's page limit of 14,400 units: the file is written as PDF 1.6 PDF 1.4 heeft geen UserUnit, die een pagina langer dan 14.400 pt (200 in) nodig heeft om binnen de paginalimiet van PDF/A-2 van 14.400 eenheden te blijven: het bestand wordt geschreven als PDF 1.6
|
||||
@msg the page of artboard {n} is {size}, too long and narrow for PDF's page sides of 3 to 14,400 units: it is written with a UserUnit of {unit}, which keeps the short side at 3 units or more, and apps that keep to the limit cut the long side to 14,400 units de pagina van tekengebied {n} is {size}, te lang en te smal voor paginazijden van PDF van 3 tot 14.400 eenheden: hij wordt geschreven met een UserUnit van {unit}, die de korte zijde op minstens 3 eenheden houdt, en apps die zich aan de limiet houden snijden de lange zijde af op 14.400 eenheden
|
||||
@msg {label} files hold real numbers up to {max}, and the page of artboard {n}, {side} pt long, needs larger ones: choose PDF 1.6 or later without a PDF/X standard, or a smaller artboard {label}-bestanden bevatten reële getallen tot {max}, en de pagina van tekengebied {n}, {side} pt lang, heeft grotere nodig: kies PDF 1.6 of later zonder PDF/X-standaard, of een kleiner tekengebied
|
||||
@msg line {line}: value for `{var}` must be true or false regel {line}: de waarde voor `{var}` moet true of false zijn
|
||||
@msg line {line}: value for `{var}` is longer than {MAX_GRAPH_CSV} bytes regel {line}: de waarde voor `{var}` is langer dan {MAX_GRAPH_CSV} bytes
|
||||
@msg a bristle brush name can have at most {max} characters: `{name}` has {count} de naam van een borstelpenseel mag maximaal {max} tekens hebben: `{name}` heeft er {count}
|
||||
@msg `{file}` isn't a VectorCraft document, a PDF or a PDF-compatible .ai file `{file}` is geen VectorCraft-document, geen PDF en geen PDF-compatibel .ai-bestand
|
||||
@msg no saved preset named `{name}` geen opgeslagen voorinstelling met de naam `{name}`
|
||||
@msg no saved preset named `{name}` to rename geen opgeslagen voorinstelling met de naam `{name}` om te hernoemen
|
||||
@msg `{ID}`: the reference would be larger than {MAX_BYTES} bytes `{ID}`: de verwijzing zou groter worden dan {MAX_BYTES} bytes
|
||||
@msg the artboard is locked het tekengebied is vergrendeld
|
||||
@msg node {_1} is on a locked artboard knooppunt {_1} staat op een vergrendeld tekengebied
|
||||
@msg thumbnail: no page {n} (the file has 1) miniatuur: geen pagina {n} (het bestand heeft er 1)
|
||||
@msg select an Objects on Path group selecteer een groep Objecten op pad
|
||||
@msg a path inside a compound path, blend, envelope, repeat or Intertwine group can't take objects een pad binnen een samengesteld pad, mengsel, omvorming, herhaling of verstrengelingsgroep kan geen objecten opnemen
|
||||
@msg a clipping path can't take objects een knippad kan geen objecten opnemen
|
||||
@msg objects inside a blend, envelope, repeat or Intertwine group can't be attached to a path objecten binnen een mengsel, omvorming, herhaling of verstrengelingsgroep kunnen niet aan een pad worden gekoppeld
|
||||
@msg a clipping path can't be attached to a path een knippad kan niet aan een pad worden gekoppeld
|
||||
@msg `background` must be edges, corners or colors `background` moet edges, corners of colors zijn
|
||||
@msg `match` must be distance or channels `match` moet distance of channels zijn
|
||||
@msg `{key}` must be from 0 to 100 `{key}` moet van 0 tot 100 zijn
|
||||
@msg `colors` must list 1 to 16 colors, each hex (#rrggbb or #rgb) or black, white, red, green or blue `colors` moet 1 tot 16 kleuren bevatten, elk hexadecimaal (#rrggbb of #rgb) of black, white, red, green of blue
|
||||
@msg the linked image shows its preview: embed or relink it first de gekoppelde afbeelding toont haar voorvertoning: sluit haar eerst in of koppel haar opnieuw
|
||||
@msg a CMYK image has no transparency to set een CMYK-afbeelding heeft geen transparantie om in te stellen
|
||||
@msg every pixel matches the background: no image would be left elke pixel komt overeen met de achtergrond: er zou geen afbeelding overblijven
|
||||
@msg an image of {w} × {h} pixels is too large to change een afbeelding van {w} × {h} pixels is te groot om te wijzigen
|
||||
@msg select an image with a color mask selecteer een afbeelding met een kleurmasker
|
||||
@msg the color mask's settings are out of range de instellingen van het kleurmasker vallen buiten het bereik
|
||||
@msg a CMYK image can't take a color mask een CMYK-afbeelding kan geen kleurmasker krijgen
|
||||
@msg the mask would hide every pixel het masker zou elke pixel verbergen
|
||||
@msg Recolor completed; {locked} and {hidden} were left unchanged Herkleuren voltooid; ongewijzigd gelaten: {locked} en {hidden}
|
||||
@msg Recolor completed; {objects} were left unchanged Herkleuren voltooid; ongewijzigd gelaten: {objects}
|
||||
@msg Recolor completed; {objects} was left unchanged Herkleuren voltooid; ongewijzigd gelaten: {objects}
|
||||
@msg 1 locked object 1 vergrendeld element
|
||||
@msg {n} locked objects {n} vergrendelde elementen
|
||||
@msg 1 hidden object 1 verborgen element
|
||||
@msg {n} hidden objects {n} verborgen elementen
|
||||
@msg panels can't be shown in Presentation Mode panelen kunnen niet worden getoond in de presentatiemodus
|
||||
@msg unknown preset `{name}`: not a built-in or saved preset (see imageTrace.presets) onbekende voorinstelling `{name}`: geen ingebouwde of opgeslagen voorinstelling (zie imageTrace.presets)
|
||||
@msg more than {MAX_CSV_ROWS} data sets: Import Data Sets reads at most {MAX_CSV_ROWS} meer dan {MAX_CSV_ROWS} gegevenssets: Gegevenssets importeren leest er maximaal {MAX_CSV_ROWS}
|
||||
@msg more than {MAX_CSV_COLS} variables: Import Data Sets reads at most {MAX_CSV_COLS} meer dan {MAX_CSV_COLS} variabelen: Gegevenssets importeren leest er maximaal {MAX_CSV_COLS}
|
||||
@msg `{key}: {top}` and `options.{key}: {inner}` disagree: give the option once `{key}: {top}` en `options.{key}: {inner}` spreken elkaar tegen: geef de optie één keer
|
||||
@msg {_1} is an exporter (File › Export › Export As…) {_1} is een exportplug-in (Bestand › Exporteren › Exporteren als…)
|
||||
@msg `documentData` is {size} bytes (limit {MAX_DOCUMENT_DATA}) `documentData` is {size} bytes (limiet {MAX_DOCUMENT_DATA})
|
||||
@msg a mask that covers several layers comes in as a clipping group in each layer it covers een masker dat meerdere lagen bedekt, wordt ingelezen als een knipgroep in elke laag die het bedekt
|
||||
@msg a graph's records don't end where they should: its art was read as it is de records van een grafiek eindigen niet waar ze zouden moeten: de illustratie ervan is gelezen zoals ze is
|
||||
@msg `{w}` takes no operands `{w}` neemt geen operanden
|
||||
@msg a wraparound group is inside a compound path een tekstomloopgroep staat binnen een samengesteld pad
|
||||
@msg it ends inside a multi-layer mask het eindigt binnen een masker over meerdere lagen
|
||||
@msg a multi-layer mask's operators are out of order de operatoren van een masker over meerdere lagen staan in de verkeerde volgorde
|
||||
@msg a multi-layer mask needs one clipping path een masker over meerdere lagen heeft één knippad nodig
|
||||
@msg a group crosses a multi-layer mask een groep doorkruist een masker over meerdere lagen
|
||||
@msg graphs come in as plain art, without their data or settings grafieken worden ingelezen als gewone illustraties, zonder hun gegevens of instellingen
|
||||
@msg source must be the id of a Shaper Group's original shape source moet de id van de oorspronkelijke vorm van een Shapergroep zijn
|
||||
@msg group must be the id of a Shaper Group group moet de id van een Shapergroep zijn
|
||||
@msg the shape is not an editable original shape of that Shaper Group de vorm is geen bewerkbare oorspronkelijke vorm van die Shapergroep
|
||||
@msg id {value} is a layer, not an object id {value} is een laag, geen object
|
||||
@msg id {value} is a layer, not an object; move layers with layer.move id {value} is een laag, geen object; verplaats lagen met layer.move
|
||||
@msg the PCX file is cut short het PCX-bestand is afgebroken
|
||||
@msg the PCX file's header is damaged de header van het PCX-bestand is beschadigd
|
||||
@msg PCX files with {bits}-bit pixels in {planes} planes can't be read PCX-bestanden met {bits}-bits pixels in {planes} vlakken kunnen niet worden gelezen
|
||||
@msg the Pixar file is cut short het Pixar-bestand is afgebroken
|
||||
@msg the Pixar file's header is damaged de header van het Pixar-bestand is beschadigd
|
||||
@msg the Pixar file's image data is damaged de afbeeldingsgegevens van het Pixar-bestand zijn beschadigd
|
||||
@msg the JPEG 2000 file can't be read het JPEG 2000-bestand kan niet worden gelezen
|
||||
@msg the JPEG 2000 file has an unsupported color space or JPX content het JPEG 2000-bestand heeft een niet-ondersteunde kleurruimte of JPX-inhoud
|
||||
@msg the HEIC or HEIF file can't be read het HEIC- of HEIF-bestand kan niet worden gelezen
|
||||
@msg the HEIC or HEIF file holds a kind of image that can't be read het HEIC- of HEIF-bestand bevat een soort afbeelding die niet kan worden gelezen
|
||||
@msg HEIC and HEIF images can't be opened in this build HEIC- en HEIF-afbeeldingen kunnen in deze build niet worden geopend
|
||||
@msg the JPEG XL file is cut short het JPEG XL-bestand is afgebroken
|
||||
@msg the JPEG XL container is too large to read de JPEG XL-container is te groot om te lezen
|
||||
@msg CMYK JPEG XL images can't be read CMYK-afbeeldingen in JPEG XL kunnen niet worden gelezen
|
||||
@msg the JPEG XL file can't be read: {e} het JPEG XL-bestand kan niet worden gelezen: {e}
|
||||
@msg the params must be an object, not {got} de parameters moeten een object zijn, niet {got}
|
||||
@msg unknown parameter `{path}`; the object takes no keys onbekende parameter `{path}`; het object accepteert geen sleutels
|
||||
@msg unknown parameter `{path}`; it takes: {keys} onbekende parameter `{path}`; het accepteert: {keys}
|
||||
@msg missing `{path}` `{path}` ontbreekt
|
||||
@msg `{path}` must be {expected}, not {got} `{path}` moet {expected} zijn, niet {got}
|
||||
@msg `{path}` is nested too deeply `{path}` is te diep genest
|
||||
@msg {path}: not a PNG, JPEG, WebP, TIFF or BMP image {path}: geen PNG-, JPEG-, WebP-, TIFF- of BMP-afbeelding
|
||||
@msg the image is {iw} × {ih} pixels and the artboard at that width is {rw} × {rh} pixels: their proportions differ de afbeelding is {iw} × {ih} pixels en het tekengebied is bij die breedte {rw} × {rh} pixels: hun verhoudingen verschillen
|
||||
@msg `threshold` must be a number from 0 to 1 `threshold` moet een getal van 0 tot 1 zijn
|
||||
@msg background {v}: a color such as "#808080" background {v}: een kleur zoals "#808080"
|
||||
@msg comparing with an image file isn't available in the browser vergelijken met een afbeeldingsbestand is niet beschikbaar in de browser
|
||||
@msg columns {first} and {column} both name the variable `{name}` kolommen {first} en {column} noemen allebei de variabele `{name}`
|
||||
@msg nothing in data set {name} was applied: no object is bound to a variable it has a value for niets uit gegevensset {name} is toegepast: geen enkel object is gekoppeld aan een variabele waarvoor de set een waarde heeft
|
||||
@msg no bound object reports a value (locked objects and embedded images report none) geen enkel gekoppeld object geeft een waarde (vergrendelde objecten en ingesloten afbeeldingen geven er geen)
|
||||
@msg Edit Original opens image and document files only; “{name}” is not one Origineel bewerken opent alleen afbeeldings- en documentbestanden; „{name}” is er geen
|
||||
@msg only http, https and mailto URLs open in the browser, not “{url}” alleen http-, https- en mailto-URL’s worden in de browser geopend, niet „{url}”
|
||||
@msg {id} opens another app: only the person at the keyboard can run it {id} opent een andere app: alleen de persoon achter het toetsenbord kan dit uitvoeren
|
||||
@msg “{name}” is not a file „{name}” is geen bestand
|
||||
@msg too many changed shortcuts te veel gewijzigde sneltoetsen
|
||||
@msg byColor must be true or false byColor moet true of false zijn
|
||||
@msg byColor can't split Auto Grouping groups: trace without Auto Grouping byColor kan groepen van Automatisch groeperen niet splitsen: traceer zonder Automatisch groeperen
|
||||
@msg byColor can't regroup a trace with a live Pathfinder effect: expand without byColor byColor kan een tracering met een live Padvinder-effect niet hergroeperen: vouw uit zonder byColor
|
||||
@msg `colorGroup` needs `library: "document"` `colorGroup` vereist `library: "document"`
|
||||
@msg `colorGroup` needs `palette: "documentLibrary"` `colorGroup` vereist `palette: "documentLibrary"`
|
||||
@msg `colorGroup` needs `mode: "color"` `colorGroup` vereist `mode: "color"`
|
||||
@msg no color group `{name}` in the document (see swatch.list) geen kleurgroep `{name}` in het document (zie swatch.list)
|
||||
@msg {label} keeps 1 of the document's {n} artboards: the file reopens with one. Turn on Preserve Editing Capabilities to keep them all. {label} behoudt 1 van de {n} tekengebieden van het document: het bestand wordt met één tekengebied opnieuw geopend. Schakel Bewerkbaarheid behouden in om ze allemaal te behouden.
|
||||
@msg `spread` must be pad, repeat or reflect `spread` moet pad, repeat of reflect zijn
|
||||
@msg `repeats` must be a whole number from 1 to {MAX_REPEATS} `repeats` moet een geheel getal van 1 tot {MAX_REPEATS} zijn
|
||||
@msg `spread` applies to linear, radial, conic and diamond gradients `spread` geldt voor lineaire, radiale, conische en ruitvormige verlopen
|
||||
@msg {_1} finished, but the document or the plug-in changed meanwhile: run it again {_1} is voltooid, maar het document of de plug-in is intussen gewijzigd: voer het opnieuw uit
|
||||
@msg Running “{name}”… „{name}” wordt uitgevoerd…
|
||||
@msg a live effect runs while the document is drawn, so it can't be `heavy` een live-effect wordt uitgevoerd terwijl het document wordt getekend, dus kan het niet `heavy` zijn
|
||||
@msg an exporter always gets an export's budget: leave `budget` out een exportplug-in krijgt altijd het budget van een export: laat `budget` weg
|
||||
@msg “{_1}” asks for a heavy budget (each run up to {minutes} minutes and {times} times the usual instructions): a person has to approve it in the desktop app, or pass `allowHeavy: true` in a session started with --allow-plugin-grants „{_1}” vraagt om een groot rekenbudget (elke uitvoering tot {minutes} minuten en {times} keer het gebruikelijke aantal instructies): een persoon moet dit goedkeuren in de desktop-app, of geef `allowHeavy: true` door in een sessie die is gestart met --allow-plugin-grants
|
||||
@msg `name` must be 1-64 printable characters `name` moet uit 1-64 afdrukbare tekens bestaan
|
||||
@msg `version`, `description` or `author` is too long `version`, `description` of `author` is te lang
|
||||
@msg `warnings` must be a list of strings `warnings` moet een lijst met strings zijn
|
||||
@msg `{k}` must be one of {_1} `{k}` moet een van {_1} zijn
|
||||
@msg `{k}` must be {what} `{k}` moet {what} zijn
|
||||
@msg an exporter declares 1 to {MAX_EXTENSIONS} `extensions` een exportplug-in declareert 1 tot {MAX_EXTENSIONS} `extensions`
|
||||
@msg at most {MAX_UNGROUPED} parameters outside groups: give the others a `group` maximaal {MAX_UNGROUPED} parameters buiten groepen: geef de andere een `group`
|
||||
@msg can't encode the input de invoer kan niet worden gecodeerd
|
||||
@msg expected {"dataBase64"} verwacht: {"dataBase64"}
|
||||
@msg expected {"objects"} verwacht: {"objects"}
|
||||
@msg export `{name}`: {e} export `{name}`: {e}
|
||||
@msg extension {e} is listed twice extensie {e} staat twee keer in de lijst
|
||||
@msg extension {e}: use 1-16 lower-case letters and digits, without the dot extensie {e}: gebruik 1-16 kleine letters en cijfers, zonder de punt
|
||||
@msg invalid id {_1}: use 1-64 characters from A-Z a-z 0-9 . _ - ongeldige id {_1}: gebruik 1-64 tekens uit A-Z a-z 0-9 . _ -
|
||||
@msg invalid parameter name {k} ongeldige parameternaam {k}
|
||||
@msg manifest is not UTF-8 het manifest is geen UTF-8
|
||||
@msg manifest is too long (limit {MAX_MANIFEST_BYTES} bytes) het manifest is te lang (limiet {MAX_MANIFEST_BYTES} bytes)
|
||||
@msg manifest is {_1} bytes (limit {MAX_MANIFEST_BYTES}) het manifest telt {_1} bytes (limiet {MAX_MANIFEST_BYTES})
|
||||
@msg module is {_1} bytes (limit {_2}) de module telt {_1} bytes (limiet {_2})
|
||||
@msg needs approval: it asks for {0}, which the user grants when installing it on its own goedkeuring nodig: de plug-in vraagt om {0}, wat de gebruiker toestaat wanneer hij die afzonderlijk installeert
|
||||
@msg not JSON: {e} geen JSON: {e}
|
||||
@msg not a WebAssembly binary (missing \0asm header) geen WebAssembly-binair bestand (de header \0asm ontbreekt)
|
||||
@msg parameter `{k}`: {what} parameter `{k}`: {what}
|
||||
@msg parameter `{name}`: {what} parameter `{name}`: {what}
|
||||
@msg plug-in parameters must be a JSON object plug-in-parameters moeten een JSON-object zijn
|
||||
@msg the module must export its linear memory as `memory` de module moet haar lineaire geheugen exporteren als `memory`
|
||||
@msg the objects to change are no longer in the document de te wijzigen objecten staan niet meer in het document
|
||||
@msg the runtime panicked de runtime is vastgelopen
|
||||
@msg unexpected host trap onverwachte trap in de host
|
||||
@msg vc_abi_version returned {v}; this host implements version {ABI_VERSION} vc_abi_version gaf {v} terug; deze host implementeert versie {ABI_VERSION}
|
||||
@msg vc_alloc returned 0 (out of memory) vc_alloc gaf 0 terug (onvoldoende geheugen)
|
||||
@msg vc_alloc returned a block outside memory vc_alloc gaf een blok buiten het geheugen terug
|
||||
@msg vc_run returned error code {packed} vc_run gaf foutcode {packed} terug
|
||||
@msg {_1} is not a file {_1} is geen bestand
|
||||
@msg {_1} is {_2} bytes (limit {_3}) {_1} is {_2} bytes (limiet {_3})
|
||||
@msg {_1} objects (limit {MAX_OBJECTS}) {_1} objecten (limiet {MAX_OBJECTS})
|
||||
@msg {at}: {msg} {at}: {msg}
|
||||
@msg {what} points outside memory {what} wijst buiten het geheugen
|
||||
@msg `angle` must be a number `angle` moet een getal zijn
|
||||
@msg `aspect` must be from 0.01 to 100 `aspect` moet van 0,01 tot 100 zijn
|
||||
@msg `cap` must be "butt", "round" or "square" `cap` moet "butt", "round" of "square" zijn
|
||||
@msg `fillRule` must be "nonzero" or "evenodd" `fillRule` moet "nonzero" of "evenodd" zijn
|
||||
@msg `helpUrl` must be an https:// address of at most {MAX_HELP_URL} bytes `helpUrl` moet een https://-adres van maximaal {MAX_HELP_URL} bytes zijn
|
||||
@msg `help` must be 1-{MAX_HELP} printable characters `help` moet uit 1-{MAX_HELP} afdrukbare tekens bestaan
|
||||
@msg `id` must be an effect id of 1-{MAX_EFFECT_ID} bytes `id` moet een effect-id van 1-{MAX_EFFECT_ID} bytes zijn
|
||||
@msg `id` must be the id of an input object `id` moet de id van een invoerobject zijn
|
||||
@msg `join` must be "miter", "round" or "bevel" `join` moet "miter", "round" of "bevel" zijn
|
||||
@msg `label` and `group` must be 1-{MAX_LABEL} printable characters `label` en `group` moeten uit 1-{MAX_LABEL} afdrukbare tekens bestaan
|
||||
@msg `maxLength` must be 1-{MAX_TEXT}, and the default no longer `maxLength` moet 1-{MAX_TEXT} zijn, en de standaardwaarde niet langer
|
||||
@msg `minItems` and `maxItems` must be 0-{MAX_LIST}, `maxItems` at least 1, and the default that many `minItems` en `maxItems` moeten 0-{MAX_LIST} zijn, `maxItems` minstens 1, en de standaardwaarde zoveel items
|
||||
@msg `name` must be a string `name` moet een string zijn
|
||||
@msg `opacity` must be a number `opacity` moet een getal zijn
|
||||
@msg `type` must be "path" or "compound" `type` moet "path" of "compound" zijn
|
||||
@msg `unit` must be 1-{MAX_UNIT} printable characters `unit` moet uit 1-{MAX_UNIT} afdrukbare tekens bestaan
|
||||
@msg `visibleWhen` lists 1 to {MAX_CONDITION_VALUES} values for `{other}` `visibleWhen` noemt 1 tot {MAX_CONDITION_VALUES} waarden voor `{other}`
|
||||
@msg `visibleWhen` names `{other}`, which isn't a parameter declared before this one `visibleWhen` noemt `{other}`, dat geen parameter is die vóór deze is gedeclareerd
|
||||
@msg `visibleWhen` names at most {MAX_CONDITIONS} parameters `visibleWhen` noemt maximaal {MAX_CONDITIONS} parameters
|
||||
@msg `visibleWhen` takes `{other}`'s values, of a checkbox or a choice `visibleWhen` neemt de waarden van `{other}`, een selectievakje of een keuzelijst
|
||||
@msg `visible` must be true or false `visible` moet true of false zijn
|
||||
@msg `{key}` must be a number from {_1} to {_2} `{key}` moet een getal van {_1} tot {_2} zijn
|
||||
@msg `{key}` must be an array of at most {MAX_ITEMS} entries `{key}` moet een array van maximaal {MAX_ITEMS} items zijn
|
||||
@msg a color default must be a color object or a hex string such as "#3a7bd5" een standaardkleur moet een kleurobject of een hexadecimale string zoals "#3a7bd5" zijn
|
||||
@msg a color object or a hex string such as "#3a7bd5" een kleurobject of een hexadecimale string zoals "#3a7bd5"
|
||||
@msg a freeform gradient holds at most {MAX_ITEMS} points and lines een verloop in vrije vorm bevat maximaal {MAX_ITEMS} punten en lijnen
|
||||
@msg a freeform gradient line names a point it doesn't have een lijn van een verloop in vrije vorm noemt een punt dat het verloop niet heeft
|
||||
@msg a gradient needs 1-{MAX_ITEMS} stops een verloop heeft 1-{MAX_ITEMS} kleurstops nodig
|
||||
@msg a list of numbers een lijst met getallen
|
||||
@msg a list of {min_items} to {max_items} numbers een lijst met {min_items} tot {max_items} getallen
|
||||
@msg a new object needs a `path` een nieuw object heeft een `path` nodig
|
||||
@msg a number een getal
|
||||
@msg a painted live effect returns only `objects` een geschilderd live-effect geeft alleen `objects` terug
|
||||
@msg a painted live effect's piece has only `path`, `fillRule`, `fills` and `strokes` een stuk van een geschilderd live-effect heeft alleen `path`, `fillRule`, `fills` en `strokes`
|
||||
@msg a read-only object was left out een alleen-lezen object is weggelaten
|
||||
@msg a read-only object was left out: return it, as {"id"} alone or as it was given een alleen-lezen object is weggelaten: geef het terug, als alleen {"id"} of zoals het is gegeven
|
||||
@msg a string een string
|
||||
@msg a stroke has only `paint`, `width`, `join`, `cap` and `miterLimit` een contour heeft alleen `paint`, `width`, `join`, `cap` en `miterLimit`
|
||||
@msg a stroke must be {"paint", "width"?, "join"?, "cap"?, "miterLimit"?} een contour moet {"paint", "width"?, "join"?, "cap"?, "miterLimit"?} zijn
|
||||
@msg an effect must be {"id", "params"?, "visible"?} een effect moet {"id", "params"?, "visible"?} zijn
|
||||
@msg an effect on a fill returns only `fills` een effect op een vulling geeft alleen `fills` terug
|
||||
@msg an effect on a stroke returns only `strokes` een effect op een contour geeft alleen `strokes` terug
|
||||
@msg an object must be a JSON object een object moet een JSON-object zijn
|
||||
@msg bad range ongeldig bereik
|
||||
@msg choices must be 1-64 non-empty, printable strings keuzes moeten 1-64 niet-lege, afdrukbare strings zijn
|
||||
@msg coordinate out of range (limit ±{MAX_COORD} pt) coördinaat buiten bereik (limiet ±{MAX_COORD} pt)
|
||||
@msg default is not one of the options de standaardwaarde is geen van de opties
|
||||
@msg each piece needs a `path` elk stuk heeft een `path` nodig
|
||||
@msg is listed twice staat twee keer in de lijst
|
||||
@msg pattern transform out of range patroontransformatie buiten bereik
|
||||
@msg read-only field '{field}' changed alleen-lezen veld '{field}' is gewijzigd
|
||||
@msg stops must be in order of `offset` kleurstops moeten op volgorde van `offset` staan
|
||||
@msg the document has no pattern {pattern} het document heeft geen patroon {pattern}
|
||||
@msg the document has no swatch {n} het document heeft geen staal {n}
|
||||
@msg the output de uitvoer
|
||||
@msg the path has no anchor points het pad heeft geen ankerpunten
|
||||
@msg too many anchor points (limit {MAX_ANCHORS}) te veel ankerpunten (limiet {MAX_ANCHORS})
|
||||
@msg true or false true of false
|
||||
@msg a number >= {_1} een getal >= {_1}
|
||||
@msg a number > {_1} een getal > {_1}
|
||||
@msg a number <= {_1} een getal <= {_1}
|
||||
@msg a number < {_1} een getal < {_1}
|
||||
@msg a number {_1} to {_2} een getal van {_1} tot {_2}
|
||||
@msg a number >= {_1} and < {_2} een getal >= {_1} en < {_2}
|
||||
@msg a number > {_1} and <= {_2} een getal > {_1} en <= {_2}
|
||||
@msg a number > {_1} and < {_2} een getal > {_1} en < {_2}
|
||||
@msg a number ({_1}) een getal ({_1})
|
||||
@msg a number >= {_1} ({_2}) een getal >= {_1} ({_2})
|
||||
@msg a number > {_1} ({_2}) een getal > {_1} ({_2})
|
||||
@msg a number <= {_1} ({_2}) een getal <= {_1} ({_2})
|
||||
@msg a number < {_1} ({_2}) een getal < {_1} ({_2})
|
||||
@msg a number {_1} to {_2} ({_3}) een getal van {_1} tot {_2} ({_3})
|
||||
@msg a number >= {_1} and < {_2} ({_3}) een getal >= {_1} en < {_2} ({_3})
|
||||
@msg a number > {_1} and <= {_2} ({_3}) een getal > {_1} en <= {_2} ({_3})
|
||||
@msg a number > {_1} and < {_2} ({_3}) een getal > {_1} en < {_2} ({_3})
|
||||
@msg an integer een geheel getal
|
||||
@msg an integer >= {_1} een geheel getal >= {_1}
|
||||
@msg an integer <= {_1} een geheel getal <= {_1}
|
||||
@msg an integer {_1} to {_2} een geheel getal van {_1} tot {_2}
|
||||
@msg one of {_1} een van {_1}
|
||||
@msg an object id (a non-negative integer) een object-id (een niet-negatief geheel getal)
|
||||
@msg a list of object ids een lijst met object-id's
|
||||
@msg a color (a string, [r, g, b] or an object) een kleur (een tekenreeks, [r, g, b] of een object)
|
||||
@msg [x, y] (two numbers) [x, y] (twee getallen)
|
||||
@msg an object een object
|
||||
@msg a list een lijst
|
||||
@msg unknown key `{k}`; the keys here are {_1} onbekende sleutel `{k}`; de sleutels hier zijn {_1}
|
||||
@msg {_1} is listed twice {_1} staat twee keer in de lijst
|
||||
@msg {_1} is not the id of an input object {_1} is niet de id van een invoerobject
|
||||
@msg {_1} is read-only {_1} is alleen-lezen
|
||||
@msg {what} must be from {lo} to {hi} {what} moet van {lo} tot {hi} zijn
|
||||
@msg a color component een kleurcomponent
|
||||
@msg a plate een drukplaat
|
||||
@msg Automation asked to install this plug-in. To install it, choose Object › Plug-ins › Install Plug-in… yourself. Automatisering vroeg om deze plug-in te installeren. Kies zelf Object › Plug-ins › Plug-in installeren… om hem te installeren.
|
||||
@msg “{name}” is another module than the plug-in with id {_1} and would get the settings and cache kept for it: install it with `replace: true` once the user agrees „{name}” is een andere module dan de plug-in met id {_1} en zou de instellingen en cache krijgen die daarvoor worden bewaard: installeer hem met `replace: true` zodra de gebruiker akkoord gaat
|
||||
@msg “{name}” lists `{id}` in `commandAllowlist`, which a plug-in may not call „{name}” noemt `{id}` in `commandAllowlist`, die een plug-in niet mag aanroepen
|
||||
@msg vc_call `{shown}`: {why} vc_call `{shown}`: {why}
|
||||
@msg vc_call `{shown}`: the manifest's `commandAllowlist` doesn't list it vc_call `{shown}`: de `commandAllowlist` van het manifest noemt deze opdracht niet
|
||||
@msg vc_call `{shown}`: the id or the arguments lie outside the module's memory vc_call `{shown}`: de id of de argumenten liggen buiten het geheugen van de module
|
||||
@msg vc_call `{shown}`: the id or the arguments are not UTF-8 vc_call `{shown}`: de id of de argumenten zijn geen UTF-8
|
||||
@msg vc_call `{shown}`: the arguments are not a JSON object vc_call `{shown}`: de argumenten zijn geen JSON-object
|
||||
@msg only a filter with the usual budget declares `commandAllowlist` alleen een filter met het gebruikelijke budget declareert `commandAllowlist`
|
||||
@msg command calls ({MAX_CALLS} calls and {MAX_CALL_BYTES} bytes per run) opdrachtaanroepen ({MAX_CALLS} aanroepen en {MAX_CALL_BYTES} bytes per uitvoering)
|
||||
@msg command call size (vc_call `{shown}`: {len} bytes, limit {MAX_CALL_DATA}) grootte van een opdrachtaanroep (vc_call `{shown}`: {len} bytes, limiet {MAX_CALL_DATA})
|
||||
@msg at most {MAX_ALLOWED_COMMANDS} commands in `commandAllowlist` maximaal {MAX_ALLOWED_COMMANDS} opdrachten in `commandAllowlist`
|
||||
@msg a plug-in may not call this command een plug-in mag deze opdracht niet aanroepen
|
||||
@msg `commandAllowlist` needs the permission `commands`, and `commands` needs a `commandAllowlist` `commandAllowlist` vereist de machtiging `commands`, en `commands` vereist een `commandAllowlist`
|
||||
@msg `commandAllowlist` names `{shown}`, which is not a command id or is listed twice `commandAllowlist` noemt `{shown}`, dat geen opdracht-id is of twee keer in de lijst staat
|
||||
@msg permission `{permission}` needs plug-in API level {PROGRESS_API}: give `api` {PROGRESS_API} machtiging `{permission}` vereist plug-in-API-niveau {PROGRESS_API}: geef `api` {PROGRESS_API}
|
||||
@msg the module imports `env.{name}` with another type than the host's: it is {signature} de module importeert `env.{name}` met een ander type dan dat van de host: het is {signature}
|
||||
@msg the module imports `env.{name}`, which a plug-in may use only at plug-in API level {PROGRESS_API} (`api` {PROGRESS_API}) and with the permission `{permission}` de module importeert `env.{name}`, dat een plug-in alleen mag gebruiken op plug-in-API-niveau {PROGRESS_API} (`api` {PROGRESS_API}) en met de machtiging `{permission}`
|
||||
@msg the module imports `{from}.{name}`, which the host doesn't offer: a plug-in may import only the `env.vc_*` functions that docs/plugins.md lists (plug-in API level 2), and no WASI, files or network de module importeert `{from}.{name}`, dat de host niet aanbiedt: een plug-in mag alleen de `env.vc_*`-functies importeren die docs/plugins.md noemt (plug-in-API-niveau 2), en geen WASI, bestanden of netwerk
|
||||
@msg `api` is {_1}; this host implements plug-in API levels 1 to {API_LEVEL} `api` is {_1}; deze host implementeert plug-in-API-niveaus 1 tot {API_LEVEL}
|
||||
@msg `paintOutput` may only be true `paintOutput` mag alleen true zijn
|
||||
@msg `paintOutput` is only for a live effect (`kind` "effect") at `api` 2 `paintOutput` is alleen voor een live-effect (`kind` "effect") bij `api` 2
|
||||
@msg `grant` must be a list of permission names `grant` moet een lijst met namen van machtigingen zijn
|
||||
@msg `grant` names an unknown permission `{shown}` `grant` noemt een onbekende machtiging `{shown}`
|
||||
@msg a plug-in of kind `{_1}` needs the permission `{_2}` een plug-in van het soort `{_1}` heeft de machtiging `{_2}` nodig
|
||||
@msg at most {MAX_PERMISSIONS} `permissions` maximaal {MAX_PERMISSIONS} `permissions`
|
||||
@msg permission `{shown}` doesn't apply to a plug-in of kind `{_1}` machtiging `{shown}` geldt niet voor een plug-in van het soort `{_1}`
|
||||
@msg permission `{shown}` is listed twice machtiging `{shown}` staat twee keer in de lijst
|
||||
@msg only a filter declares `inputs` alleen een filter declareert `inputs`
|
||||
@msg `inputs` names an unknown object kind `{shown}`: use type, image or symbolInstance `inputs` noemt een onbekend objectsoort `{shown}`: gebruik type, image of symbolInstance
|
||||
@msg `inputs` lists `{shown}` twice `inputs` noemt `{shown}` twee keer
|
||||
@msg `inputs` needs `api` 2 or later `inputs` vereist `api` 2 of hoger
|
||||
@msg `inputs` needs the permission `doc.read` `inputs` vereist de machtiging `doc.read`
|
||||
@msg memory budget (object {_1} needs {size} bytes of input, {left} left) geheugenbudget (object {_1} heeft {size} bytes invoer nodig, {left} over)
|
||||
@msg object budget (more than {MAX_OBJECTS} read-only objects) objectbudget (meer dan {MAX_OBJECTS} alleen-lezen objecten)
|
||||
@msg instruction budget instructiebudget
|
||||
@msg time budget tijdbudget
|
||||
@msg memory budget (the selection is too large to hand over) geheugenbudget (de selectie is te groot om door te geven)
|
||||
@msg output size ({what} is {len} bytes, limit {max}) uitvoergrootte ({what} is {len} bytes, limiet {max})
|
||||
@msg the plug-in's grant can't be removed from the plug-in store de toekenning van de plug-in kan niet uit de plug-inopslag worden verwijderd
|
||||
@msg permission `{shown}` is reserved for a later plug-in API; this host doesn't grant it machtiging `{shown}` is gereserveerd voor een latere plug-in-API; deze host kent haar niet toe
|
||||
@msg unknown permission `{shown}` onbekende machtiging `{shown}`
|
||||
@msg “{name}” asks for the permissions {asked}: a person has to approve them in the desktop app, or pass `grant` in a session started with --allow-plugin-grants „{name}” vraagt om de machtigingen {asked}: een persoon moet ze goedkeuren in de desktop-app, of geef `grant` door in een sessie die is gestart met --allow-plugin-grants
|
||||
@msg `grant` and `allowHeavy` take effect only in a session started with --allow-plugin-grants: approve the plug-in in the desktop app `grant` en `allowHeavy` werken alleen in een sessie die is gestart met --allow-plugin-grants: keur de plug-in goed in de desktop-app
|
||||
@msg Only the person at the keyboard can approve installing a plug-in Alleen de persoon achter het toetsenbord kan het installeren van een plug-in goedkeuren
|
||||
@msg “{name}” wasn't granted `{p}`, which its output needs: nothing was changed „{name}” heeft `{p}` niet gekregen, wat de uitvoer ervan nodig heeft: er is niets gewijzigd
|
||||
@msg a heavy filter runs in the background, so it can't declare `commands` een zwaar filter wordt op de achtergrond uitgevoerd, dus kan het geen `commands` declareren
|
||||
@msg at most {MAX_COMMANDS} `commands` maximaal {MAX_COMMANDS} `commands`
|
||||
@msg command {name} is declared twice opdracht {name} is twee keer gedeclareerd
|
||||
@msg command {name}: `label` must be 1-64 printable characters opdracht {name}: `label` moet uit 1-64 afdrukbare tekens bestaan
|
||||
@msg command {name}: use an id of 1-{MAX_COMMAND_ID} characters from a-z 0-9 _ that starts with a letter opdracht {name}: gebruik een id van 1-{MAX_COMMAND_ID} tekens uit a-z 0-9 _ die met een letter begint
|
||||
@msg command {name}: {e} opdracht {name}: {e}
|
||||
@msg manifest: {e} manifest: {e}
|
||||
@msg manifest: {e} at line {line} column {column} manifest: {e} op regel {line} kolom {column}
|
||||
@msg `commands` must be a list of commands, each with an `id` and a `label` `commands` moet een lijst met opdrachten zijn, elk met een `id` en een `label`
|
||||
@msg command {name} must be an object with an `id` and a `label` opdracht {name} moet een objectwaarde met een `id` en een `label` zijn
|
||||
@msg missing field `{key}` veld `{key}` ontbreekt
|
||||
@msg duplicate field `{key}` dubbel veld `{key}`
|
||||
@msg only a filter or a live effect declares `commands` alleen een filter of een live-effect declareert `commands`
|
||||
@msg “{name}” › {label}: {e} „{name}” › {label}: {e}
|
||||
@msg the module doesn't have the SHA-256 `hash` gives: nothing was installed de module heeft niet de SHA-256 die `hash` opgeeft: er is niets geïnstalleerd
|
||||
@msg select one object selecteer één object
|
||||
@msg no similar objects found (rotated or reflected copies are not matched); change the Global Edit Options and try again geen vergelijkbare objecten gevonden (gedraaide of gespiegelde kopieën worden niet herkend); wijzig de Opties voor globale bewerking en probeer het opnieuw
|
||||
@msg Global Edit is off Globale bewerking staat uit
|
||||
@msg only an object of the Global Edit other than the one it started from can be left out alleen een ander object van de globale bewerking dan het object waarmee die begon, kan worden weggelaten
|
||||
@msg `artboards`: all or a range such as 1, 3-5, not {v} `artboards`: all of een bereik zoals 1, 3-5, niet {v}
|
||||
@msg `{_1}` has no symbols to place `{_1}` heeft geen symbolen om te plaatsen
|
||||
@msg missing `library` (see symbol.libraries) `library` ontbreekt (zie symbol.libraries)
|
||||
@msg no symbol `{n}` geen symbool `{n}`
|
||||
@msg no symbol `{n}` in `{_1}` geen symbool `{n}` in `{_1}`
|
||||
@msg no symbol library `{key}` (see symbol.libraries) geen symboolbibliotheek `{key}` (zie symbol.libraries)
|
||||
@msg the document has no symbols to save het document heeft geen symbolen om op te slaan
|
||||
@msg `{_1}` has no brushes to apply `{_1}` heeft geen penselen om toe te passen
|
||||
@msg missing `library` (see brush.libraries) `library` ontbreekt (zie brush.libraries)
|
||||
@msg no brush `{n}` geen penseel `{n}`
|
||||
@msg no brush `{n}` in `{_1}` geen penseel `{n}` in `{_1}`
|
||||
@msg no brush library `{key}` (see brush.libraries) geen penseelbibliotheek `{key}` (zie brush.libraries)
|
||||
@msg the document has no brushes to save het document heeft geen penselen om op te slaan
|
||||
@msg a {width}×{height} screenshot's byte count overflows het aantal bytes van een schermafbeelding van {width}×{height} loopt over
|
||||
@msg the window's {what} ({points} points × {scale} DPI) cannot size a screenshot de {what} van het venster ({points} punten × {scale} DPI) kan geen formaat voor een schermafbeelding geven
|
||||
@msg {label} must be a number {label} moet een getal zijn
|
||||
@msg {label} must be a number of at least 0.1 {label} moet een getal van minstens 0,1 zijn
|
||||
@msg {label} must be a number from {min} to {max} {label} moet een getal van {min} tot {max} zijn
|
||||
@msg {label} must be a whole number from {min} to {max} {label} moet een geheel getal van {min} tot {max} zijn
|
||||
@msg features lists at most {max} tags features noemt maximaal {max} tags
|
||||
@msg unknown OpenType feature `{t}` onbekende OpenType-functie `{t}`
|
||||
@msg {label} must be a number above 0 and at most {max} {label} moet een getal boven 0 en maximaal {max} zijn
|
||||
@msg {label} must be at most {max} characters {label} mag maximaal {max} tekens lang zijn
|
||||
@msg {label} must be one character {label} moet één teken zijn
|
||||
@msg at most {max} tab stops maximaal {max} tabstops
|
||||
@msg unknown align `{other}` onbekende uitlijning `{other}`
|
||||
@msg no character style `{name}` geen tekenstijl `{name}`
|
||||
@msg {_1} is an importer (File › Open With) {_1} is een importplug-in (Bestand › Openen met)
|
||||
@msg missing `importer` (see document.formats) `importer` ontbreekt (zie document.formats)
|
||||
@msg `importer` must be a plug-in format id (see document.formats) `importer` moet een indelings-id van een plug-in zijn (zie document.formats)
|
||||
@msg “{shown}” opens {_1} files, not `{_2}` „{shown}” opent {_1}-bestanden, niet `{_2}`
|
||||
@msg `{_1}` is a plug-in of kind `{_2}`, not an importer `{_1}` is een plug-in van het soort `{_2}`, geen importplug-in
|
||||
@msg `{_1}` is a plug-in of kind `{_2}`, not an exporter `{_1}` is een plug-in van het soort `{_2}`, geen exportplug-in
|
||||
@msg `{_1}` is an importer: open a file with document.open {{"importer": "{_2}"}} `{_1}` is een importplug-in: open een bestand met document.open {{"importer": "{_2}"}}
|
||||
@msg `{_1}` is an exporter: export with document.export {{"format": "{_2}"}} `{_1}` is een exportplug-in: exporteer met document.export {{"format": "{_2}"}}
|
||||
@msg `{_1}` is a live effect: apply it with effect.apply {{"effect": "{_2}"}} `{_1}` is een live-effect: pas het toe met effect.apply {{"effect": "{_2}"}}
|
||||
@msg the importer returned no objects de importplug-in heeft geen objecten teruggegeven
|
||||
@msg an importer returns `objects` and `warnings`, not `{key}` een importplug-in geeft `objects` en `warnings` terug, niet `{key}`
|
||||
@msg the file is larger than the {MAX_INPUT_BYTES} bytes an importer reads het bestand is groter dan de {MAX_INPUT_BYTES} bytes die een importplug-in leest
|
||||
@msg an importer declares 1 to {MAX_EXTENSIONS} `extensions` een importplug-in declareert 1 tot {MAX_EXTENSIONS} `extensions`
|
||||
@msg only an exporter or an importer declares `extensions` alleen een exportplug-in of een importplug-in declareert `extensions`
|
||||
@msg an importer always gets an import's budget: leave `budget` out een importplug-in krijgt altijd het budget van een import: laat `budget` weg
|
||||
@msg only paths and compound paths can be aligned to the pixel grid alleen paden en samengestelde paden kunnen op het pixelraster worden uitgelijnd
|
||||
@msg `first` and `last` must be numbers of lines the console holds, first before last `first` en `last` moeten nummers zijn van regels die de console bevat, first vóór last
|
||||
@msg no plug-in effect is deferred er is geen plug-in-effect uitgesteld
|
||||
@msg The selected art has no islands to bridge De geselecteerde illustratie heeft geen eilanden om te overbruggen
|
||||
@msg No bridge of this width fits across the selected art Geen brug van deze breedte past over de geselecteerde illustratie
|
||||
@msg Some islands could not be joined to the area around the art Sommige eilanden konden niet worden verbonden met het gebied rond de illustratie
|
||||
@msg `width` must be from {lo} to {hi} pt `width` moet van {lo} tot {hi} pt zijn
|
||||
@msg `count` must be a whole number from 1 to {MAX_BRIDGES_PER_ISLAND} `count` moet een geheel getal van 1 tot {MAX_BRIDGES_PER_ISLAND} zijn
|
||||
|
||||
File Bestand
|
||||
New… Nieuw…
|
||||
New Without Dialog Nieuw zonder dialoogvenster
|
||||
@@ -3351,6 +3852,8 @@ theme Appearance Vormgeving
|
||||
Rename Library Group Bibliotheekgroep hernoemen
|
||||
Delete Library Group Bibliotheekgroep verwijderen
|
||||
Move Library Item to Group Bibliotheekitem naar groep verplaatsen
|
||||
Rename Library Item Bibliotheekitem hernoemen
|
||||
Add to Character Styles Aan tekenstijlen toevoegen
|
||||
Rename Library Bibliotheek hernoemen
|
||||
Show Library Bibliotheek weergeven
|
||||
Use Library Item Bibliotheekitem gebruiken
|
||||
@@ -4197,6 +4700,7 @@ imageTrace Outline Contour
|
||||
@plural {n} step|{n} steps {n} stap|{n} stappen
|
||||
@plural {n} stroke|{n} strokes {n} lijn|{n} lijnen
|
||||
@msg no library `{id}` geen bibliotheek `{id}`
|
||||
@msg the library has another item of that kind named `{name}` de bibliotheek heeft al een ander item van die soort met de naam `{name}`
|
||||
@msg select some type first selecteer eerst wat tekst
|
||||
@msg kerning must be a number, "auto", or "optical" kerning moet een getal, ‘auto’ of ‘optical’ zijn
|
||||
@msg {_1} has no {_2} style {_1} heeft geen {_2}stijl
|
||||
@@ -4574,6 +5078,7 @@ imageTrace Outline Contour
|
||||
@msg not a valid plug-in module: {0} geen geldige plug-inmodule: {0}
|
||||
@msg not an EMF or WMF file geen EMF- of WMF-bestand
|
||||
@msg not an HP-GL file geen HP-GL-bestand
|
||||
@msg not a PICT file geen PICT-bestand
|
||||
@msg `pens` must be an array of 1 to 255 #rrggbb colors `pens` moet een array van 1 tot 255 #rrggbb-kleuren zijn
|
||||
@msg not found niet gevonden
|
||||
@msg not in pattern editing mode niet in patroonbewerkingsmodus
|
||||
@@ -4909,6 +5414,7 @@ imageTrace Outline Contour
|
||||
@msg choose the font files to add kies de lettertypebestanden die je wilt toevoegen
|
||||
@msg not a file geen bestand
|
||||
@msg not a font file geen lettertypebestand
|
||||
@msg the active document changed while the question was open; nothing was deleted het actieve document is gewijzigd terwijl de vraag openstond; er is niets verwijderd
|
||||
@msg that document is no longer open dat document is niet langer geopend
|
||||
@msg larger than 256 MB groter dan 256 MB
|
||||
@msg the files come to more than 1 GB: add fewer at a time de bestanden lopen op tot meer dan 1 GB: voeg er minder tegelijk toe
|
||||
@@ -5330,6 +5836,65 @@ mark-style Japanese Japans
|
||||
@msg {label} can't build a solid from an image: trace it first with Object › Image Trace › Make. {label} kan geen massief object maken van een afbeelding: traceer deze eerst met Object › Afbeelding traceren › Maken.
|
||||
@msg {label} requires a shape with at least two anchors {label} vereist een vorm met minstens twee ankerpunten
|
||||
@msg The shape is too complex for a 3D effect De vorm is te complex voor een 3D-effect
|
||||
@msg Extrude & Bevel Extruderen en afschuinen
|
||||
@msg Revolve Draaien
|
||||
@msg Inflate Opblazen
|
||||
@msg Rotate Roteren
|
||||
@msg Extrude & Bevel (Classic) Extruderen en afschuinen (klassiek)
|
||||
@msg Revolve (Classic) Draaien (klassiek)
|
||||
@msg Rotate (Classic) Roteren (klassiek)
|
||||
@msg This effect Dit effect
|
||||
@msg clipping paths knippaden
|
||||
@msg other objects andere objecten
|
||||
@msg {label} requires a group holding a shape with at least two anchors {label} vereist een groep met een vorm met minstens twee ankerpunten
|
||||
@msg Revolve requires a group holding a shape with at least two anchors Draaien vereist een groep met een vorm met minstens twee ankerpunten
|
||||
@msg Revolve requires a shape with at least two anchors Draaien vereist een vorm met minstens twee ankerpunten
|
||||
@msg {label} on a group needs paths, compound paths, type, groups, clipping groups, blends and symbol instances: release or expand its {what} first. {label} op een groep vereist paden, samengestelde paden, tekst, groepen, knipgroepen, vermengingen en symboolinstanties: geef eerst het volgende vrij of breid het uit: {what}.
|
||||
@msg {label} on a group takes at most {MAX_MEMBERS} objects {label} op een groep neemt maximaal {MAX_MEMBERS} objecten op
|
||||
@msg A 3D effect on a group or layer goes on the group itself, not on its fill or stroke Een 3D-effect op een groep of laag hoort op de groep zelf, niet op de vulling of contour ervan
|
||||
@msg a 3D effect on a group's fill or stroke draws nothing een 3D-effect op de vulling of contour van een groep tekent niets
|
||||
@msg a 3D effect on a group's fill or stroke draws nothing to export een 3D-effect op de vulling of contour van een groep tekent niets om te exporteren
|
||||
@msg The 3D object is too complex to export Het 3D-object is te complex om te exporteren
|
||||
@msg the object has no 3D effect (Extrude & Bevel, Revolve, Inflate or Rotate) het object heeft geen 3D-effect (Extruderen en afschuinen, Draaien, Opblazen of Roteren)
|
||||
@msg its 3D effect builds no solid het 3D-effect ervan maakt geen massief object
|
||||
@msg bevel must be none or one of {_1} bevel moet none of een van {_1} zijn
|
||||
@msg {_1} can't build solids from this art: its symbol instances, blends and clipping groups hold too many objects {_1} kan van deze illustratie geen massieve objecten maken: de symboolinstanties, vermengingen en knipgroepen ervan bevatten te veel objecten
|
||||
@msg {label} can't build a solid from the instance of symbol "{symbol}": the symbol's art isn't available {label} kan geen massief object maken van de instantie van symbool "{symbol}": de illustratie van het symbool is niet beschikbaar
|
||||
@msg {_1}: the clipping path is too complex to cut the art with {_1}: het knippad is te complex om de illustratie mee uit te knippen
|
||||
@msg {_1} takes at most {MAX_MEMBERS} objects {_1} neemt maximaal {MAX_MEMBERS} objecten op
|
||||
@msg {_1} can't build solids from art nested more than {MAX_DEPTH} levels deep {_1} kan geen massieve objecten maken van illustraties die meer dan {MAX_DEPTH} niveaus diep genest zijn
|
||||
@msg Revolve paint is too complex for this surface; reduce Segments or simplify the gradient De verf van Draaien is te complex voor dit oppervlak; verlaag Segmenten of vereenvoudig het verloop
|
||||
@msg Revolve edge must be left or right Draaien: edge moet left of right zijn
|
||||
@msg Revolve cap must be a boolean Draaien: cap moet een booleaanse waarde zijn
|
||||
@msg the revolved object has no fill or stroke het gedraaide object heeft geen vulling of contour
|
||||
@msg lightColor must be an opaque RGB color in #rrggbb form lightColor moet een dekkende RGB-kleur in de vorm #rrggbb zijn
|
||||
@msg lights must contain one to ten lights lights moet één tot tien lichten bevatten
|
||||
@msg each light must be an object elk licht moet een object zijn
|
||||
@msg unknown light setting: use color, intensity, rotation, height, softness or behind onbekende lichtinstelling: gebruik color, intensity, rotation, height, softness of behind
|
||||
@msg light {key} must be a number from {min} to {max} licht: {key} moet een getal van {min} tot {max} zijn
|
||||
@msg light color must use opaque #rrggbb color van een licht moet een dekkend #rrggbb gebruiken
|
||||
@msg light behind must be true or false behind van een licht moet true of false zijn
|
||||
@msg shadow must be true or false shadow moet true of false zijn
|
||||
@msg shadowPosition must be behind or below shadowPosition moet behind of below zijn
|
||||
@msg {key} must be a number from {min} to {max} {key} moet een getal van {min} tot {max} zijn
|
||||
@msg each of `{GRAPHICS}` must be an object elk item van `{GRAPHICS}` moet een object zijn
|
||||
@msg `{GRAPHICS}` entries take symbol, face, x, y, scale and rotation, not `{k}` items van `{GRAPHICS}` nemen symbol, face, x, y, scale en rotation aan, niet `{k}`
|
||||
@msg each of `{GRAPHICS}` needs `symbol`, the name of a symbol elk item van `{GRAPHICS}` heeft `symbol` nodig, de naam van een symbool
|
||||
@msg `{GRAPHICS}` face must be front or back face in `{GRAPHICS}` moet front of back zijn
|
||||
@msg `{GRAPHICS}` {key} must be a number from {lo} to {hi} {key} in `{GRAPHICS}` moet een getal van {lo} tot {hi} zijn
|
||||
@msg `{GRAPHICS}` must be an array `{GRAPHICS}` moet een array zijn
|
||||
@msg Graphics map onto planar faces: use the Extrude or Plane object type Illustraties worden op platte vlakken geplaatst: gebruik het objecttype Extruderen of Vlak
|
||||
@msg `{GRAPHICS}` takes at most {MAX_GRAPHICS} graphics `{GRAPHICS}` neemt maximaal {MAX_GRAPHICS} illustraties op
|
||||
@msg A plane has one face: map its graphics onto the front Een vlak heeft één zijde: plaats de illustraties ervan op de voorkant
|
||||
@msg The graphics are too complex: simplify the symbols' art De illustraties zijn te complex: vereenvoudig de illustraties van de symbolen
|
||||
@msg A graphic's art may be nested at most {MAX_LEVELS} levels deep: simplify the symbol's art De illustratie van een grafisch element mag maximaal {MAX_LEVELS} niveaus diep genest zijn: vereenvoudig de illustratie van het symbool
|
||||
@msg A graphic's art may nest symbols at most {MAX_NESTING} levels deep: simplify the symbol's art De illustratie van een grafisch element mag symbolen maximaal {MAX_NESTING} niveaus diep nesten: vereenvoudig de illustratie van het symbool
|
||||
@msg A graphic's art holds too many objects: simplify the symbol's art De illustratie van een grafisch element bevat te veel objecten: vereenvoudig de illustratie van het symbool
|
||||
@msg A graphic draws at most {MAX_PIECES} fills and strokes: simplify the symbol's art Een grafisch element tekent maximaal {MAX_PIECES} vullingen en contouren: vereenvoudig de illustratie van het symbool
|
||||
@msg `surface` must be one of {_1} `surface` moet een van {_1} zijn
|
||||
@msg {label} draws the source art for this object instead of its 3D surface {label} tekent voor dit object de bronillustratie in plaats van het 3D-oppervlak
|
||||
@msg {label} draws no faces for this object {label} tekent geen vlakken voor dit object
|
||||
@msg the wireframe has more than {MAX_WIRE_EDGES} edges het draadmodel heeft meer dan {MAX_WIRE_EDGES} randen
|
||||
@msg The 3D surface is too complex; simplify the shape Het 3D-oppervlak is te complex; vereenvoudig de vorm
|
||||
Transform Objects Objecten transformeren
|
||||
@msg unknown parameter `{key}`; did you mean `{near}`? onbekende parameter `{key}`; bedoelde je `{near}`?
|
||||
@@ -6815,6 +7380,7 @@ breakText Glyphs Glyphs
|
||||
# Deferred plug-in effects
|
||||
Refresh Deferred Effects Uitgestelde effecten vernieuwen
|
||||
Deferred Effects Uitgestelde effecten
|
||||
@msgplural Opened with {n} plug-in effect deferred. Effect › Refresh Deferred Effects runs it.|Opened with {n} plug-in effects deferred. Effect › Refresh Deferred Effects runs them. Geopend met {n} uitgesteld plug-in-effect. Effect › Uitgestelde effecten vernieuwen voert het uit.|Geopend met {n} uitgestelde plug-in-effecten. Effect › Uitgestelde effecten vernieuwen voert ze uit.
|
||||
|
||||
# Cutting Tools add-on (Object › Plug-ins › Cutting Tools).
|
||||
Cutting Tools Snijgereedschap
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3483,6 +3483,8 @@ theme Appearance Wygląd
|
||||
Rename Library Group Zmień nazwę grupy biblioteki
|
||||
Delete Library Group Usuń grupę biblioteki
|
||||
Move Library Item to Group Przenieś element biblioteki do grupy
|
||||
Rename Library Item Zmień nazwę elementu biblioteki
|
||||
Add to Character Styles Dodaj do stylów znakowych
|
||||
Rename Library Zmień nazwę biblioteki
|
||||
Show Library Pokaż bibliotekę
|
||||
Use Library Item Użyj elementu biblioteki
|
||||
@@ -4300,6 +4302,7 @@ imageTrace Outline Kontur
|
||||
@plural {n} step|{n} steps {n} krok|{n} kroki|{n} kroków
|
||||
@plural {n} stroke|{n} strokes {n} obrys|{n} obrysy|{n} obrysów
|
||||
@msg no library `{id}` brak biblioteki `{id}`
|
||||
@msg the library has another item of that kind named `{name}` biblioteka ma już inny element tego rodzaju o nazwie `{name}`
|
||||
@msg select some type first najpierw zaznacz tekst
|
||||
@msg kerning must be a number, "auto", or "optical" kerning musi być liczbą, „auto” lub „optical”
|
||||
@msg the selection has no gradient fill zaznaczenie nie ma gradientu wypełnienia
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3705,6 +3705,8 @@ font-technology Variable Variáveis
|
||||
Rename Library Group Renomear grupo de biblioteca
|
||||
Delete Library Group Excluir grupo de biblioteca
|
||||
Move Library Item to Group Mover item da biblioteca para o grupo
|
||||
Rename Library Item Renomear item da biblioteca
|
||||
Add to Character Styles Adicionar aos Estilos de Caractere
|
||||
Library Biblioteca
|
||||
Rename Library Renomear biblioteca
|
||||
Show Library Mostrar biblioteca
|
||||
@@ -3742,6 +3744,7 @@ axis Both Ambos
|
||||
Drag to float the toolbar Arraste para flutuar a barra de ferramentas
|
||||
Drag to the window's left or right edge to dock Arraste até a borda esquerda ou direita da janela para encaixar
|
||||
@msg no library `{id}` nenhuma biblioteca `{id}`
|
||||
@msg the library has another item of that kind named `{name}` a biblioteca já tem outro item desse tipo chamado `{name}`
|
||||
@msg select some type first selecione algum texto primeiro
|
||||
@msg kerning must be a number, "auto", or "optical" O kerning deve ser um número, “auto” ou “optical”
|
||||
@msg the selection has no gradient fill a seleção não tem gradiente de preenchimento
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -3615,6 +3615,8 @@ digits Malayalam Малаялам
|
||||
Rename Library Group Переименовать группу библиотеки
|
||||
Delete Library Group Удалить группу библиотеки
|
||||
Move Library Item to Group Переместить элемент библиотеки в группу
|
||||
Rename Library Item Переименовать элемент библиотеки
|
||||
Add to Character Styles Добавить в стили символов
|
||||
Library Библиотека
|
||||
Rename Library Переименовать библиотеку
|
||||
Show Library Показать библиотеку
|
||||
@@ -4204,6 +4206,7 @@ axis Both Оба
|
||||
# (`untranslated_report` lists any that are missing). Command ids, parameter
|
||||
# names and values in backticks or code (`colorModel rgb`, `document.export`) stay as they are.
|
||||
@msg no library `{id}` нет библиотеки `{id}`
|
||||
@msg the library has another item of that kind named `{name}` в библиотеке уже есть другой элемент этого вида с именем `{name}`
|
||||
@msg select some type first сначала выделите текст
|
||||
@msg kerning must be a number, "auto", or "optical" kerning должен быть числом, «auto» или «optical»
|
||||
@msg the selection has no gradient fill у выделения нет градиентной заливки
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -3505,6 +3505,8 @@ digits Malayalam Malayalam
|
||||
Rename Library Group Byt namn på biblioteksgrupp
|
||||
Delete Library Group Radera biblioteksgrupp
|
||||
Move Library Item to Group Flytta biblioteksobjekt till grupp
|
||||
Rename Library Item Byt namn på biblioteksobjekt
|
||||
Add to Character Styles Lägg till i teckenstilar
|
||||
Library Bibliotek
|
||||
Rename Library Byt namn på bibliotek
|
||||
Show Library Visa bibliotek
|
||||
@@ -4078,6 +4080,7 @@ axis Both Båda
|
||||
Drag to the window's left or right edge to dock Dra till fönstrets vänster- eller högerkant för att docka
|
||||
Float Tool Group Gör verktygsgruppen flytande
|
||||
@msg no library `{id}` inget bibliotek `{id}`
|
||||
@msg the library has another item of that kind named `{name}` biblioteket har redan ett annat objekt av den sorten med namnet `{name}`
|
||||
@msg select some type first markera någon text först
|
||||
@msg kerning must be a number, "auto", or "optical" kerning måste vara ett tal, ”auto” eller ”optical”
|
||||
@msg the selection has no gradient fill markeringen har ingen fyllnadsgradient
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -3617,6 +3617,7 @@ fn translated_messages_keep_the_command_ids_their_english_names() {
|
||||
/// the messages each one lacks.
|
||||
const COMPLETE_MESSAGES: &[&str] = &[
|
||||
"cs", "de", "el", "es", "fr", "hi", "hu", "it", "ja", "ka", "ko", "pl", "pt-br", "ru", "sv", "uk", "vi", "zh-hans", "zh-hant", "fi", "tr", "ca",
|
||||
"nl",
|
||||
];
|
||||
|
||||
/// Crates whose error and status messages reach the status bar.
|
||||
|
||||
@@ -3394,6 +3394,8 @@ digits Malayalam Malayalam
|
||||
Rename Library Group Kitaplık Grubunu Yeniden Adlandır
|
||||
Delete Library Group Kütüphane Grubunu Sil
|
||||
Move Library Item to Group Kitaplık Öğesini Gruba Taşı
|
||||
Rename Library Item Kitaplık Öğesini Yeniden Adlandır
|
||||
Add to Character Styles Karakter Stillerine Ekle
|
||||
Library Kütüphane
|
||||
Rename Library Kitaplığı Yeniden Adlandır
|
||||
Show Library Kitaplığı Göster
|
||||
@@ -3962,6 +3964,7 @@ axis Both Her İkisi
|
||||
Drag to the window's left or right edge to dock Sabitlemek için pencerenin sol veya sağ kenarına sürükleyin
|
||||
Float Tool Group Araç Grubunu Yüzer Yap
|
||||
@msg no library `{id}` `{id}` kütüphanesi yok
|
||||
@msg the library has another item of that kind named `{name}` kitaplıkta zaten bu türden `{name}` adlı başka bir öğe var
|
||||
@msg select some type first önce bir tür seçin
|
||||
@msg kerning must be a number, "auto", or "optical" kerning bir sayı, “auto” veya “optical” olmalıdır
|
||||
@msg the selection has no gradient fill seçimin degrade dolgusu yok
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -3621,6 +3621,8 @@ effect Points Точки
|
||||
Rename Library Group Перейменувати групу бібліотеки
|
||||
Delete Library Group Видалити групу бібліотеки
|
||||
Move Library Item to Group Перемістити елемент бібліотеки в групу
|
||||
Rename Library Item Перейменувати елемент бібліотеки
|
||||
Add to Character Styles Додати до стилів символів
|
||||
Library Бібліотека
|
||||
Rename Library Перейменувати бібліотеку
|
||||
Show Library Показати бібліотеку
|
||||
@@ -4202,6 +4204,7 @@ axis Both Обидві
|
||||
Drag to the window's left or right edge to dock Перетягніть до лівого або правого краю вікна для прикріплення
|
||||
Float Tool Group Від’єднати групу інструментів
|
||||
@msg no library `{id}` немає бібліотеки `{id}`
|
||||
@msg the library has another item of that kind named `{name}` у бібліотеці вже є інший елемент цього виду з назвою `{name}`
|
||||
@msg select some type first спочатку виділіть текст
|
||||
@msg kerning must be a number, "auto", or "optical" kerning має бути числом, «auto» або «optical»
|
||||
@msg the selection has no gradient fill виділення не має градієнтної заливки
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -2424,6 +2424,8 @@ digits Hindi Hindi
|
||||
Move Guide to Layer Di chuyển đường căn vào lớp
|
||||
Move in Perspective Di chuyển theo phối cảnh
|
||||
Move Library Item to Group Di chuyển mục thư viện vào nhóm
|
||||
Rename Library Item Đổi tên mục thư viện
|
||||
Add to Character Styles Thêm vào các kiểu ký tự
|
||||
Move Locked and Hidden Artwork with Artboard Di chuyển tác phẩm đã khóa và ẩn cùng bảng vẽ
|
||||
Move Mesh Point Di chuyển điểm lưới
|
||||
Move Mesh Points Di chuyển các điểm lưới
|
||||
@@ -4974,6 +4976,7 @@ theme Appearance Giao diện
|
||||
@msg no interaction in progress không có tương tác nào đang tiến hành
|
||||
@msg no key object không có đối tượng khóa
|
||||
@msg no library `{id}` không có thư viện `{id}`
|
||||
@msg the library has another item of that kind named `{name}` thư viện đã có một mục khác cùng loại tên là `{name}`
|
||||
@msg no library `{key}` (see {list}) không có thư viện `{key}` (xem {list})
|
||||
@msg No linked files to look for Không có tệp liên kết để tìm kiếm
|
||||
@msg no Live Paint edge near that point không có cạnh tô trực tiếp gần điểm đó
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 204 and column 5.
|
@@ -3444,6 +3444,8 @@ digits Malayalam 马拉雅拉姆数字
|
||||
Rename Library Group 重命名库组
|
||||
Delete Library Group 删除库组
|
||||
Move Library Item to Group 将库项目移到组
|
||||
Rename Library Item 重命名库项目
|
||||
Add to Character Styles 添加到字符样式
|
||||
Library 库
|
||||
Rename Library 重命名库
|
||||
Show Library 显示库
|
||||
@@ -4195,6 +4197,7 @@ imageTrace Outline 轮廓
|
||||
@msg the layer to flatten into is hidden 要拼合到的图层已隐藏
|
||||
@msg there are no objects to release 没有可释放的对象
|
||||
@msg no library `{id}` 没有库 `{id}`
|
||||
@msg the library has another item of that kind named `{name}` 库中已有另一个同类项目名为 `{name}`
|
||||
@msg {path}: not a file {path}:不是文件
|
||||
@msg {path}: {e} {path}:{e}
|
||||
@msg can't write .{ext} images 无法写入 .{ext} 图像
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1959,6 +1959,7 @@ file-filter Templates 範本
|
||||
@msg the layer to flatten into is hidden 要平面化到的圖層已隱藏
|
||||
@msg there are no objects to release 沒有可釋放的物件
|
||||
@msg no library `{id}` 沒有資料庫 `{id}`
|
||||
@msg the library has another item of that kind named `{name}` 資料庫中已有另一個同類項目名為 `{name}`
|
||||
@msg {path}: not a file {path}:不是檔案
|
||||
@msg {path}: {e} {path}:{e}
|
||||
@msg can't write .{ext} images 無法寫入 .{ext} 影像
|
||||
@@ -4680,6 +4681,8 @@ digits Malayalam 馬來亞拉姆數字
|
||||
Rename Library Group 重新命名資料庫群組
|
||||
Delete Library Group 刪除資料庫群組
|
||||
Move Library Item to Group 將資料庫項目移至群組
|
||||
Rename Library Item 重新命名資料庫項目
|
||||
Add to Character Styles 新增至字元樣式
|
||||
Library 資料庫
|
||||
Rename Library 重新命名資料庫
|
||||
Show Library 顯示資料庫
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -558,7 +558,7 @@ fn delete_key(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
fn thumbnail_drag(ui: &mut Ui, th: Rect, id: NodeId) {
|
||||
let resp = ui.interact(th, ui.scope_id().with("ap-thumb"), Sense::drag()).on_hover_text(tl!("Drag onto art to apply this appearance"));
|
||||
widgets::drag_source(ui, &resp, || PanelDrag::Appearance(id));
|
||||
if resp.dragged() {
|
||||
if resp.dragged_by(egui::PointerButton::Primary) {
|
||||
ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing);
|
||||
}
|
||||
}
|
||||
@@ -704,13 +704,13 @@ fn stack(app: &mut VectorcraftApp, ui: &mut Ui, n: &Node, sel: Sel, object_row:
|
||||
let lit = |item: Option<usize>, k: usize| effects.as_ref().is_some_and(|(list, ks)| *list == item && ks.contains(&k));
|
||||
let mut rows = vec![(Slot::Object { top: true }, object_row)];
|
||||
let mut stopped = false;
|
||||
// Starts or ends a row drag.
|
||||
// Starts (primary button only) or ends a row drag.
|
||||
let frozen = only.is_some();
|
||||
let mut track = |resp: &egui::Response, what: Dragged| {
|
||||
if frozen {
|
||||
return;
|
||||
}
|
||||
if resp.drag_started() {
|
||||
if resp.drag_started_by(egui::PointerButton::Primary) {
|
||||
set_pstate(&ctx, "ap-drag", Some(what));
|
||||
// Where the row was grabbed, for its dimmed copy under the pointer.
|
||||
// (From where the button went down: the drag starts once the pointer has moved on.)
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
//! patterns), are added to it; the + button adds the selection's graphic, fill or stroke color,
|
||||
//! pattern or gradient, or text styles. A click on a color, gradient or pattern paints the
|
||||
//! selection through the active Fill/Stroke proxy, a style click applies it to the selected type,
|
||||
//! and a graphic is dragged onto the canvas (or double-clicked) to place a copy. Libraries are
|
||||
//! kept on this machine.
|
||||
//! and a graphic is dragged onto the canvas (or double-clicked) to place a copy. A character
|
||||
//! style's context menu also applies it, adds it to the document's character styles without
|
||||
//! applying it (`library.addToCharacterStyles`) and renames it (`library.renameItem`). Libraries
|
||||
//! are kept on this machine.
|
||||
//!
|
||||
//! The search field filters the items by name; items can be moved into user-named groups, shown as
|
||||
//! collapsible sections after the ungrouped items; and the panel menu exports the library to a
|
||||
@@ -94,12 +96,22 @@ fn ask_group_name(app: &mut VectorcraftApp, library: &str, rename: Option<&str>,
|
||||
app.ui.dialog = Some(crate::state::Dialog::new("command", d));
|
||||
}
|
||||
|
||||
/// The name dialog for renaming item `item` (its key) of `kind` in `library`, filled with its name.
|
||||
fn ask_item_name(app: &mut VectorcraftApp, library: &str, kind: ItemKind, item: &str) {
|
||||
let name = app.session.libraries.get(library).and_then(|l| l.items().find(|(k, key, _)| *k == kind && *key == item)).map(|(.., n)| n.to_string());
|
||||
let fixed = json!({ "library": library, "kind": kind_param(kind), "item": item });
|
||||
let d = json!({ "__command": "library.renameItem", "__label": "Rename Library Item", "name": name.unwrap_or_else(|| item.to_string()), "__params": fixed });
|
||||
app.ui.dialog = Some(crate::state::Dialog::new("command", d));
|
||||
}
|
||||
|
||||
/// What a click in the panel asks for, done once the list is drawn.
|
||||
enum Act {
|
||||
Run(&'static str, Value),
|
||||
/// The New Group dialog; the items (`[{kind, item}]`) go into the new group.
|
||||
NewGroup(Value),
|
||||
RenameGroup(String),
|
||||
/// The Rename dialog for an item (its kind and key).
|
||||
RenameItem(ItemKind, String),
|
||||
}
|
||||
|
||||
/// What a drag in the panel holds for the library shown: one of its items, one of its groups (by
|
||||
@@ -164,6 +176,9 @@ struct Items<'a> {
|
||||
grab: Option<Grab>,
|
||||
/// Whether the items show in a list (else colours and graphics as icons).
|
||||
list: bool,
|
||||
/// Whether a document is open, and whether type is selected there for a style to apply to.
|
||||
has_doc: bool,
|
||||
can_apply: bool,
|
||||
}
|
||||
|
||||
impl Items<'_> {
|
||||
@@ -214,7 +229,10 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let searching = !query.is_empty();
|
||||
let shown = |name: &str| !searching || name.to_lowercase().contains(&query);
|
||||
let grab = egui::DragAndDrop::payload::<PanelDrag>(ui.ctx()).and_then(|d| grabbed(&d, &lib_id));
|
||||
let items = Items { library: &lib_id, lib, groups: lib.group_index(), fill_active, grab, list };
|
||||
// Whether a character style's Apply Character Style is enabled (looked up only when the library has one).
|
||||
let can_apply =
|
||||
has_doc && !lib.char_styles.is_empty() && vectorcraft_engine::cmd::textstyles::target_style_attrs(&app.session, &json!({}), false).is_some();
|
||||
let items = Items { library: &lib_id, lib, groups: lib.group_index(), fill_active, grab, list, has_doc, can_apply };
|
||||
// The items shown in each section: the ungrouped ones first, then each group's.
|
||||
let mut counts = vec![0usize; lib.groups.len() + 1];
|
||||
for (kind, key, _) in lib.items().filter(|(_, _, name)| shown(name)) {
|
||||
@@ -374,6 +392,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
}
|
||||
Some(Act::NewGroup(items)) => ask_group_name(app, &lib_id, None, items),
|
||||
Some(Act::RenameGroup(g)) => ask_group_name(app, &lib_id, Some(&g), Value::Null),
|
||||
Some(Act::RenameItem(kind, item)) => ask_item_name(app, &lib_id, kind, &item),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
@@ -466,7 +485,13 @@ impl Items<'_> {
|
||||
if resp.clicked() {
|
||||
*act = Some(Act::Run("library.use", json!({ "kind": kind_param(kind), "item": st.name })));
|
||||
}
|
||||
resp.context_menu(|ui| self.item_menu(ui, act, kind, &st.name));
|
||||
resp.context_menu(|ui| {
|
||||
if kind == ItemKind::CharStyle {
|
||||
self.char_style_menu(ui, act, &st.name);
|
||||
} else {
|
||||
self.item_menu(ui, act, kind, &st.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
ui.add_space(6.0);
|
||||
}
|
||||
@@ -597,6 +622,40 @@ impl Items<'_> {
|
||||
/// An item's context menu entries: Move to Group (No Group, the library's groups, New
|
||||
/// Group…) and Delete.
|
||||
fn item_menu(&self, ui: &mut Ui, act: &mut Option<Act>, kind: ItemKind, key: &str) {
|
||||
self.group_menu(ui, act, kind, key);
|
||||
if menu_item(ui, "Delete", true, false) {
|
||||
*act = Some(Act::Run("library.removeItem", json!({ "kind": kind_param(kind), "item": key })));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// A character style's context menu: Apply Character Style (with type selected), Add to
|
||||
/// Character Styles (the document's, not applied), Move to Group, Rename… and Delete.
|
||||
fn char_style_menu(&self, ui: &mut Ui, act: &mut Option<Act>, key: &str) {
|
||||
let item = json!({ "kind": "charStyle", "item": key });
|
||||
if menu_item(ui, "Apply Character Style", self.can_apply, false) {
|
||||
*act = Some(Act::Run("library.use", item.clone()));
|
||||
ui.close();
|
||||
}
|
||||
if menu_item(ui, "Add to Character Styles", self.has_doc, false) {
|
||||
*act = Some(Act::Run("library.addToCharacterStyles", json!({ "item": key })));
|
||||
ui.close();
|
||||
}
|
||||
ui.separator();
|
||||
self.group_menu(ui, act, ItemKind::CharStyle, key);
|
||||
if menu_item(ui, "Rename…", true, false) {
|
||||
*act = Some(Act::RenameItem(ItemKind::CharStyle, key.to_string()));
|
||||
ui.close();
|
||||
}
|
||||
if menu_item(ui, "Delete", true, false) {
|
||||
*act = Some(Act::Run("library.removeItem", item));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
|
||||
/// The Move to Group submenu of an item's context menu: No Group, the library's groups and
|
||||
/// New Group….
|
||||
fn group_menu(&self, ui: &mut Ui, act: &mut Option<Act>, kind: ItemKind, key: &str) {
|
||||
let at = self.group_of(kind, key);
|
||||
let item = json!({ "kind": kind_param(kind), "item": key });
|
||||
ui.menu_button(format!(" {}", tl!("Move to Group")), |ui| {
|
||||
@@ -624,10 +683,6 @@ impl Items<'_> {
|
||||
}
|
||||
});
|
||||
});
|
||||
if menu_item(ui, "Delete", true, false) {
|
||||
*act = Some(Act::Run("library.removeItem", item));
|
||||
ui.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -416,6 +416,89 @@ fn group_dialogs_run_with_their_library_and_group() {
|
||||
assert_eq!(got["groups"], json!([{"name": "Cold", "items": [{"kind": "color", "item": "Blue"}]}]));
|
||||
}
|
||||
|
||||
/// A `button` click at `pos`, pressed in one frame and released in the next.
|
||||
fn click_at(app: &mut VectorcraftApp, ctx: &egui::Context, pos: egui::Pos2, button: egui::PointerButton) -> Vec<(String, Rect)> {
|
||||
let event = |pressed| egui::Event::PointerButton { pos, button, pressed, modifiers: Default::default() };
|
||||
frame_at(app, ctx, 600.0, vec![egui::Event::PointerMoved(pos), event(true)]);
|
||||
frame_at(app, ctx, 600.0, vec![event(false)]);
|
||||
frame_at(app, ctx, 600.0, vec![]).0
|
||||
}
|
||||
|
||||
/// The menu entries shown in `texts`, in order from the top: the labels starting with the menu's
|
||||
/// indent.
|
||||
fn menu_entries(texts: &[(String, Rect)]) -> Vec<String> {
|
||||
let mut entries: Vec<_> = texts.iter().filter(|(t, _)| t.starts_with(" ")).map(|(t, r)| (t.trim().to_string(), r.top())).collect();
|
||||
entries.sort_by(|a, b| a.1.total_cmp(&b.1));
|
||||
entries.into_iter().map(|(t, _)| t).collect()
|
||||
}
|
||||
|
||||
/// A right-click on a library character style opens its menu without applying it: Apply
|
||||
/// Character Style (only with type selected), Add to Character Styles, Move to Group, Rename… and
|
||||
/// Delete. Add puts the style in the document's character styles and leaves the selected type as
|
||||
/// it was; Rename… opens a dialog with the style's name that renames it on OK and changes nothing
|
||||
/// on Cancel. A paragraph style's menu stays Move to Group and Delete.
|
||||
#[test]
|
||||
fn a_character_style_s_menu_applies_adds_renames_and_deletes() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 200, "height": 200})).unwrap();
|
||||
let data = json!({"name": "Type", "charStyles": [{"name": "Headline", "attrs": {"size": 31.0}}], "paraStyles": [{"name": "Body", "attrs": {}}]});
|
||||
let lib = app.run("library.import", json!({"data": data.to_string()})).unwrap()["id"].as_str().unwrap().to_string();
|
||||
let ctx = egui::Context::default();
|
||||
crate::theme::install_fonts(&ctx);
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
// No type selected: Apply is there but does nothing.
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Headline").center(), egui::PointerButton::Secondary);
|
||||
assert_eq!(menu_entries(&menu), ["Apply Character Style", "Add to Character Styles", "Move to Group", "Rename…", "Delete"]);
|
||||
click_at(&mut app, &ctx, at(&menu, " Apply Character Style").center(), egui::PointerButton::Primary);
|
||||
assert!(app.session.active().unwrap().doc.char_styles.is_empty(), "disabled without type");
|
||||
// With type selected: a right-click applies nothing; Add adds the style, unapplied.
|
||||
let t = app.run("text.create", json!({"x": 10, "y": 80, "text": "Type", "size": 9})).unwrap()["id"].as_u64().unwrap();
|
||||
app.run("select.set", json!({"ids": [t]})).unwrap();
|
||||
let style_of = |app: &VectorcraftApp| match &app.session.active().unwrap().doc.node(vectorcraft_doc::NodeId(t)).unwrap().kind {
|
||||
vectorcraft_doc::NodeKind::Text(text) => (text.runs[0].style.size, text.runs[0].style.style_name.clone()),
|
||||
_ => panic!("not text"),
|
||||
};
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Headline").center(), egui::PointerButton::Secondary);
|
||||
assert_eq!(style_of(&app), (9.0, None), "a right-click applies nothing");
|
||||
let undo = app.session.active().unwrap().history.undo.len();
|
||||
click_at(&mut app, &ctx, at(&menu, " Add to Character Styles").center(), egui::PointerButton::Primary);
|
||||
let doc = &app.session.active().unwrap().doc;
|
||||
assert_eq!(doc.char_styles.iter().map(|c| c.name.as_str()).collect::<Vec<_>>(), ["Headline"]);
|
||||
assert_eq!(style_of(&app), (9.0, None), "added, not applied");
|
||||
assert_eq!(app.session.active().unwrap().history.undo.len(), undo + 1);
|
||||
// Apply applies it.
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Headline").center(), egui::PointerButton::Secondary);
|
||||
click_at(&mut app, &ctx, at(&menu, " Apply Character Style").center(), egui::PointerButton::Primary);
|
||||
assert_eq!(style_of(&app), (31.0, Some("Headline".into())));
|
||||
// Rename…: Cancel keeps the name, OK renames.
|
||||
for (ok, want) in [(false, "Headline"), (true, "Title")] {
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Headline").center(), egui::PointerButton::Secondary);
|
||||
click_at(&mut app, &ctx, at(&menu, " Rename…").center(), egui::PointerButton::Primary);
|
||||
let d = app.ui.dialog.as_mut().expect("the Rename dialog");
|
||||
assert_eq!((d.str("__command"), d.str("name")), ("library.renameItem".to_string(), "Headline".to_string()));
|
||||
d.fields.insert("name".into(), json!("Title"));
|
||||
if ok {
|
||||
crate::dialogs::confirm(&mut app).unwrap();
|
||||
} else {
|
||||
crate::dialogs::cancel(&mut app);
|
||||
}
|
||||
assert_eq!(style_order(&mut app), [want]);
|
||||
}
|
||||
// The paragraph style's menu.
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Body").center(), egui::PointerButton::Secondary);
|
||||
assert_eq!(menu_entries(&menu), ["Move to Group", "Delete"]);
|
||||
// Delete removes the character style from the library only.
|
||||
let (texts, _) = frame_at(&mut app, &ctx, 600.0, vec![]);
|
||||
let menu = click_at(&mut app, &ctx, at(&texts, "Title").center(), egui::PointerButton::Secondary);
|
||||
click_at(&mut app, &ctx, at(&menu, " Delete").center(), egui::PointerButton::Primary);
|
||||
assert!(app.session.libraries.get(&lib).unwrap().char_styles.is_empty());
|
||||
assert_eq!(app.session.active().unwrap().doc.char_styles.len(), 1, "the document's style stays");
|
||||
}
|
||||
|
||||
/// Export Library… writes the library's file and Import Library… adds it back as a new library.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[test]
|
||||
|
||||
@@ -690,10 +690,11 @@ fn body<K: LibraryKind>(app: &mut VectorcraftApp, ui: &mut Ui, id: &str) {
|
||||
bottom::<K>(app, ui, id);
|
||||
}
|
||||
|
||||
/// An item of library `id` dragged out of its tile or row `resp` carries what `K` says it does.
|
||||
/// An item of library `id` dragged out of its tile or row `resp` with the primary button carries
|
||||
/// what `K` says it does.
|
||||
fn drag_out<K: LibraryKind>(ui: &Ui, resp: &egui::Response, id: &str, row: &Row<K::Item>) {
|
||||
if row.item.is_some()
|
||||
&& resp.drag_started()
|
||||
&& resp.drag_started_by(egui::PointerButton::Primary)
|
||||
&& let Some(drag) = K::drag(id, row.name)
|
||||
{
|
||||
egui::DragAndDrop::set_payload(ui.ctx(), drag);
|
||||
|
||||
@@ -117,14 +117,15 @@ pub(super) struct TileEvents {
|
||||
}
|
||||
|
||||
/// Clicks, double-clicks, tooltips and drag and drop of the tile or row `resp` of entry `e`
|
||||
/// (`items`: the panel's rows, `sel`: its selection, `list`: rows stack downwards). A drag from it
|
||||
/// starts a [`PanelDrag`] carrying the rows it moves; see [`tile_drop`] for drags held over it.
|
||||
/// (`items`: the panel's rows, `sel`: its selection, `list`: rows stack downwards). A primary-button
|
||||
/// drag from it starts a [`PanelDrag`] carrying the rows it moves; see [`tile_drop`] for drags held
|
||||
/// over it.
|
||||
pub(super) fn tile_input(ui: &Ui, resp: Response, e: &Entry, items: &[Entry], sel: &[String], list: bool, ev: &mut TileEvents) {
|
||||
let name = e.name();
|
||||
if matches!(e, Entry::Swatch { .. } | Entry::Folder(_)) && resp.double_clicked() {
|
||||
ev.edit = Some(e.clone());
|
||||
}
|
||||
if resp.drag_started() {
|
||||
if resp.drag_started_by(egui::PointerButton::Primary) {
|
||||
let with_sel = sel.iter().any(|s| s == name);
|
||||
let names = items
|
||||
.iter()
|
||||
|
||||
@@ -533,6 +533,50 @@ fn dragging_tiles_reorders_and_moves_into_groups_as_one_undo_step_each() {
|
||||
assert_eq!((names_of(&app, None), app.session.doc().unwrap().history.undo.len()), (before, undo));
|
||||
}
|
||||
|
||||
/// Press `pointer` at `from`, drag to `to` and release there, a frame per step from `time`. Returns
|
||||
/// whether a drag-and-drop payload was held over `to` before the release.
|
||||
fn drag_by(app: &mut VectorcraftApp, ctx: &egui::Context, from: Pos2, to: Pos2, pointer: PointerButton, time: f64) -> bool {
|
||||
let button = |pos, pressed| Event::PointerButton { pos, button: pointer, pressed, modifiers: Modifiers::NONE };
|
||||
frame(app, ctx, vec![Event::PointerMoved(from), button(from, true)], time, show);
|
||||
frame(app, ctx, vec![Event::PointerMoved(from + vec2(6.0, 4.0))], time + 0.1, show);
|
||||
frame(app, ctx, vec![Event::PointerMoved(to)], time + 0.2, show);
|
||||
let held = egui::DragAndDrop::has_any_payload(ctx);
|
||||
frame(app, ctx, vec![Event::PointerMoved(to), button(to, false)], time + 0.3, show);
|
||||
frame(app, ctx, vec![], time + 0.4, show);
|
||||
held
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn only_a_primary_drag_moves_swatches_and_groups() {
|
||||
let mut app = app();
|
||||
let ctx = context();
|
||||
frame(&mut app, &ctx, vec![], 0.0, show);
|
||||
frame(&mut app, &ctx, vec![], 0.5, show);
|
||||
let undo = app.session.doc().unwrap().history.undo.len();
|
||||
let (before, grays) = (names_of(&app, None), names_of(&app, Some("Grays")));
|
||||
let groups = |app: &VectorcraftApp| app.session.active().unwrap().doc.swatch_groups.iter().map(|g| g.name.clone()).collect::<Vec<_>>();
|
||||
let group_order = groups(&app);
|
||||
let mut time = 1.0;
|
||||
for pointer in [PointerButton::Secondary, PointerButton::Middle] {
|
||||
// A swatch onto the left half of Red, and onto a folder.
|
||||
let held = drag_by(&mut app, &ctx, tile_center(&ctx, "Amber"), tile_center(&ctx, "Red") - vec2(4.0, 0.0), pointer, time);
|
||||
assert!(!held, "a {pointer:?} drag carries no swatch");
|
||||
let held = drag_by(&mut app, &ctx, tile_center(&ctx, "Amber"), tile_center(&ctx, "Grays"), pointer, time + 1.0);
|
||||
assert!(!held, "a {pointer:?} drag carries no swatch into a group");
|
||||
// A group onto another group.
|
||||
let held = drag_by(&mut app, &ctx, tile_center(&ctx, "Grays"), tile_center(&ctx, "Brights") - vec2(4.0, 0.0), pointer, time + 2.0);
|
||||
assert!(!held, "a {pointer:?} drag carries no group");
|
||||
assert_eq!((names_of(&app, None), names_of(&app, Some("Grays")), groups(&app)), (before.clone(), grays.clone(), group_order.clone()));
|
||||
assert_eq!(app.session.doc().unwrap().history.undo.len(), undo, "a {pointer:?} drag records no undo step");
|
||||
time += 3.0;
|
||||
}
|
||||
// The primary button still moves the swatch.
|
||||
assert!(drag_by(&mut app, &ctx, tile_center(&ctx, "Amber"), tile_center(&ctx, "Red") - vec2(4.0, 0.0), PointerButton::Primary, time));
|
||||
let n = names_of(&app, None);
|
||||
assert_eq!(n[n.iter().position(|x| x == "Red").unwrap() - 1], "Amber");
|
||||
assert_eq!(app.session.doc().unwrap().history.undo.len(), undo + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn art_dropped_on_the_panel_becomes_a_pattern_swatch() {
|
||||
let mut app = app();
|
||||
|
||||
@@ -8,7 +8,12 @@ use super::tests_appearance::{app_with_rect, click, frame_events, frame_raw, run
|
||||
use super::*;
|
||||
|
||||
fn pointer(pos: egui::Pos2, pressed: bool, modifiers: egui::Modifiers) -> egui::Event {
|
||||
egui::Event::PointerButton { pos, button: egui::PointerButton::Primary, pressed, modifiers }
|
||||
pointer_by(pos, pressed, modifiers, egui::PointerButton::Primary)
|
||||
}
|
||||
|
||||
/// `button` pressed (or released) at `pos` with `modifiers`.
|
||||
fn pointer_by(pos: egui::Pos2, pressed: bool, modifiers: egui::Modifiers, button: egui::PointerButton) -> egui::Event {
|
||||
egui::Event::PointerButton { pos, button, pressed, modifiers }
|
||||
}
|
||||
|
||||
/// One frame of the Appearance panel with `events` and `modifiers` held.
|
||||
@@ -19,12 +24,17 @@ fn panel_frame(ctx: &egui::Context, app: &mut VectorcraftApp, events: Vec<egui::
|
||||
|
||||
/// Drag from `from` to `to` in the Appearance panel, `modifiers` held on release.
|
||||
fn drag(ctx: &egui::Context, app: &mut VectorcraftApp, from: egui::Pos2, to: egui::Pos2, modifiers: egui::Modifiers) {
|
||||
drag_by(ctx, app, from, to, modifiers, egui::PointerButton::Primary);
|
||||
}
|
||||
|
||||
/// [`drag`] with `button`.
|
||||
fn drag_by(ctx: &egui::Context, app: &mut VectorcraftApp, from: egui::Pos2, to: egui::Pos2, modifiers: egui::Modifiers, button: egui::PointerButton) {
|
||||
let none = egui::Modifiers::NONE;
|
||||
panel_frame(ctx, app, vec![egui::Event::PointerMoved(from)], none);
|
||||
panel_frame(ctx, app, vec![pointer(from, true, none)], none);
|
||||
panel_frame(ctx, app, vec![pointer_by(from, true, none, button)], none);
|
||||
panel_frame(ctx, app, vec![egui::Event::PointerMoved(from + egui::vec2(0.0, 8.0))], none);
|
||||
panel_frame(ctx, app, vec![egui::Event::PointerMoved(to)], modifiers);
|
||||
panel_frame(ctx, app, vec![pointer(to, false, modifiers)], modifiers);
|
||||
panel_frame(ctx, app, vec![pointer_by(to, false, modifiers, button)], modifiers);
|
||||
panel_frame(ctx, app, vec![], none);
|
||||
}
|
||||
|
||||
@@ -233,3 +243,40 @@ fn the_thumbnail_drags_the_appearance_and_the_properties_fx_button_opens_the_eff
|
||||
let texts = frame_raw(&props, &mut app, Default::default(), properties::show);
|
||||
assert!(texts.iter().any(|(t, _)| t == "Distort & Transform"), "{texts:?}");
|
||||
}
|
||||
|
||||
/// A secondary or middle drag of the thumbnail carries no appearance and shows no grabbing hand,
|
||||
/// and one of a fill or stroke row neither moves nor copies it; the primary button still does.
|
||||
#[test]
|
||||
fn only_a_primary_drag_carries_the_thumbnail_or_a_row() {
|
||||
let mut app = app_with_rect(); // [Fill, Stroke]
|
||||
let ctx = egui::Context::default();
|
||||
let none = egui::Modifiers::NONE;
|
||||
let kinds = |app: &VectorcraftApp| first_selected(app).unwrap().appearance.items.iter().map(|i| i.kind_name()).collect::<Vec<_>>();
|
||||
let undo = app.session.doc().unwrap().history.undo.len();
|
||||
for button in [egui::PointerButton::Secondary, egui::PointerButton::Middle] {
|
||||
let texts = panel_frame(&ctx, &mut app, vec![], none);
|
||||
let label = text_rect(&texts, "Rectangle");
|
||||
let thumb = egui::pos2(label.left() - 28.0, label.center().y);
|
||||
for e in [egui::Event::PointerMoved(thumb), pointer_by(thumb, true, none, button)] {
|
||||
panel_frame(&ctx, &mut app, vec![e], none);
|
||||
}
|
||||
let held = thumb + egui::vec2(30.0, 30.0);
|
||||
let mut out =
|
||||
ctx.run_ui(egui::RawInput { events: vec![egui::Event::PointerMoved(held)], ..Default::default() }, |ui| appearance::show(&mut app, ui));
|
||||
out.textures_delta.clear();
|
||||
assert!(!egui::DragAndDrop::has_any_payload(&ctx), "a {button:?} drag of the thumbnail carries nothing");
|
||||
assert_ne!(out.platform_output.cursor_icon, egui::CursorIcon::Grabbing, "{button:?}");
|
||||
panel_frame(&ctx, &mut app, vec![pointer_by(held, false, none, button)], none);
|
||||
panel_frame(&ctx, &mut app, vec![], none);
|
||||
// The fill dragged onto the stroke row, with and without Alt.
|
||||
for modifiers in [none, egui::Modifiers::ALT] {
|
||||
let texts = panel_frame(&ctx, &mut app, vec![], none);
|
||||
drag_by(&ctx, &mut app, row_of(&texts, "Fill:"), row_of(&texts, "Stroke:") + egui::vec2(0.0, 9.0), modifiers, button);
|
||||
assert_eq!(kinds(&app), ["fill", "stroke"], "a {button:?} drag moves and copies nothing");
|
||||
}
|
||||
}
|
||||
assert_eq!(app.session.doc().unwrap().history.undo.len(), undo, "no undo step");
|
||||
let texts = panel_frame(&ctx, &mut app, vec![], none);
|
||||
drag(&ctx, &mut app, row_of(&texts, "Fill:"), row_of(&texts, "Stroke:"), egui::Modifiers::ALT);
|
||||
assert_eq!(kinds(&app), ["fill", "stroke", "fill"], "a primary Alt-drag copies the fill");
|
||||
}
|
||||
|
||||
@@ -106,6 +106,37 @@ fn clicking_a_library_symbol_adds_it_to_the_documents_symbols_in_one_step() {
|
||||
assert!(last_open(&app.ui).is_none());
|
||||
}
|
||||
|
||||
/// A secondary or middle drag out of a library tile carries no symbol and adds nothing; a primary
|
||||
/// drag still carries it.
|
||||
#[test]
|
||||
fn only_a_primary_drag_carries_a_library_symbol_out() {
|
||||
let mut app = app();
|
||||
let ctx = context();
|
||||
app.run("window.symbolLibrary", json!({"library": "Basic Shapes"})).unwrap();
|
||||
let undo = undo_len(&app);
|
||||
let mut time = 0.0;
|
||||
let mut drag = |app: &mut VectorcraftApp, pointer: PointerButton| {
|
||||
let at = tile(app, &ctx, "Burst", time);
|
||||
let button = |pos, pressed| Event::PointerButton { pos, button: pointer, pressed, modifiers: Modifiers::NONE };
|
||||
frame(&ctx, vec![Event::PointerMoved(at), button(at, true)], time + 0.5, |ui| library_panel::show_window(app, ui.ctx()));
|
||||
for (i, d) in [20.0, 60.0].into_iter().enumerate() {
|
||||
frame(&ctx, vec![Event::PointerMoved(at + vec2(d, d))], time + 0.6 + 0.1 * i as f64, |ui| library_panel::show_window(app, ui.ctx()));
|
||||
}
|
||||
let carried = egui::DragAndDrop::payload::<PanelDrag>(&ctx).map(|p| (*p).clone());
|
||||
let end = at + vec2(60.0, 60.0);
|
||||
frame(&ctx, vec![button(end, false)], time + 0.9, |ui| library_panel::show_window(app, ui.ctx()));
|
||||
frame(&ctx, vec![], time + 1.0, |ui| library_panel::show_window(app, ui.ctx()));
|
||||
time += 2.0;
|
||||
carried
|
||||
};
|
||||
for pointer in [PointerButton::Secondary, PointerButton::Middle] {
|
||||
assert_eq!(drag(&mut app, pointer), None, "a {pointer:?} drag carries nothing");
|
||||
}
|
||||
assert_eq!((symbols(&app).len(), undo_len(&app)), (0, undo), "nothing is added");
|
||||
let carried = drag(&mut app, PointerButton::Primary);
|
||||
assert_eq!(carried, Some(PanelDrag::LibrarySymbol { library: "basic-shapes".into(), name: "Burst".into() }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_window_menu_and_the_symbols_panel_open_symbol_libraries() {
|
||||
let mut app = app();
|
||||
|
||||
@@ -273,7 +273,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui, kind: Kind) {
|
||||
// Overrides: an attribute the style sets that the selection doesn't match.
|
||||
let overridden = is_cur && cur.as_ref().is_some_and(|(_, m)| attrs.iter().any(|(k, v)| m.get(k) != Some(v)));
|
||||
let (r, resp) = ui.allocate_exact_size(vec2(ui.available_width(), 22.0), Sense::click_and_drag());
|
||||
if resp.drag_started() {
|
||||
if resp.drag_started_by(egui::PointerButton::Primary) {
|
||||
egui::DragAndDrop::set_payload(ui.ctx(), RowDrag { kind, name: name.clone() });
|
||||
}
|
||||
if scroll_to.as_deref() == Some(name.as_str()) {
|
||||
|
||||
@@ -184,6 +184,44 @@ fn dragging_a_style_onto_delete_deletes_it() {
|
||||
}
|
||||
}
|
||||
|
||||
/// A secondary or middle drag of a style row onto Create New Style or Delete carries no row and
|
||||
/// runs nothing; a primary drag still deletes.
|
||||
#[test]
|
||||
fn only_a_primary_drag_carries_a_style_row() {
|
||||
for kind in [Kind::Char, Kind::Para] {
|
||||
let (mut app, _) = drag_app();
|
||||
let ctx = egui::Context::default();
|
||||
let before = styles(&mut app, kind);
|
||||
let undo = app.session.doc().unwrap().history.undo.len();
|
||||
let commands = app.run_count;
|
||||
for pointer in [egui::PointerButton::Secondary, egui::PointerButton::Middle] {
|
||||
for from_right in [40.0, 12.0] {
|
||||
let button = std::cell::Cell::new(egui::Pos2::ZERO);
|
||||
let mut draw = |app: &mut VectorcraftApp, ui: &mut egui::Ui| {
|
||||
ui.set_width(280.0);
|
||||
let right = ui.max_rect().right();
|
||||
show(app, ui, kind);
|
||||
button.set(egui::pos2(right - from_right, ui.min_rect().bottom() - 12.0));
|
||||
};
|
||||
frame_events(&ctx, &mut app, vec![], &mut draw);
|
||||
let row = text_rect(&frame_events(&ctx, &mut app, vec![], &mut draw), "Body").center();
|
||||
let press = |pos, pressed| egui::Event::PointerButton { pos, button: pointer, pressed, modifiers: Default::default() };
|
||||
frame_events(&ctx, &mut app, vec![egui::Event::PointerMoved(row), press(row, true)], &mut draw);
|
||||
frame_events(&ctx, &mut app, vec![egui::Event::PointerMoved(row + vec2(0.0, 12.0))], &mut draw);
|
||||
let to = button.get();
|
||||
frame_events(&ctx, &mut app, vec![egui::Event::PointerMoved(to)], &mut draw);
|
||||
assert!(!egui::DragAndDrop::has_any_payload(&ctx), "{}: a {pointer:?} drag carries no row", kind.what());
|
||||
frame_events(&ctx, &mut app, vec![press(to, false)], &mut draw);
|
||||
frame_events(&ctx, &mut app, vec![], &mut draw);
|
||||
}
|
||||
}
|
||||
assert_eq!((app.run_count, styles(&mut app, kind)), (commands, before.clone()), "{}: nothing runs", kind.what());
|
||||
assert_eq!(app.session.doc().unwrap().history.undo.len(), undo, "no undo step");
|
||||
assert!(drag_row_onto_footer(&ctx, &mut app, kind, "Body", 12.0, false), "{} Styles: Delete is outlined", kind.what());
|
||||
assert_eq!(styles(&mut app, kind).len(), before.len() - 1, "{}: a primary drag deletes Body", kind.what());
|
||||
}
|
||||
}
|
||||
|
||||
fn capture_app() -> (VectorcraftApp, NodeId, egui::Context) {
|
||||
let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 300, "height": 200})).unwrap();
|
||||
|
||||
@@ -88,10 +88,10 @@ impl PanelDrag {
|
||||
}
|
||||
}
|
||||
|
||||
/// Make `resp` (which senses drags) a source of the [`PanelDrag`] `drag` builds when a drag starts
|
||||
/// on it.
|
||||
/// Make `resp` (which senses drags) a source of the [`PanelDrag`] `drag` builds when a drag with the
|
||||
/// primary button starts on it. A secondary or middle drag carries nothing.
|
||||
pub fn drag_source(ui: &Ui, resp: &Response, drag: impl FnOnce() -> PanelDrag) {
|
||||
if resp.drag_started() {
|
||||
if resp.drag_started_by(egui::PointerButton::Primary) {
|
||||
egui::DragAndDrop::set_payload(ui.ctx(), drag());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -294,7 +294,7 @@ other `sv-*` locale resolve to it), Georgian (`ka`, complete; `ka-GE` and `ka_GE
|
||||
control channel, MCP and tests read them) and are translated only where the status bar draws them
|
||||
(`i18n::msg`). `@msg` catalog rows hold a whole message or a template such as
|
||||
`Couldn't open {name}: {e}`; `{_1}`, `{_2}` … stand for the format string's `{}`, and the values in the
|
||||
placeholders are translated in turn (the reason after `: {e}` is often a message too). Czech, German, Greek, Spanish, French, Georgian, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish and Catalan
|
||||
placeholders are translated in turn (the reason after `: {e}` is often a message too). Czech, German, Greek, Spanish, French, Georgian, Hungarian, Italian, Japanese, Korean, Polish, Brazilian Portuguese, Russian, Simplified Chinese, Traditional Chinese, Swedish, Ukrainian, Vietnamese, Finnish, Turkish, Catalan and Dutch
|
||||
translate status and error messages (`COMPLETE_MESSAGES` in `i18n::tests`); the untranslated report lists the
|
||||
message literals the scan finds that one of them has no row for. The scan reads `Err("…")`, `Other(…)`,
|
||||
`#[error(…)]` and `status(…)` messages, messages given to an error enum's variant (`PsError::Limit(…)`, the reason
|
||||
|
||||
@@ -15,7 +15,7 @@ translation never fails a test or a build: the interface shows the English text
|
||||
`cargo xtask ci` prints the untranslated report (`cargo xtask i18n-report` alone), which lists per language the
|
||||
strings missing from each catalog with the `complete_menus` flag and the messages missing from each language in
|
||||
the `COMPLETE_MESSAGES` list. Every non-English language marked "full" has the flag, and all of them except
|
||||
Bulgarian, Danish, Indonesian and Dutch are in the list. No language has help content: there is no translated (or
|
||||
Bulgarian, Danish and Indonesian are in the list. No language has help content: there is no translated (or
|
||||
English) in-app help, and the docs are English.
|
||||
|
||||
**Native review:** every catalog was written clean-room from the English meaning, most of it by agents
|
||||
@@ -51,7 +51,7 @@ plus review. Native-speaker review is human work and isn't in the hours.
|
||||
|---|---|---|---|
|
||||
| Traditional Chinese (Taiwan) | `zh-hant` | 4,892 rows, 790 of them `@msg` (counted 2026-10-21): menus, `tl!` literals and messages complete when counted (80% overall) | partial |
|
||||
| Italian | `it` | 4,011 / 4,020 | full |
|
||||
| Dutch | `nl` | 5,317 rows, 777 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one/other plurals | full |
|
||||
| Dutch | `nl` | 7,299 rows, 1,609 of them `@msg` and 47 `@msgplural` (counted 2026-11-13 on `main` at `9a1a158a3`): in `COMPLETE_MESSAGES`, and the untranslated report lists the same missing messages for it as for German; one/other plurals | full |
|
||||
| Danish | `da` | 5,279 rows, 750 of them `@msg` (counted 2026-10-21): menus and `tl!` literals complete when counted; its messages are partial; one/other plurals | full |
|
||||
| Russian | `ru` | 4,009 / 4,020 | full |
|
||||
| Ukrainian | `uk` | 4,009 / 4,020 (one/few/many plurals) | full |
|
||||
|
||||
+9
-1
@@ -4061,7 +4061,15 @@ center?, to?}` uses one: a graphic is placed centred on `center` (pasted with it
|
||||
gives another colour merges into the document's), a colour paints the selection's fill or stroke, and a style is added
|
||||
to the document under its name without the white space around it (numbered when that name is taken by other
|
||||
attributes) and applied to the selected text, each as one undo step. `library.removeItem {library?, kind, item}` removes
|
||||
one.
|
||||
one. `library.addToCharacterStyles {library?, item}` adds a character style to the document's character styles without
|
||||
applying it, so no text needs to be selected: a document style of that name with the same attributes is reused
|
||||
(`existing: true`, no undo step), and a name taken by other attributes gets a number, as `library.use` names it; a new
|
||||
style is one undo step. With either command, a character style's color linked to a swatch that is not a global or spot
|
||||
swatch of the document keeps the color it shows without the link. `library.renameItem {library?, kind, item, name}` renames an item in place, its group keeping it
|
||||
(a graphic keeps its id); the name is trimmed and has 1 to 256 characters, another item of its kind with that name is
|
||||
an error, renaming an item to its own name writes nothing, and a rename is not a document undo step. A right-click on a
|
||||
character style in the panel offers Apply Character Style (with type selected), Add to Character Styles, Move to Group,
|
||||
Rename… and Delete ([help page](https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/add-and-use-text-and-character-styles-in-libraries.html)).
|
||||
|
||||
Gradients and patterns are kinds of their own (the panel's + button lists Fill Gradient, Stroke Gradient, Fill Pattern
|
||||
and Stroke Pattern, and a gradient or pattern swatch dragged from the Swatches panel onto the list is added).
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user