diff --git a/crates/engine/src/cmd/draw2/curves3d.rs b/crates/engine/src/cmd/draw2/curves3d.rs index 005c49f07..faad5442c 100644 --- a/crates/engine/src/cmd/draw2/curves3d.rs +++ b/crates/engine/src/cmd/draw2/curves3d.rs @@ -153,19 +153,17 @@ impl Interactive for HelixM { } match (self.center, self.rb, self.rt) { (None, ..) => Prompt::new("Specify center point of base", Accept::POINT), - (Some(c), None, _) => { - Prompt::new(if self.diameter { "Specify base diameter" } else { "Specify base radius or" }, Accept::POINT_OR_NUMBER) - .kw(if self.diameter { &[] } else { &["Diameter"] }) - .default("1.0000") - .base(c) - } + (Some(c), None, _) => Prompt::new(if self.diameter { "Specify base diameter" } else { "Specify base radius" }, Accept::POINT_OR_NUMBER) + .kw(if self.diameter { &[] } else { &["Diameter"] }) + .default("1.0000") + .base(c), (Some(c), Some(rb), None) => { - Prompt::new(if self.diameter { "Specify top diameter" } else { "Specify top radius or" }, Accept::POINT_OR_NUMBER) + Prompt::new(if self.diameter { "Specify top diameter" } else { "Specify top radius" }, Accept::POINT_OR_NUMBER) .kw(if self.diameter { &[] } else { &["Diameter"] }) .default(format!("{rb:.4}")) .base(c) } - (Some(c), Some(_), Some(_)) => Prompt::new("Specify helix height or", Accept::POINT_OR_NUMBER) + (Some(c), Some(_), Some(_)) => Prompt::new("Specify helix height", Accept::POINT_OR_NUMBER) .kw(&["Axis endpoint", "Turns", "turn Height", "tWist"]) .default("1.0000") .base(c), diff --git a/crates/engine/src/cmd/draw2/xline.rs b/crates/engine/src/cmd/draw2/xline.rs index 31f152d16..78ab5c610 100644 --- a/crates/engine/src/cmd/draw2/xline.rs +++ b/crates/engine/src/cmd/draw2/xline.rs @@ -119,7 +119,7 @@ impl Interactive for XlineM2 { Some(b) => Prompt::new("Specify through point", Accept::POINT).base(b), }, XMode::Fixed(_) => Prompt::new("Specify through point", Accept::POINT), - XMode::AngAsk => Prompt::new("Enter angle of xline (0) or", Accept::NUMBER).kw(&["Reference"]), + XMode::AngAsk => Prompt::new("Enter angle of xline (0)", Accept::NUMBER).kw(&["Reference"]), XMode::RefSelect => Prompt::new("Select a line object", Accept::POINT), XMode::RefAngle(_) => Prompt::new("Enter angle of xline", Accept::NUMBER).default("0"), XMode::Bisect => match self.bis.len() { @@ -129,7 +129,7 @@ impl Interactive for XlineM2 { }, XMode::OffDist => { let d = s.doc().map(|d| d.header.f64("OFFSETDIST", 1.0)).unwrap_or(1.0); - Prompt::new("Specify offset distance or", Accept::NUMBER).kw(&["Through"]).default(if d < 0.0 { + Prompt::new("Specify offset distance", Accept::NUMBER).kw(&["Through"]).default(if d < 0.0 { "Through".into() } else { format!("{d:.4}") diff --git a/crates/engine/src/cmd/inquiry.rs b/crates/engine/src/cmd/inquiry.rs index 119d727e1..364fa6796 100644 --- a/crates/engine/src/cmd/inquiry.rs +++ b/crates/engine/src/cmd/inquiry.rs @@ -217,6 +217,11 @@ fn run_dist(s: &mut Session, p: &Value) -> Result { let a = point3_req(s, "dist", p, "p1")?; let b = point3_req(s, "dist", p, "p2")?; let d = b - a; + if !d.len().is_finite() { + return Err(bad("dist", "the distance is too large")); + } + s.distance = d.len(); + s.last_point = a.xy(); Ok(json!({ "distance": d.len(), "angle": d.xy().angle().to_degrees(), @@ -430,6 +435,8 @@ fn run_area(s: &mut Session, p: &Value) -> Result { if let Some(what) = too_large(a, per) { return Err(bad("area", format!("the {what} is too large"))); } + s.area = a; + s.perimeter = per; Ok(json!({ "area": a, "perimeter": per, "message": area_text(s, a, per) })) } @@ -516,6 +523,13 @@ pub(super) fn object_area(s: &Session, h: Handle) -> Result<(f64, f64)> { total } EntityKind::Region(r) => (r.area(), r.perimeter()), + // Like an open polyline: the area closed by the chord, the perimeter its own length. + EntityKind::Spline(sp) if sp.is_valid() => { + let b = sp.bounds(); + let pts = sp.tessellate_spans((b.min.dist(b.max) * 1e-7).max(1e-12)); + // A length past f64's range is too large to report, as a polyline's is, not 0. + (cadcraft_geom::shoelace(&pts).abs(), sp.checked_length().unwrap_or(f64::INFINITY)) + } _ => return Err(bad("area", "object has no area")), }) } @@ -872,16 +886,25 @@ impl Interactive for DistM { self.first_source = s.picked_viewport; Ok(Step::Continue) } - (Some(a), Input::Point(b)) => { + (Some(first), Input::Point(b)) => { let (a, b) = match (self.first_source, s.picked_viewport) { (Some(first), Some(second)) if first.viewport == second.viewport => (first.point, second.point), - _ => (a, b), + _ => (first, b), }; let (za, zb) = if self.first_source.is_some() || s.picked_viewport.is_some() { (0.0, 0.0) } else { (z_at(s, a), z_at(s, b)) }; - let t = dist_text(s, Vec3::new(a.x, a.y, za), Vec3::new(b.x, b.y, zb)); + let (a, b) = (Vec3::new(a.x, a.y, za), Vec3::new(b.x, b.y, zb)); + if !(b - a).len().is_finite() { + // The first point stays LASTPOINT, as after a measurement. + s.last_point = first; + return Err(bad("dist", "the distance is too large")); + } + let t = dist_text(s, a, b); for l in t.lines() { s.echo(l.to_string()); } + // As in AutoCAD, the second point doesn't become LASTPOINT: the first stays. + s.distance = (b - a).len(); + s.last_point = first; Ok(Step::Done) } (Some(a), Input::Keyword(k)) if k == "Multiple points" => { @@ -909,7 +932,11 @@ impl DistM { .as_deref() .or(self.multi.as_deref()) .map_or(0.0, |pts| if closed { arcs::polyline(pts, &self.bulges, true).len() } else { path_len(pts, &self.bulges) }); + if !d.is_finite() { + return Err(bad("dist", "the distance is too large")); + } s.echo(format!("Distance = {}", fmt_d(s, d))); + s.distance = d; Ok(Step::Done) } } @@ -1123,10 +1150,14 @@ impl AreaM { return if self.mode == AreaMode::Single { Step::Done } else { Step::Continue }; } s.echo(area_text(s, a, per)); + // AREA: this area, or in Add and Subtract mode the running total; PERIMETER: this area's. + s.perimeter = per; if self.mode == AreaMode::Single { + s.area = a; return Step::Done; } self.total = total; + s.area = total; s.echo(format!("Total area = {}", fmt_d(s, self.total))); Step::Continue } diff --git a/crates/engine/src/cmd/modify2/blend.rs b/crates/engine/src/cmd/modify2/blend.rs index 32b477eea..ef2258969 100644 --- a/crates/engine/src/cmd/modify2/blend.rs +++ b/crates/engine/src/cmd/modify2/blend.rs @@ -81,7 +81,7 @@ impl Interactive for BlendM { return Prompt::new("Enter continuity", curves::KW).kw(&["Tangent", "Smooth"]).default("Tangent"); } match self.first { - None => Prompt::new("Select first object or", Accept::POINT).kw(&["CONtinuity"]), + None => Prompt::new("Select first object", Accept::POINT).kw(&["CONtinuity"]), Some(_) => Prompt::new("Select second point", Accept::POINT), } } diff --git a/crates/engine/src/cmd/modify2/lengthen.rs b/crates/engine/src/cmd/modify2/lengthen.rs index 0c86c2c9c..7597ca771 100644 --- a/crates/engine/src/cmd/modify2/lengthen.rs +++ b/crates/engine/src/cmd/modify2/lengthen.rs @@ -194,14 +194,14 @@ impl Interactive for LengthenM { fn prompt(&self, _s: &Session) -> Prompt { match self.phase { LPhase::Main => { - Prompt::new("Select an object to measure or", Accept::POINT).kw(&["DElta", "Percent", "Total", "DYnamic"]).default("DYnamic") + Prompt::new("Select an object to measure", Accept::POINT).kw(&["DElta", "Percent", "Total", "DYnamic"]).default("DYnamic") } - LPhase::Delta => Prompt::new("Enter delta length or", Accept::NUMBER).kw(&["Angle"]).default("0.0000"), + LPhase::Delta => Prompt::new("Enter delta length", Accept::NUMBER).kw(&["Angle"]).default("0.0000"), LPhase::DeltaAngle => Prompt::new("Enter delta angle", Accept::NUMBER).default("0"), LPhase::Percent => Prompt::new("Enter percentage length", Accept::NUMBER).default("100.0000"), - LPhase::Total => Prompt::new("Specify total length or", Accept::NUMBER).kw(&["Angle"]).default("1.0000"), + LPhase::Total => Prompt::new("Specify total length", Accept::NUMBER).kw(&["Angle"]).default("1.0000"), LPhase::TotalAngle => Prompt::new("Specify total angle", Accept::NUMBER).default("57"), - LPhase::Change => Prompt::new("Select an object to change or", Accept::POINT).kw(&["Undo"]), + LPhase::Change => Prompt::new("Select an object to change", Accept::POINT).kw(&["Undo"]), LPhase::DynEnd(..) => Prompt::new("Specify new end point", Accept::POINT), } } diff --git a/crates/engine/src/cmd/modify2/ncopy.rs b/crates/engine/src/cmd/modify2/ncopy.rs index 475256e84..9b6f9eeb2 100644 --- a/crates/engine/src/cmd/modify2/ncopy.rs +++ b/crates/engine/src/cmd/modify2/ncopy.rs @@ -87,8 +87,8 @@ impl Interactive for NcopyM { } fn prompt(&self, _s: &Session) -> Prompt { match (self.selecting_done, self.base) { - (false, _) => Prompt::new("Select nested objects to copy or", Accept::POINT).kw(&["Settings"]), - (true, None) => Prompt::new("Specify base point or", Accept::POINT).kw(&["Displacement", "Multiple"]).default("Displacement"), + (false, _) => Prompt::new("Select nested objects to copy", Accept::POINT).kw(&["Settings"]), + (true, None) => Prompt::new("Specify base point", Accept::POINT).kw(&["Displacement", "Multiple"]).default("Displacement"), (true, Some(b)) => Prompt::new("Specify second point or ", Accept::POINT).base(b), } } diff --git a/crates/engine/src/cmd/modify2/pedit.rs b/crates/engine/src/cmd/modify2/pedit.rs index 0c1b64879..59d614323 100644 --- a/crates/engine/src/cmd/modify2/pedit.rs +++ b/crates/engine/src/cmd/modify2/pedit.rs @@ -398,7 +398,7 @@ impl Interactive for PeditM { fn prompt(&self, s: &Session) -> Prompt { match self.phase { PPhase::MSelect | PPhase::MConvert | PPhase::MMain | PPhase::MWidth | PPhase::MFuzz => self.multi_prompt(), - PPhase::Select => Prompt::new("Select polyline or", Accept::POINT).kw(&["Multiple"]), + PPhase::Select => Prompt::new("Select polyline", Accept::POINT).kw(&["Multiple"]), PPhase::Convert => { Prompt::new("Object selected is not a polyline. Do you want to turn it into one?", curves::KW).kw(&["Yes", "No"]).default("Y") } diff --git a/crates/engine/src/cmd/overkill.rs b/crates/engine/src/cmd/overkill.rs index abfdff2eb..632001461 100644 --- a/crates/engine/src/cmd/overkill.rs +++ b/crates/engine/src/cmd/overkill.rs @@ -146,20 +146,49 @@ impl Opts { } } -/// Round every number of a JSON value to a multiple of `q`. -fn quantize(v: &mut Value, q: f64) { +/// Take the measurements (floating-point numbers) out of a JSON value, in order, leaving a marker +/// in their place: two objects are equal when what is left matches, counts and flags included, +/// and each pair of measurements is within the tolerance. +fn split_numbers(v: &mut Value, nums: &mut Vec) { match v { Value::Number(n) => { - if let Some(x) = n.as_f64() { - *v = json!((x / q).round()); + if n.is_f64() + && let Some(x) = n.as_f64() + { + nums.push(x); + *v = Value::String(NUMBER.into()); } } - Value::Array(a) => a.iter_mut().for_each(|x| quantize(x, q)), - Value::Object(o) => o.values_mut().for_each(|x| quantize(x, q)), + Value::Array(a) => a.iter_mut().for_each(|x| split_numbers(x, nums)), + Value::Object(o) => o.values_mut().for_each(|x| split_numbers(x, nums)), _ => {} } } +/// What [`split_numbers`] leaves where a number was. +const NUMBER: &str = "\u{0}#"; + +/// Whether two lists of numbers match pairwise to within `tol`. +fn within(a: &[f64], b: &[f64], tol: f64) -> bool { + a.len() == b.len() && a.iter().zip(b).all(|(x, y)| (x - y).abs() <= tol) +} + +/// The numbers summed with weights in [1, 2) that no simple pattern shares (golden-ratio steps), +/// so points on a diagonal of a grid don't all get the same sum; and the sum of the weights. +fn weighted_sum(nums: &[f64]) -> (f64, f64) { + nums.iter().enumerate().fold((0.0, 0.0), |(sum, total), (j, x)| { + let w = 1.0 + (j as f64 * 0.618_033_988_749_895).fract(); + (sum + w * x, total + w) + }) +} + +/// The cell of `x` on a grid of `step`. Values within one step of each other land in the same or +/// neighbouring cells; values too large for the grid share the outermost ones. +fn cell_of(x: f64, step: f64) -> i64 { + let k = (x / step).floor(); + if k.is_finite() { k.clamp(-9e15, 9e15) as i64 } else { i64::MIN } +} + #[derive(Default)] struct Report { duplicates: usize, @@ -234,33 +263,37 @@ fn overkill(s: &mut Session, hs: Option>, o: &Opts) -> Result = HashMap::new(); - for (i, c) in cands.iter().enumerate() { + // Keepers so far: (properties, shape) → cell of the sum → their numbers. + type Keepers = HashMap>>; + let mut seen: HashMap<(u32, String), Keepers> = HashMap::new(); + // Followed objects first, so a keeper is never displaced: everything deleted is within the + // tolerance of an object that stays. + let (followed, rest): (Vec, Vec) = (0..cands.len()).partition(|i| cands.get(*i).is_some_and(|c| c.protected)); + for i in followed.into_iter().chain(rest) { + let Some(c) = cands.get(i) else { continue }; let Ok(mut v) = serde_json::to_value(&c.e.kind) else { continue }; - if o.tol > 0.0 { - quantize(&mut v, o.q()); + let mut nums = Vec::new(); + split_numbers(&mut v, &mut nums); + let (sum, weights) = weighted_sum(&nums); + let cell = cell_of(sum, o.q() * weights.max(1.0)); + let cells = seen.entry((c.prop, v.to_string())).or_default(); + let found = [cell.saturating_sub(1), cell, cell.saturating_add(1)] + .into_iter() + .any(|k| cells.get(&k).is_some_and(|keepers| keepers.iter().any(|n| within(n, &nums, o.tol)))); + if !found || c.protected { + // A followed object stays even when it matches another. + cells.entry(cell).or_default().push(nums); + continue; } - let key = (c.prop, v.to_string()); - match seen.get(&key).copied() { - None => { - seen.insert(key, i); - } - Some(k) => { - let keeper_protected = cands.get(k).is_some_and(|x| x.protected); - let victim = match (keeper_protected, c.protected) { - (_, false) => i, - (false, true) => { - seen.insert(key, i); - k - } - (true, true) => continue, - }; - if let Some(g) = gone.get_mut(victim) { - *g = true; - rep.duplicates += 1; - } - } + if let Some(g) = gone.get_mut(i) { + *g = true; + rep.duplicates += 1; } } } @@ -421,8 +454,8 @@ fn collinear(members: &[&LineRec], cands: &[Cand], o: &Opts, gone: &mut [bool], fn arcs(cands: &[Cand], o: &Opts, gone: &mut [bool], changed: &mut HashMap, rep: &mut Report) { let q = o.q(); let g = q.max(1e-9); - let cell = |x: f64| (x / g).round() as i64; - let mut buckets: HashMap<(u32, i64, i64, i64, i64), Vec> = HashMap::new(); + // (index, properties, centre and radius); cells of `g` hold them. + let mut recs: Vec<(usize, u32, [f64; 4])> = Vec::new(); for (i, c) in cands.iter().enumerate() { if gone.get(i).copied().unwrap_or(true) || c.protected { continue; @@ -442,12 +475,45 @@ fn arcs(cands: &[Cand], o: &Opts, gone: &mut [bool], changed: &mut HashMap = buckets.keys().copied().collect(); - keys.sort_unstable(); - for key in keys { - let Some(group) = buckets.get(&key) else { continue }; + // Those within `g` of each other in centre and radius are on one circle. Each object joins the + // first group whose every member is within `g` of it, or starts one: matches don't chain, so + // nothing is deleted for matching only an object that itself matches the keeper. Members are + // looked for in the neighbouring cells too, so values on either side of a cell boundary meet. + let mut grid: HashMap<(u32, [i64; 4]), Vec> = HashMap::new(); + let mut group_of: Vec = Vec::with_capacity(recs.len()); + // Each group's records, in draw order; groups in the order of their first object. + let mut members: Vec> = Vec::new(); + for (ri, (_, prop, v)) in recs.iter().enumerate() { + let cells = v.map(|x| cell_of(x, g)); + let mut near_groups: Vec = Vec::new(); + for n in 0..81_i64 { + let near = [n % 3 - 1, n / 3 % 3 - 1, n / 9 % 3 - 1, n / 27 % 3 - 1]; + let mut key = cells; + for (k, d) in key.iter_mut().zip(near) { + *k = k.saturating_add(d); + } + near_groups.extend(grid.get(&(*prop, key)).map(Vec::as_slice).unwrap_or_default().iter().filter_map(|rj| group_of.get(*rj))); + } + near_groups.sort_unstable(); + near_groups.dedup(); + let fits = |gi: &usize| members.get(*gi).is_some_and(|m| m.iter().all(|rk| recs.get(*rk).is_some_and(|(_, _, w)| within(v, w, g)))); + let gi = match near_groups.into_iter().find(fits) { + Some(gi) => gi, + None => { + members.push(Vec::new()); + members.len() - 1 + } + }; + if let Some(m) = members.get_mut(gi) { + m.push(ri); + } + group_of.push(gi); + grid.entry((*prop, cells)).or_default().push(ri); + } + let groups = members.iter().map(|m| m.iter().filter_map(|ri| recs.get(*ri).map(|r| r.0)).collect::>()); + for group in groups { if group.len() < 2 { continue; } @@ -465,7 +531,7 @@ fn arcs(cands: &[Cand], o: &Opts, gone: &mut [bool], changed: &mut HashMap Prompt { match self.table { None => Prompt::new("Select a table", Accept::SELECT), - Some(_) => Prompt::new("Enter maximum part height or", Accept::POINT_OR_NUMBER).kw(&["Off"]), + Some(_) => Prompt::new("Enter maximum part height", Accept::POINT_OR_NUMBER).kw(&["Off"]), } } fn input(&mut self, s: &mut Session, i: Input) -> Result { diff --git a/crates/engine/src/lib.rs b/crates/engine/src/lib.rs index 8f84b35d7..d1fa2b03d 100644 --- a/crates/engine/src/lib.rs +++ b/crates/engine/src/lib.rs @@ -92,6 +92,12 @@ pub struct Session { pub last_command: Option, /// LASTPOINT. pub last_point: Vec2, + /// AREA and PERIMETER: the last area AREA or MEASUREGEOM measured (in their Add and Subtract + /// modes the running total) and that area's perimeter. Not saved, as in AutoCAD. + pub area: f64, + pub perimeter: f64, + /// DISTANCE: the last distance DIST or MEASUREGEOM measured (with Multiple points, the total). + pub distance: f64, /// The last segment given at a point prompt (its base point and the point): polar angles /// relative to the last segment (POLARMODE bit 1) are measured from it. pub last_segment: Option<(Vec2, Vec2)>, @@ -173,6 +179,9 @@ impl Session { log: Vec::new(), last_command: None, last_point: Vec2::ZERO, + area: 0.0, + perimeter: 0.0, + distance: 0.0, last_segment: None, last_polar: None, point_mods: Vec::new(), diff --git a/crates/engine/src/prompt.rs b/crates/engine/src/prompt.rs index 1563be702..e3498dcf0 100644 --- a/crates/engine/src/prompt.rs +++ b/crates/engine/src/prompt.rs @@ -26,6 +26,41 @@ impl Accept { pub const SELECT: Accept = Accept { point: true, number: false, text: false, select: true, enter: true }; } +/// Prompts that ask for one of their keywords, which AutoCAD 2024 writes without "or" before them: +/// "Enter an option [?/Make/Set/…]:", "Enter layout option [Copy/Delete/…/?] :", "New color +/// [Truecolor/COlorbook] :". A prompt asking for something else besides its keywords has +/// it: "Enter block name or [?]:", "Specify insertion base point or [Basepoint/…]:". Read from +/// AutoCAD's command line over measured runs, where no prompt was written both ways. +const NO_OR: [&str; 27] = [ + "Bring to front", + "Calculate rectangle dimensions based on", + "Choose mode for selected object conversion", + "Create annotative block", + "Enter a configuration option", + "Enter a plotting preference", + "Enter an annotation option", + "Enter an option", + "Enter an option to change", + "Enter attribute visibility setting", + "Enter justification", + "Enter layout option", + "Enter leader format option", + "Enter line spacing type", + "Enter object ordering option", + "Enter polyline linetype generation option", + "Enter property to change", + "Enter the type of array", + "Enter type of unused objects to purge", + "Enter viewport arrangement", + "Explode block", + "New color", + "Orient relative to sheet in paper space viewports", + "Select a content type", + "Select a leader type", + "Use landing", + "Viewport View Locking", +]; + /// A prompt shown on the command line. #[derive(Clone, Debug, Default, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] @@ -148,15 +183,7 @@ impl Prompt { } let mut s = self.message.clone(); if !self.keywords.is_empty() { - // A question offers its answers ("Fix any errors detected? [Yes/No]"); anything else - // offers options besides what it asks for ("Specify next point or [Undo]"). - s.push_str(if self.message.is_empty() { - "[" - } else if self.message.ends_with('?') { - " [" - } else { - " or [" - }); + s.push_str(self.keyword_lead()); s.push_str(&self.keywords.join("/")); s.push(']'); } @@ -166,6 +193,20 @@ impl Prompt { s.push(':'); s } + /// What goes between the message and its keywords. A question offers its answers ("Fix any + /// errors detected? [Yes/No]"), and so does a prompt for an option ([`NO_OR`]): " [". Anything + /// else offers options besides what it asks for ("Specify next point or [Undo]"): " or [". With + /// no message, "[". The command line in the window draws the keywords itself and takes this + /// too. + pub fn keyword_lead(&self) -> &'static str { + if self.message.is_empty() { + "[" + } else if self.message.ends_with('?') || NO_OR.contains(&self.message.as_str()) { + " [" + } else { + " or [" + } + } /// Match typed text against keywords: full word or the capitalised shortcut, case-insensitive. pub fn match_keyword(&self, text: &str) -> Option { let t = text.trim(); @@ -338,6 +379,13 @@ mod tests { assert_eq!(p.display(), "Specify next point or [Undo/Close]:"); let q = Prompt::new("Erase polyline?", Accept::TEXT).kw(&["Yes", "No"]).default("No"); assert_eq!(q.display(), "Erase polyline? [Yes/No] :"); + // A prompt for an option has no "or", as AutoCAD writes it. + let o = Prompt::new("Enter an option", Accept::TEXT).kw(&["Close", "Join"]); + assert_eq!(o.display(), "Enter an option [Close/Join]:"); + let c = Prompt::new("New color", Accept::TEXT).kw(&["Truecolor", "COlorbook"]).default("BYLAYER"); + assert_eq!(c.display(), "New color [Truecolor/COlorbook] :"); + let b = Prompt::new("Enter block name", Accept::TEXT).kw(&["?"]); + assert_eq!(b.display(), "Enter block name or [?]:"); assert_eq!(p.match_keyword("u").as_deref(), Some("Undo")); assert_eq!(p.match_keyword("CL").as_deref(), Some("Close")); assert_eq!(p.match_keyword("x"), None); diff --git a/crates/engine/src/sysvars.rs b/crates/engine/src/sysvars.rs index 3fe47c052..fcecbd2cf 100644 --- a/crates/engine/src/sysvars.rs +++ b/crates/engine/src/sysvars.rs @@ -67,6 +67,9 @@ const SESSION_VARS: &[&str] = &[ "ZOOMFACTOR", "MEASUREINIT", "LASTPOINT", + "AREA", + "PERIMETER", + "DISTANCE", "FONTALT", "FONTFALLBACK", "SAVETIME", @@ -145,6 +148,9 @@ pub fn get(s: &Session, name: &str) -> Option { "ZOOMFACTOR" => json!(st.zoomfactor), "MEASUREINIT" => json!(i32::from(st.measureinit)), "LASTPOINT" => json!([s.last_point.x, s.last_point.y, 0.0]), + "AREA" => json!(s.area), + "PERIMETER" => json!(s.perimeter), + "DISTANCE" => json!(s.distance), // Held in radians (`$ANGBASE` in DXF is in degrees); reported in degrees, like POLARANG. "ANGBASE" => json!(s.doc().ok()?.header.f64("ANGBASE", 0.0).to_degrees()), "CONSTRAINTINFER" => json!(i32::from(s.doc().ok()?.parametric.settings.infer)), @@ -249,6 +255,9 @@ const READ_ONLY: &[&str] = &[ "BLOCKEDITOR", "CTAB", "LASTPOINT", + "AREA", + "PERIMETER", + "DISTANCE", "VIEWCTR", "VIEWSIZE", "EXTMIN", @@ -464,11 +473,6 @@ pub fn set(s: &mut Session, name: &str, v: &Value) -> Result<()> { pub fn list(s: &Session) -> Value { let mut m = serde_json::Map::new(); - for n in SESSION_VARS { - if let Some(v) = get(s, n) { - m.insert((*n).to_string(), v); - } - } if let Ok(d) = s.doc() { for (k, v) in &d.header.vars { if matches!(k.as_str(), "ANGBASE" | "SNAPUNIT" | "GRIDUNIT" | "CECOLOR") { @@ -478,6 +482,13 @@ pub fn list(s: &Session) -> Value { } } } + // The session's values last: a drawing's header can carry the same names (ORTHOMODE, + // LWDISPLAY, an AREA), and `get` reads the session's. + for n in SESSION_VARS { + if let Some(v) = get(s, n) { + m.insert((*n).to_string(), v); + } + } table::list(s, &mut m); Value::Object(m) } diff --git a/crates/engine/tests/it/assoc_array.rs b/crates/engine/tests/it/assoc_array.rs index 131210fa1..f672176b3 100644 --- a/crates/engine/tests/it/assoc_array.rs +++ b/crates/engine/tests/it/assoc_array.rs @@ -336,7 +336,7 @@ fn typed_arrayedit() { let a = rect_array(&mut s); typed(&mut s, &["arrayedit", "l"]); let p = s.prompt_text(); - assert!(p.contains("Enter an option or [Source/REPlace/Base point/Rows/Columns/Levels/RESet/eXit] "), "{p}"); + assert!(p.contains("Enter an option [Source/REPlace/Base point/Rows/Columns/Levels/RESet/eXit] "), "{p}"); typed(&mut s, &["c", "4", "t", "9", "r", "2", "5", ""]); assert!(s.prompt_text().contains("Enter an option"), "{}", s.prompt_text()); assert_eq!(centres(&s, &a).len(), 8); diff --git a/crates/engine/tests/it/inquiry_variables.rs b/crates/engine/tests/it/inquiry_variables.rs new file mode 100644 index 000000000..f42749458 --- /dev/null +++ b/crates/engine/tests/it/inquiry_variables.rs @@ -0,0 +1,271 @@ +//! AREA, PERIMETER and DISTANCE as AutoCAD 2024 leaves them after AREA, DIST and MEASUREGEOM +//! (measured with accoreconsole, running these scripts on these drawings): AREA is the area just +//! measured, or the running total in Add and Subtract mode, PERIMETER the perimeter of the last +//! area; DISTANCE the distance measured, or the total of DIST's Multiple points. After DIST's two +//! points LASTPOINT is still the first; after Multiple points it is the last. + +use cadcraft_engine::doc::{Common, EntityKind, Handle}; +use cadcraft_engine::geom::{Spline, Vec2}; +use cadcraft_engine::{Input, Session, sysvars}; +use serde_json::{Value, json}; + +fn var(s: &Session, name: &str) -> f64 { + sysvars::get(s, name).and_then(|v| v.as_f64()).unwrap_or_else(|| panic!("{name} not a number")) +} + +fn lastpoint(s: &Session) -> (f64, f64) { + let v = sysvars::get(s, "LASTPOINT").unwrap(); + (v[0].as_f64().unwrap(), v[1].as_f64().unwrap()) +} + +fn close(got: f64, want: f64) -> bool { + (got - want).abs() <= 1e-9 * (1.0 + want.abs()) +} + +fn handle(v: &Value) -> Handle { + Handle::parse_hex(v.get("handle").unwrap_or(&v["handles"][0]).as_str().unwrap()).unwrap() +} + +fn lisp(s: &mut Session, expr: &str) { + s.cmdline(expr).unwrap(); + assert!(s.running.is_none(), "{expr}: {}", s.prompt_text()); +} + +/// The closed polyline with an arc and the circle the Add-mode scripts pick. +fn p_and_c(s: &mut Session) -> (Handle, Handle) { + let p = handle(&s.execute("pline", &json!({ "vertices": [[0, 0], { "p": [40, 0], "bulge": 0.5 }, [40, 30], [0, 30]], "closed": true })).unwrap()); + let c = handle(&s.execute("circle", &json!({ "center": [150, 15], "radius": 10 })).unwrap()); + (p, c) +} + +#[test] +fn area_of_points_sets_area_and_perimeter() { + let mut s = Session::new(); + lisp(&mut s, "(command \"_.AREA\" '(0.0 0.0) '(40.0 0.0) '(40.0 30.0) '(0.0 30.0) \"\")"); + assert!(close(var(&s, "AREA"), 1200.0) && close(var(&s, "PERIMETER"), 140.0)); +} + +#[test] +fn add_mode_totals_the_area_and_keeps_the_last_perimeter() { + // Points, then the circle as an object. + let mut s = Session::new(); + let (_, c) = p_and_c(&mut s); + lisp( + &mut s, + &format!( + "(command \"_.AREA\" \"_A\" '(0.0 0.0) '(40.0 0.0) '(40.0 30.0) '(0.0 30.0) \"\" \"_O\" (list (handent \"{}\") '(160.0 15.0)) \"\" \"\")", + c.hex() + ), + ); + assert!(close(var(&s, "AREA"), 1514.159265358979), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 62.83185307179586), "{}", var(&s, "PERIMETER")); + // Both as objects. + let mut s = Session::new(); + let (p, c) = p_and_c(&mut s); + lisp( + &mut s, + &format!( + "(command \"_.AREA\" \"_A\" \"_O\" (list (handent \"{}\") '(0.0 15.0)) (list (handent \"{}\") '(160.0 15.0)) \"\" \"\")", + p.hex(), + c.hex() + ), + ); + assert!(close(var(&s, "AREA"), 1671.411490437671), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 62.83185307179586), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn subtract_mode_takes_the_area_off_the_total() { + // At large coordinates: the polyline added, the circle subtracted. + let mut s = Session::new(); + let p = handle( + &s.execute( + "pline", + &json!({ "vertices": [[-35000, 81000], { "p": [-33000, 81000], "bulge": 0.5 }, [-33000, 82500], [-35000, 82500]], "closed": true }), + ) + .unwrap(), + ); + let c = handle(&s.execute("circle", &json!({ "center": [-27000, 81750], "radius": 500 })).unwrap()); + lisp( + &mut s, + &format!( + "(command \"_.AREA\" \"_A\" \"_O\" (list (handent \"{}\") '(-35000.0 81750.0)) \"\" \"_S\" \"_O\" (list (handent \"{}\") '(-27000.0 81750.0)) \"\" \"\")", + p.hex(), + c.hex() + ), + ); + assert!(close(var(&s, "AREA"), 2607732.399299283), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 3141.592653589793), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn area_of_an_open_spline_closes_it_by_its_chord() { + let control = [(0.8, 0.25), (0.82, 0.24), (0.84, 0.25), (0.84, 0.28), (0.82, 0.29), (0.8, 0.28), (0.8, 0.25)]; + let spline = Spline { + degree: 3, + knots: vec![0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 4.0, 4.0], + control: control.iter().map(|&(x, y)| Vec2::new(x, y)).collect(), + weights: Vec::new(), + fit: Vec::new(), + closed: false, + fit_opts: Default::default(), + }; + let mut s = Session::new(); + let space = s.space(); + let h = s.doc_mut().unwrap().add(&space, Common::default(), EntityKind::Spline(spline)).unwrap(); + lisp(&mut s, &format!("(command \"_.AREA\" \"_O\" (list (handent \"{}\") '(0.8 0.265)))", h.hex())); + assert!(close(var(&s, "AREA"), 0.001308333333333334), "{}", var(&s, "AREA")); + // The spline's length, 0.13046952991870 by an independent integration. AutoCAD reported + // 0.1304733129441191, 2.9e-5 longer than that: its own approximation of the length. + assert!(close(var(&s, "PERIMETER"), 0.1304695299187), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn area_of_a_spline_counts_its_narrow_knot_spans() { + // A degree-1 spline is its control polygon, here the triangle (0,0) (1,0) (0,1): area 0.5, + // perimeter 2 + sqrt(2), though two of its three knot spans are a billionth of the domain. + let control = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (0.0, 0.0)]; + let spline = Spline { + degree: 1, + knots: vec![0.0, 0.0, 1e-9, 2e-9, 1.0, 1.0], + control: control.iter().map(|&(x, y)| Vec2::new(x, y)).collect(), + ..Spline::default() + }; + let mut s = Session::new(); + let space = s.space(); + let h = s.doc_mut().unwrap().add(&space, Common::default(), EntityKind::Spline(spline)).unwrap(); + lisp(&mut s, &format!("(command \"_.AREA\" \"_O\" (list (handent \"{}\") '(0.5 0.0)))", h.hex())); + assert!(close(var(&s, "AREA"), 0.5), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 2.0 + 2f64.sqrt()), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn area_of_a_spline_with_more_spans_than_samples_counts_each() { + // The square (0,0) (100,0) (100,100) (0,100) as a degree-1 spline: 5000 spans along the bottom, + // then two a millionth wide up the right side and across the top. Area 10000, perimeter (the + // open spline's length) 300. + let mut control: Vec = (0..=5000).map(|i| Vec2::new(i as f64 / 50.0, 0.0)).collect(); + control.extend([Vec2::new(100.0, 100.0), Vec2::new(0.0, 100.0)]); + let mut knots: Vec = (0..=5000).map(f64::from).collect(); + knots.insert(0, 0.0); + knots.extend([5000.0 + 1e-6, 5000.0 + 2e-6, 5000.0 + 2e-6]); + let spline = Spline { degree: 1, knots, control, ..Spline::default() }; + let mut s = Session::new(); + let space = s.space(); + let h = s.doc_mut().unwrap().add(&space, Common::default(), EntityKind::Spline(spline)).unwrap(); + lisp(&mut s, &format!("(command \"_.AREA\" \"_O\" (list (handent \"{}\") '(50.0 0.0)))", h.hex())); + assert!(close(var(&s, "AREA"), 1e4), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 300.0), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn a_spline_too_long_to_measure_is_refused_and_not_kept() { + let mut s = Session::new(); + lisp(&mut s, "(command \"_.AREA\" '(0.0 0.0) '(10.0 0.0) '(10.0 10.0) \"\")"); + // Finite ends 2e308 apart: its chord closes no area, but its length is past f64's range. That is + // too large to report, as a polyline's is, not a perimeter of 0. + let spline = Spline::from_line(Vec2::new(-1e308, 0.0), Vec2::new(1e308, 0.0), 1); + let space = s.space(); + let h = s.doc_mut().unwrap().add(&space, Common::default(), EntityKind::Spline(spline)).unwrap(); + let err = s.execute("area", &json!({ "handle": h.hex() })).unwrap_err(); + assert!(err.to_string().contains("the perimeter is too large"), "{err}"); + lisp(&mut s, &format!("(command \"_.AREA\" \"_O\" (list (handent \"{}\") '(0.0 0.0)))", h.hex())); + assert!(s.log.iter().any(|l| l.contains("The perimeter is too large.")), "{:?}", s.log); + assert!(close(var(&s, "AREA"), 50.0), "{}", var(&s, "AREA")); + assert!(close(var(&s, "PERIMETER"), 20.0 + 200f64.sqrt()), "{}", var(&s, "PERIMETER")); +} + +#[test] +fn dist_sets_the_distance_and_leaves_lastpoint_at_the_first_point() { + let mut s = Session::new(); + lisp(&mut s, "(command \"_.DIST\" '(0.5 0.25) '(0.53 0.29))"); + assert!(close(var(&s, "DISTANCE"), 0.05), "{}", var(&s, "DISTANCE")); + let (x, y) = lastpoint(&s); + assert!(close(x, 0.5) && close(y, 0.25), "{x}, {y}"); +} + +#[test] +fn dist_with_multiple_points_sets_the_total_and_lastpoint_at_the_last() { + let mut s = Session::new(); + lisp(&mut s, "(command \"_.DIST\" '(0.0 0.0) \"_M\" '(40.0 0.0) '(40.0 30.0) '(0.0 30.0) \"\")"); + assert!(close(var(&s, "DISTANCE"), 110.0), "{}", var(&s, "DISTANCE")); + let (x, y) = lastpoint(&s); + assert!(close(x, 0.0) && close(y, 30.0), "{x}, {y}"); +} + +#[test] +fn measuregeom_sets_them_as_dist_and_area_do() { + let mut s = Session::new(); + // (AutoCAD's MEASUREGEOM asks for the next option after each measurement until eXit; here it + // ends after one.) + lisp(&mut s, "(command \"_.MEASUREGEOM\" \"_D\" '(0.0 0.0) '(30.0 40.0))"); + assert!(close(var(&s, "DISTANCE"), 50.0), "{}", var(&s, "DISTANCE")); + lisp(&mut s, "(command \"_.MEASUREGEOM\" \"_AR\" '(0.5 0.25) '(0.54 0.25) '(0.54 0.28) '(0.5 0.28) \"\")"); + assert!(close(var(&s, "AREA"), 0.0012) && close(var(&s, "PERIMETER"), 0.14), "{} {}", var(&s, "AREA"), var(&s, "PERIMETER")); +} + +#[test] +fn the_json_forms_set_them_too_and_they_are_read_only() { + let mut s = Session::new(); + s.execute("area", &json!({ "points": [[0, 0], [40, 0], [40, 30], [0, 30]] })).unwrap(); + s.execute("dist", &json!({ "p1": [0, 0], "p2": [30, 40] })).unwrap(); + assert_eq!((var(&s, "AREA"), var(&s, "PERIMETER"), var(&s, "DISTANCE")), (1200.0, 140.0, 50.0)); + for name in ["AREA", "PERIMETER", "DISTANCE"] { + assert!(s.execute("setvar", &json!({ "name": name, "value": 1 })).is_err(), "{name}"); + } +} + +#[test] +fn lastpoint_after_multiple_points_is_the_last_point_entered() { + // A length typed with Length extends the path, but LASTPOINT stays at the last point picked; + // after Undo it stays at the point undone (AutoCAD 2024 leaves LASTPOINT at 10,0 and 10,10). + let mut s = Session::new(); + lisp(&mut s, "(command \"_.DIST\" '(0.0 0.0) \"_M\" '(10.0 0.0) \"_L\" 5.0 \"\")"); + assert!(close(var(&s, "DISTANCE"), 15.0), "{}", var(&s, "DISTANCE")); + let (x, y) = lastpoint(&s); + assert!(close(x, 10.0) && close(y, 0.0), "{x}, {y}"); + let mut s = Session::new(); + lisp(&mut s, "(command \"_.DIST\" '(0.0 0.0) \"_M\" '(10.0 0.0) '(10.0 10.0) \"_U\" \"_T\")"); + assert!(close(var(&s, "DISTANCE"), 10.0), "{}", var(&s, "DISTANCE")); + let (x, y) = lastpoint(&s); + assert!(close(x, 10.0) && close(y, 10.0), "{x}, {y}"); +} + +#[test] +fn a_distance_too_large_to_measure_is_refused_and_not_kept() { + let mut s = Session::new(); + lisp(&mut s, "(command \"_.DIST\" '(0.5 0.25) '(0.53 0.29))"); + assert!(close(var(&s, "DISTANCE"), 0.05)); + // Finite points whose distance overflows: the JSON form, two picked points, Multiple points. + assert!(s.execute("dist", &json!({ "p1": [-1e308, 0], "p2": [1e308, 0] })).is_err()); + s.cmdline("dist").unwrap(); + s.input(Input::Point(Vec2::new(-1e308, 0.0))).unwrap(); + s.input(Input::Point(Vec2::new(1e308, 0.0))).unwrap(); + assert!(s.log.last().is_some_and(|l| l.contains("the distance is too large")), "{:?}", s.log.last()); + // LASTPOINT stays at the first point, as after a measurement. + assert_eq!(lastpoint(&s), (-1e308, 0.0)); + s.cancel(); + s.cmdline("dist").unwrap(); + s.input(Input::Point(Vec2::new(-1e308, 0.0))).unwrap(); + s.cmdline("m").unwrap(); + s.input(Input::Point(Vec2::new(1e308, 0.0))).unwrap(); + s.input(Input::Enter).unwrap(); + assert!(s.log.last().is_some_and(|l| l.contains("the distance is too large")), "{:?}", s.log.last()); + s.cancel(); + assert!(close(var(&s, "DISTANCE"), 0.05), "{}", var(&s, "DISTANCE")); +} + +#[test] +fn the_variable_list_shows_the_sessions_values() { + // A drawing's header can carry these names; GETVAR reads the session's, and so does the list. + let mut s = Session::new(); + s.doc_mut().unwrap().header.set_f64("AREA", 99.0); + // Every DXF header carries ORTHOMODE; the session's ortho is off. + s.doc_mut().unwrap().header.set_i64("ORTHOMODE", 1); + lisp(&mut s, "(command \"_.AREA\" '(0.0 0.0) '(10.0 0.0) '(10.0 10.0) \"\")"); + let list = s.execute("sysvars", &json!({})).unwrap(); + assert!(close(var(&s, "AREA"), 50.0)); + assert_eq!(list["AREA"].as_f64(), Some(var(&s, "AREA")), "{}", list["AREA"]); + assert_eq!(list["ORTHOMODE"], sysvars::get(&s, "ORTHOMODE").unwrap()); + assert_eq!(list["ORTHOMODE"], 0); +} diff --git a/crates/engine/tests/it/layout_prompts.rs b/crates/engine/tests/it/layout_prompts.rs index afa784e0b..8b6ea6637 100644 --- a/crates/engine/tests/it/layout_prompts.rs +++ b/crates/engine/tests/it/layout_prompts.rs @@ -17,7 +17,7 @@ fn typed_layout_options_prompt_for_names() { s.cmdline("LAYOUT").unwrap(); let p = s.current_prompt().expect("LAYOUT prompts").display(); - assert_eq!(p, "Enter layout option or [Copy/Delete/New/Template/Rename/SAveas/Set/?] :"); + assert_eq!(p, "Enter layout option [Copy/Delete/New/Template/Rename/SAveas/Set/?] :"); s.cmdline("n").unwrap(); assert_eq!(s.current_prompt().unwrap().display(), "Enter name of new layout :"); s.cmdline("Sheet9").unwrap(); diff --git a/crates/engine/tests/it/main.rs b/crates/engine/tests/it/main.rs index 54ea40675..38fb4d005 100644 --- a/crates/engine/tests/it/main.rs +++ b/crates/engine/tests/it/main.rs @@ -60,6 +60,7 @@ mod hatch_numeric_validation; mod hatch_options; mod helix; mod inquiry_keywords; +mod inquiry_variables; mod inquiry_z; mod insert_attribute_prompts; mod insert_prompts; @@ -107,6 +108,7 @@ mod point_modifiers; mod polyface_explode; mod post_command_passes; mod prompt_keywords; +mod prompt_or_once; mod props_bad_lineweight; mod props_insert_scale_attribs; mod purge_mlinestyles; diff --git a/crates/engine/tests/it/overkill.rs b/crates/engine/tests/it/overkill.rs index 56475ab47..19639458e 100644 --- a/crates/engine/tests/it/overkill.rs +++ b/crates/engine/tests/it/overkill.rs @@ -66,6 +66,48 @@ fn duplicates_tolerance_and_ignored_properties() { assert!(r["message"].as_str().unwrap().contains("duplicate(s) deleted")); } +#[test] +fn objects_within_the_tolerance_are_duplicates_on_either_side_of_a_rounding_step() { + // Each pair is closer than the tolerance, but its numbers round to different multiples of it + // (50.004 → 5000, 50.006 → 5001 at 0.01). + let pairs = [ + (json!({ "tolerance": 0.01 }), "circle", json!({ "center": [50.004, 50], "radius": 3 }), json!({ "center": [50.006, 50], "radius": 3 })), + (json!({ "tolerance": 0.01 }), "circle", json!({ "center": [50, 50], "radius": 3.004 }), json!({ "center": [50, 50], "radius": 3.006 })), + (json!({}), "circle", json!({ "center": [0.0000014, 0], "radius": 3 }), json!({ "center": [0.0000016, 0], "radius": 3 })), + (json!({ "tolerance": 0.01 }), "point", json!({ "at": [10.004, 0] }), json!({ "at": [10.006, 0] })), + ( + json!({ "tolerance": 0.01 }), + "text", + json!({ "at": [0.004, 0], "text": "A", "height": 2.5 }), + json!({ "at": [0.006, 0], "text": "A", "height": 2.5 }), + ), + ]; + for (opts, cmd, a, b) in pairs { + let mut s = Session::new(); + s.execute(cmd, &a).unwrap(); + s.execute(cmd, &b).unwrap(); + let r = ok(&mut s, opts); + assert_eq!(r["deleted"], 1, "{cmd} {a} {b}: {r}"); + assert_eq!(count(&s), 1, "{cmd} {a} {b}"); + } + // Arcs on (about) one circle are combined the same way. + let mut s = Session::new(); + s.execute("arc", &json!({ "center": [0.004, 0], "radius": 5, "start": 0, "end": 90 })).unwrap(); + s.execute("arc", &json!({ "center": [0.006, 0], "radius": 5, "start": 45, "end": 180 })).unwrap(); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!(r["overlapping"], 1, "{r}"); + assert_eq!(count(&s), 1); + // Farther apart than the tolerance, they stay. + let mut s = Session::new(); + s.execute("circle", &json!({ "center": [50.004, 50], "radius": 3 })).unwrap(); + s.execute("circle", &json!({ "center": [50.016, 50], "radius": 3 })).unwrap(); + s.execute("point", &json!({ "at": [10.004, 0] })).unwrap(); + s.execute("point", &json!({ "at": [10.016, 0] })).unwrap(); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!(r["deleted"], 0, "{r}"); + assert_eq!(count(&s), 4); +} + #[test] fn collinear_lines_overlap_and_end_to_end() { let mut s = Session::new(); @@ -230,3 +272,47 @@ fn many_objects_stay_fast() { assert_eq!(count(&s), 4001); assert!(t.elapsed().as_secs() < 20, "{:?}", t.elapsed()); } + +#[test] +fn within_the_tolerance_does_not_chain() { + // At 0.01, the arc is within the tolerance of both circles, but the circles are 0.016 apart: + // the arc goes, both circles stay, whichever comes first in draw order. + let circle = |s: &mut Session, x: f64| s.execute("circle", &json!({ "center": [x, 0], "radius": 3 })).unwrap(); + let arc_at = |s: &mut Session, x: f64, start: f64, end: f64| { + s.execute("arc", &json!({ "center": [x, 0], "radius": 3, "start": start, "end": end })).unwrap() + }; + let kinds = |s: &Session| s.doc().unwrap().model.iter().map(|e| e.kind.type_name()).collect::>(); + let mut s = Session::new(); + circle(&mut s, 50.0); + arc_at(&mut s, 50.008, 0.0, 90.0); + circle(&mut s, 50.016); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!((r["duplicates"].as_u64(), r["overlapping"].as_u64()), (Some(0), Some(1)), "{r}"); + assert_eq!(kinds(&s), ["Circle", "Circle"]); + let mut s = Session::new(); + arc_at(&mut s, 50.008, 0.0, 90.0); + circle(&mut s, 50.0); + circle(&mut s, 50.016); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!(r["deleted"], 1, "{r}"); + assert_eq!(kinds(&s), ["Circle", "Circle"]); + // Arcs alone: the third is 0.016 from the first, so it is not combined with it. + let mut s = Session::new(); + arc_at(&mut s, 0.0, 0.0, 90.0); + arc_at(&mut s, 0.008, 45.0, 180.0); + arc_at(&mut s, 0.016, 100.0, 200.0); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!(r["overlapping"], 1, "{r}"); + assert_eq!(kinds(&s), ["Arc", "Arc"]); + // A followed line displaces the first one, which a third line matched: the third is 0.016 from + // the followed line, so it stays. + let mut s = Session::new(); + let first = line(&mut s, [0.0, 0.0], [10.0, 0.0]); + let third = line(&mut s, [0.0, 0.008], [10.0, 0.008]); + let followed = line(&mut s, [0.0, -0.008], [10.0, -0.008]); + s.execute("dimlinear", &json!({ "object": followed.hex(), "at": [5, 5] })).unwrap(); + let r = ok(&mut s, json!({ "tolerance": 0.01 })); + assert_eq!(r["deleted"], 1, "{r}"); + let d = s.doc().unwrap(); + assert!(d.entity(first).is_none() && d.entity(third).is_some() && d.entity(followed).is_some()); +} diff --git a/crates/engine/tests/it/prompt_or_once.rs b/crates/engine/tests/it/prompt_or_once.rs new file mode 100644 index 000000000..c84c58b1c --- /dev/null +++ b/crates/engine/tests/it/prompt_or_once.rs @@ -0,0 +1,77 @@ +//! Prompts that offer options say "or" once, as AutoCAD 2024's do: "Enter angle of xline (0) or +//! [Reference]:". The prompt adds "or" before its options, so a message that ended in "or" read +//! "or or". + +use cadcraft_engine::Session; +use serde_json::json; + +fn shows(s: &Session, text: &str) { + let p = s.prompt_text(); + assert!(p.ends_with(text), "{p}"); + assert!(!p.contains(" or or "), "{p}"); +} + +#[test] +fn xline_angle_and_offset() { + let mut s = Session::new(); + s.cmdline("xline").unwrap(); + s.cmdline("a").unwrap(); + shows(&s, "Enter angle of xline (0) or [Reference]:"); + s.cancel(); + s.cmdline("xline").unwrap(); + s.cmdline("o").unwrap(); + shows(&s, "Specify offset distance or [Through] <1.0000>:"); +} + +#[test] +fn helix_radii_and_height() { + let mut s = Session::new(); + s.script("helix\n0,0\n").unwrap(); + shows(&s, "Specify base radius or [Diameter] <1.0000>:"); + s.cmdline("5").unwrap(); + shows(&s, "Specify top radius or [Diameter] <5.0000>:"); + s.cmdline("").unwrap(); + shows(&s, "Specify helix height or [Axis endpoint/Turns/turn Height/tWist] <1.0000>:"); +} + +#[test] +fn blend_first_object() { + let mut s = Session::new(); + s.cmdline("blend").unwrap(); + shows(&s, "Select first object or [CONtinuity]:"); +} + +#[test] +fn lengthen_options() { + let mut s = Session::new(); + s.cmdline("lengthen").unwrap(); + shows(&s, "Select an object to measure or [DElta/Percent/Total/DYnamic] :"); + s.cmdline("de").unwrap(); + shows(&s, "Enter delta length or [Angle] <0.0000>:"); + s.cmdline("2").unwrap(); + shows(&s, "Select an object to change or [Undo]:"); + s.cancel(); + s.cmdline("lengthen").unwrap(); + s.cmdline("t").unwrap(); + shows(&s, "Specify total length or [Angle] <1.0000>:"); +} + +#[test] +fn ncopy_pedit_and_table_break() { + let mut s = Session::new(); + s.script("line 25,-5 25,5\n\nline 0,0 10,0\n\n-block B 0,0 L\n\n").unwrap(); + s.execute("insert", &json!({ "name": "B", "at": [20, 0] })).unwrap(); + s.cmdline("zoom e").unwrap(); + s.cmdline("ncopy").unwrap(); + shows(&s, "Select nested objects to copy or [Settings]:"); + s.script("22,0\n\n").unwrap(); + shows(&s, "Specify base point or [Displacement/Multiple] :"); + s.cancel(); + s.cmdline("pedit").unwrap(); + shows(&s, "Select polyline or [Multiple]:"); + s.cancel(); + s.execute("table", &json!({ "at": [0, 20], "cells": [["1", ""], ["2", ""]], "rowHeight": 1.0, "colWidth": 3.0 })).unwrap(); + s.cmdline("table.break").unwrap(); + s.cmdline("1,19.5").unwrap(); + shows(&s, "Enter maximum part height or [Off]:"); +} diff --git a/crates/engine/tests/it/vplayer_prompts.rs b/crates/engine/tests/it/vplayer_prompts.rs index f7f7e4a1a..393ad0958 100644 --- a/crates/engine/tests/it/vplayer_prompts.rs +++ b/crates/engine/tests/it/vplayer_prompts.rs @@ -33,9 +33,9 @@ fn typed_vplayer_changes_layers_in_chosen_viewports() { // Freeze in the current viewport (the default inside a viewport). s.cmdline("VPLAYER").unwrap(); - assert_eq!(s.current_prompt().unwrap().display(), "Enter an option or [?/Color/Freeze/Thaw/Reset/Newfrz/Vpvisdflt]:"); + assert_eq!(s.current_prompt().unwrap().display(), "Enter an option [?/Color/Freeze/Thaw/Reset/Newfrz/Vpvisdflt]:"); s.script("F\n0\n").unwrap(); - assert_eq!(s.current_prompt().unwrap().display(), "Enter an option or [All/Select/Current/Except current] :"); + assert_eq!(s.current_prompt().unwrap().display(), "Enter an option [All/Select/Current/Except current] :"); s.script("\n").unwrap(); assert_eq!(frozen(&s, &a), ["0"]); assert!(frozen(&s, &b).is_empty()); diff --git a/crates/geom/src/nurbs.rs b/crates/geom/src/nurbs.rs index 104ba8d3c..e07852340 100644 --- a/crates/geom/src/nurbs.rs +++ b/crates/geom/src/nurbs.rs @@ -131,6 +131,12 @@ impl Spline { /// [`Spline::is_valid`] already; integration calls this once per sample, and re-running the /// O(knots) validity scan each time would make measuring a valid spline quadratic (CWE-407). fn derivative_unchecked(&self, t: f64) -> Vec2 { + let d = self.velocity(t); + if d.is_finite() { d } else { Vec2::ZERO } + } + + /// [`Spline::derivative_unchecked`] before a value past f64's range is read as zero. + fn velocity(&self, t: f64) -> Vec2 { let p = self.degree; let Some(n) = self.control.len().checked_sub(1) else { return Vec2::ZERO }; let (lo, hi) = self.domain(); @@ -158,8 +164,7 @@ impl Spline { if w.abs() < 1e-300 { return Vec2::ZERO; } - let d = (da - a / w * dw) / w; - if d.is_finite() { d } else { Vec2::ZERO } + (da - a / w * dw) / w } /// Unit tangent at `t` in the direction of increasing parameter; a central difference stands @@ -477,22 +482,18 @@ impl Spline { out } - /// Arc length of one integration panel. The spline is validated once by the public callers - /// ([`Spline::length_between`]/[`Spline::length`]) before any panel is measured, so the speed - /// closure uses the unchecked derivative to avoid re-scanning the knots per sample. - fn panel_length(&self, a: f64, b: f64) -> f64 { - let speed = |t: f64| self.derivative_unchecked(t).len(); + /// Arc length of one integration panel, at the speed of `derivative`. The spline is validated + /// once by the callers ([`Spline::integrated_length`]/[`Spline::param_at_length`]) before any + /// panel is measured, so the derivative is an unchecked one, to avoid re-scanning the knots per + /// sample. + fn panel_length(&self, a: f64, b: f64, derivative: fn(&Spline, f64) -> Vec2) -> f64 { + let speed = |t: f64| derivative(self, t).len(); adaptive_gauss(a, b, gauss(a, b, speed), &speed, MAX_GAUSS_DEPTH) } /// Arc length between parameters `a` and `b` (adaptive Gauss–Legendre over each knot span). pub fn length_between(&self, a: f64, b: f64) -> f64 { - if !(self.is_valid() && a.is_finite() && b.is_finite()) { - return 0.0; - } - let (lo, hi) = self.domain(); - let (a, b) = (a.min(b).clamp(lo, hi), a.max(b).clamp(lo, hi)); - let l: f64 = self.length_intervals(a, b).into_iter().map(|(x, y)| self.panel_length(x, y)).sum(); + let l = self.integrated_length(a, b); if l.is_finite() { l } else { 0.0 } } @@ -502,6 +503,25 @@ impl Spline { self.length_between(lo, hi) } + /// Arc length of the whole spline, or `None` when it is past f64's range, where + /// [`Spline::length`] reads 0. An invalid spline's is 0. + pub fn checked_length(&self) -> Option { + let (lo, hi) = self.domain(); + let l = self.integrated_length(lo, hi); + l.is_finite().then_some(l) + } + + /// Arc length between `a` and `b`, infinite or NaN when it overflows (the length, or the speed + /// along the way); 0 for an invalid spline or a non-finite parameter. + fn integrated_length(&self, a: f64, b: f64) -> f64 { + if !(self.is_valid() && a.is_finite() && b.is_finite()) { + return 0.0; + } + let (lo, hi) = self.domain(); + let (a, b) = (a.min(b).clamp(lo, hi), a.max(b).clamp(lo, hi)); + self.length_intervals(a, b).into_iter().map(|(x, y)| self.panel_length(x, y, Spline::velocity)).sum() + } + /// The parameter `len` along the curve from parameter `from` (forward for positive `len`, /// backward for negative), clamped to the domain. pub fn param_at_length(&self, from: f64, len: f64) -> f64 { @@ -521,7 +541,7 @@ impl Spline { } let mut acc = 0.0; for (x0, x1) in ivs { - let l = self.panel_length(x0, x1); + let l = self.panel_length(x0, x1, Spline::derivative_unchecked); if acc + l >= target && l > 0.0 { // Bisect inside this interval, measuring from its near end. let rest = target - acc; @@ -529,7 +549,7 @@ impl Spline { let (mut s0, mut s1) = (near, far); for _ in 0..60 { let m = (s0 + s1) / 2.0; - let lm = self.panel_length(near.min(m), near.max(m)); + let lm = self.panel_length(near.min(m), near.max(m), Spline::derivative_unchecked); if lm < rest { s0 = m; } else { @@ -735,6 +755,24 @@ mod tests { assert_eq!(q.param_at_length(lo, 1e9), hi); } + #[test] + fn checked_length_tells_an_overflow_from_a_zero_length() { + let l = Spline::from_line(Vec2::ZERO, Vec2::new(3.0, 4.0), 3); + assert_eq!(l.checked_length(), Some(l.length())); + let dot = Spline::from_line(Vec2::new(1.0, 1.0), Vec2::new(1.0, 1.0), 1); + assert_eq!((dot.length(), dot.checked_length()), (0.0, Some(0.0))); + // Finite ends 2e308 apart: over a knot span of 4 the speed is in f64's range and the length + // past it; over a span of 1 the speed is past it too. `length` reads both as 0. + let ends = vec![Vec2::new(-1e308, 0.0), Vec2::new(1e308, 0.0)]; + for span in [4.0, 1.0] { + let huge = Spline { degree: 1, knots: vec![0.0, 0.0, span, span], control: ends.clone(), ..Spline::default() }; + assert_eq!((huge.length(), huge.checked_length()), (0.0, None), "{span}"); + } + let mut invalid = l.clone(); + invalid.knots.reverse(); + assert_eq!(invalid.checked_length(), Some(0.0)); + } + #[test] fn spline_arc_length_on_a_tight_bend() { // One Bezier span that turns sharply: four fixed Gauss panels come out 0.3% short, and diff --git a/crates/geom/src/spline.rs b/crates/geom/src/spline.rs index d954e66b1..1d5922d37 100644 --- a/crates/geom/src/spline.rs +++ b/crates/geom/src/spline.rs @@ -205,10 +205,69 @@ impl Spline { out } + /// Points along the curve for measuring it (AREA). Each knot span has a segment, so a narrow + /// span, which one grid over the whole domain can step over entirely, is measured too. The + /// count [`Spline::tessellate`] takes at `tol` is then shared out among the spans that bend + /// ([`Spline::span_bend`]), by the cube root of their bend: a span's chord error falls with + /// the square of its segments, so that share keeps the total error least. A straight span + /// keeps its one segment, which measures it exactly. The points number one per span plus + /// that count, past `MAX_SAMPLES` when the spans are that many, as [`Spline::length`] + /// integrates every span. An invalid spline gives its control points, as `tessellate` does. + pub fn tessellate_spans(&self, tol: f64) -> Vec { + if !self.is_valid() { + return self.control.clone(); + } + let (lo, hi) = self.domain(); + let n = self.sample_count(tol); + let spans: Vec<(f64, f64, f64)> = self.indexed_knot_spans().map(|(j, a, b)| (a, b, self.span_bend(j).cbrt())).collect(); + if spans.is_empty() { + return self.samples(n).collect(); + } + let total: f64 = spans.iter().map(|s| s.2).sum(); + let shared = total.is_finite() && total > 0.0; + let mut out = Vec::with_capacity(spans.len() + n + 1); + let (mut acc, mut used) = (0.0, 0); + for (a, b, share) in spans { + // Rounded on the running total, so the extra samples add up to `n` however thinly the + // shares are spread; the fraction first, at most 1, so a huge bend can't overflow. + acc += share; + let upto = if shared { (n as f64 * (acc / total).min(1.0)) as usize } else { 0 }; + let seg = 1 + upto.saturating_sub(used); + used = used.max(upto); + out.extend((0..seg).map(|i| self.eval_valid(a + (b - a) * i as f64 / seg as f64, lo, hi))); + } + out.push(self.eval_valid(hi, lo, hi)); + out + } + + /// How far knot span `j` (as [`Spline::indexed_knot_spans`] numbers it) can stray from its + /// chord, as an area: twice the largest triangle its first control point, the one farthest + /// from it and another make. That is between a quarter of the area of their convex hull and + /// twice it. With positive weights the span and its chord lie in that hull, so the area + /// between them is no more; it is zero when the points are collinear, and then the span is + /// straight. A weight that isn't positive lets the span leave the hull, so the square of the + /// points' polygon length counts instead. + fn span_bend(&self, j: usize) -> f64 { + let Some(pts) = self.control.get(j..=j + self.degree) else { return 0.0 }; + let Some(&a) = pts.first() else { return 0.0 }; + if !self.weights.get(j..=j + self.degree).is_none_or(|w| w.iter().all(|w| *w > 0.0)) { + let len: f64 = pts.windows(2).filter_map(|w| w.first().zip(w.get(1)).map(|(p, q)| p.dist(*q))).sum(); + return len * len; + } + let far = pts.iter().copied().max_by(|p, q| a.dist(*p).total_cmp(&a.dist(*q))).unwrap_or(a); + pts.iter().map(|p| (*p - a).cross(far - a).abs()).fold(0.0, f64::max) + } + /// The non-empty knot spans the curve is defined over, in parameter order. fn knot_spans(&self) -> impl Iterator + '_ { + self.indexed_knot_spans().map(|(_, a, b)| (a, b)) + } + + /// The non-empty knot spans with the index of the first of the `degree + 1` control points + /// that shape each. + fn indexed_knot_spans(&self) -> impl Iterator + '_ { let knots = self.knots.get(self.degree..=self.control.len()).unwrap_or(&[]); - knots.windows(2).filter_map(|w| w.first().zip(w.get(1)).map(|(a, b)| (*a, *b)).filter(|(a, b)| b > a)) + knots.windows(2).enumerate().filter_map(|(j, w)| w.first().zip(w.get(1)).map(|(a, b)| (j, *a, *b)).filter(|(_, a, b)| b > a)) } } diff --git a/crates/geom/src/spline/tests.rs b/crates/geom/src/spline/tests.rs index d953cfabd..820490d89 100644 --- a/crates/geom/src/spline/tests.rs +++ b/crates/geom/src/spline/tests.rs @@ -202,6 +202,83 @@ fn bounds_keep_their_cap_over_huge_knot_spans() { } } +#[test] +fn tessellate_spans_measures_narrow_knot_spans() { + // A degree-1 spline is its control polygon: the triangle (0,0) (1,0) (0,1), though two of its + // three spans are a billionth of the domain. One grid over the domain steps over them and + // sees no area; spread over the spans, the corners are there. + let control = vec![Vec2::ZERO, Vec2::new(1.0, 0.0), Vec2::new(0.0, 1.0), Vec2::ZERO]; + let s = Spline { degree: 1, knots: vec![0.0, 0.0, 1e-9, 2e-9, 1.0, 1.0], control, ..Spline::default() }; + assert!(s.is_valid()); + assert!(crate::shoelace(&s.tessellate(1e-3)).abs() < 1e-6); + let pts = s.tessellate_spans(1e-3); + assert!(pts.iter().any(|p| p.near(Vec2::new(1.0, 0.0), 1e-12)), "{pts:?}"); + assert!((crate::shoelace(&pts).abs() - 0.5).abs() < 1e-12); + // An ordinary spline measures as `tessellate` does, within the sampling's sag. + let w = wiggly(false); + let (a, b) = (crate::shoelace(&w.tessellate(1e-4)), crate::shoelace(&w.tessellate_spans(1e-4))); + assert!((a - b).abs() <= 1e-4 * a.abs().max(1.0), "{a} {b}"); +} + +/// The square (0,0) (100,0) (100,100) (0,100) as a degree-1 spline: `edge` spans of width 1 +/// along the bottom, then two spans a millionth wide up the right side and across the top. +fn square_with_narrow_spans(edge: usize) -> Spline { + let mut control: Vec = (0..=edge).map(|i| Vec2::new(100.0 * i as f64 / edge as f64, 0.0)).collect(); + control.extend([Vec2::new(100.0, 100.0), Vec2::new(0.0, 100.0)]); + let end = edge as f64; + let mut knots: Vec = (0..=edge).map(|i| i as f64).collect(); + knots.insert(0, 0.0); + knots.extend([end + 1e-6, end + 2e-6, end + 2e-6]); + Spline { degree: 1, knots, control, ..Spline::default() } +} + +#[test] +fn tessellate_spans_covers_every_span_however_many() { + // A degree-1 spline's spans are straight: one segment each, its control points, however many + // there are. The narrow spans are measured, not stepped over by a grid. + for edge in [3000, MAX_SAMPLES + 500] { + let s = square_with_narrow_spans(edge); + assert!(s.is_valid()); + let pts = s.tessellate_spans(1e-9); + assert_eq!(pts.len(), s.control.len()); + assert!(pts.iter().zip(&s.control).all(|(p, c)| p.near(*c, 1e-9))); + assert!((crate::shoelace(&pts).abs() - 1e4).abs() < 1e-6, "{}", crate::shoelace(&pts)); + } + let s = square_with_narrow_spans(MAX_SAMPLES + 500); + assert!(crate::shoelace(&s.samples(MAX_SAMPLES).collect::>()).abs() < 0.6e4); +} + +#[test] +fn tessellate_spans_samples_where_the_curve_bends() { + // A quadratic spline along the x-axis but for one control point 1000 above it: three spans + // bend, and the area under them is 1750/3 (a fine grid gives 583.3333334). Their chords alone + // would give 750. Below the sample cap and past it, the straight spans keep one segment each + // (their samples are the only ones on the axis but the curve's end) and the bent spans take + // all the rest. + for edge in [40, MAX_SAMPLES + 500] { + let mut control: Vec = (0..=edge).map(|i| Vec2::new(i as f64, 0.0)).collect(); + control.extend([Vec2::new(edge as f64 + 0.5, 1000.0), Vec2::new(edge as f64 + 1.0, 0.0), Vec2::new(edge as f64 + 2.0, 0.0)]); + let s = Spline::from_control(control, 2); + let pts = s.tessellate_spans(1e-9); + let area = crate::shoelace(&pts).abs(); + assert!((area - 1750.0 / 3.0).abs() < 1e-6 * area, "{edge}: {area}"); + assert_eq!(pts.iter().filter(|p| p.y == 0.0).count(), edge + 1, "{edge}"); + assert_eq!(pts.len(), s.control.len() - 2 + s.sample_count(1e-9) + 1, "{edge}"); + } +} + +#[test] +fn span_bend_bounds_the_area_off_the_chord() { + let mut s = Spline::from_control(vec![Vec2::ZERO, Vec2::new(1.0, 0.0), Vec2::new(3.0, 0.0), Vec2::new(4.0, 2.0)], 2); + // Collinear control points: a straight span. + assert_eq!(s.span_bend(0), 0.0); + // (1,0) (3,0) (4,2): twice their triangle's area. + assert!((s.span_bend(1) - 4.0).abs() < 1e-12, "{}", s.span_bend(1)); + // A weight that isn't positive: the polygon's length squared. + s.weights = vec![1.0, -0.5, 1.0, 1.0]; + assert!((s.span_bend(0) - 9.0).abs() < 1e-12, "{}", s.span_bend(0)); +} + fn scaled(s: &Spline, k: f64) -> Spline { Spline { control: s.control.iter().map(|c| *c * k).collect(), fit: s.fit.iter().map(|c| *c * k).collect(), ..s.clone() } } diff --git a/crates/ui-egui/src/cmdline.rs b/crates/ui-egui/src/cmdline.rs index 40397df99..fc25555e2 100644 --- a/crates/ui-egui/src/cmdline.rs +++ b/crates/ui-egui/src/cmdline.rs @@ -494,7 +494,12 @@ pub fn show(app: &mut CadApp, ui: &mut egui::Ui, canvas: Rect) { p.galley(pos2(x, bar.center().y - g.size().y / 2.0), g, t.text); x += gw; if !pr.raw && !pr.keywords.is_empty() { - let g = p.layout_no_wrap(if pr.message.is_empty() { " [".into() } else { crate::tl!(" or [").into() }, font.clone(), t.text); + // As the engine's prompt text says it; only " or [" has words to translate. + let lead = match pr.keyword_lead() { + " or [" => crate::tl!(" or ["), + lead => lead, + }; + let g = p.layout_no_wrap(lead.into(), font.clone(), t.text); let gw = g.size().x; p.galley(pos2(x, bar.center().y - g.size().y / 2.0), g, t.text); x += gw; diff --git a/crates/ui-egui/src/i18n/ar.tsv b/crates/ui-egui/src/i18n/ar.tsv index ccc9b72d5..7713378d9 100644 --- a/crates/ui-egui/src/i18n/ar.tsv +++ b/crates/ui-egui/src/i18n/ar.tsv @@ -305,7 +305,7 @@ Enter a vertex editing option أدخل خيار تحرير الرؤوس Enter an option أدخل خياراً Enter angle of xline أدخل زاوية الخط الإنشائي - Enter angle of xline (0) or أدخل زاوية الخط الإنشائي (0) أو + Enter angle of xline (0) أدخل زاوية الخط الإنشائي (0) Enter area of rectangle in current units أدخل مساحة المستطيل بالوحدات الحالية Enter attribute prompt أدخل موجه السمة Enter attribute tag name أدخل اسم وسم السمة @@ -316,7 +316,7 @@ Enter default attribute value أدخل قيمة السمة الافتراضية Enter degree of spline أدخل درجة السبلاين Enter delta angle أدخل زاوية دلتا - Enter delta length or أدخل طول دلتا أو + Enter delta length أدخل طول دلتا Enter dimension text أدخل نص التأشير Enter dimension text (<> = measurement) أدخل نص التأشير (<> = القياس) Enter dimension value or [name=expression] أدخل قيمة التأشير أو [name=expression] @@ -852,8 +852,8 @@ Select an arc or circle حدد قوساً أو دائرة Select an arc. حدد قوساً. Select an object حدد كائناً - Select an object to change or حدد كائناً لتغييره أو - Select an object to measure or حدد كائناً لقياسه أو + Select an object to change حدد كائناً لتغييره + Select an object to measure حدد كائناً لقياسه Select an object. حدد كائنًا. Select an open curve. حدد منحنى مفتوحاً. Select an open line, arc, polyline, ellipse arc or spline. حدد خطاً مفتوحاً أو قوساً أو متعدد خطوط أو قوس إهليلج أو سبلاين. @@ -867,9 +867,8 @@ Select first line حدد الخط الأول Select first line or arc حدد الخط الأول أو قوساً Select first object حدد الكائن الأول - Select first object or حدد الكائن الأول أو Select first point حدد النقطة الأولى - Select nested objects to copy or حدد الكائنات المتداخلة لنسخها أو + Select nested objects to copy حدد الكائنات المتداخلة لنسخها Select object حدد كائناً Select object to dimension حدد كائناً لتأشيره Select object to divide حدد كائناً لتقسيمه @@ -886,7 +885,7 @@ Select one polyline (Multiple is available through the JSON form). حدد متعدد خطوط واحداً (يتوفر الوضع المتعدد عبر نموذج JSON). Select path curve حدد منحنى المسار Select point or object حدد نقطة أو كائناً - Select polyline or حدد متعدد خطوط أو + Select polyline حدد متعدد خطوط Select second line حدد الخط الثاني Select second line or shift-select to apply corner حدد الخط الثاني أو حدد مع Shift لتطبيق الزاوية Select second object حدد الكائن الثاني @@ -956,9 +955,8 @@ Specify axis endpoint of ellipse حدد نقطة نهاية محور الإهليلج Specify base diameter حدد القطر الأساسي Specify base point حدد نقطة الأساس - Specify base point or حدد نقطة الأساس أو Specify base point or displacement (drag with the middle mouse button for realtime pan) حدد نقطة الأساس أو الإزاحة (اسحب بزر الفأرة الأوسط للإزاحة الفورية) - Specify base radius or حدد نصف القطر الأساسي أو + Specify base radius حدد نصف القطر الأساسي Specify center of donut حدد مركز الحلقة Specify center of ellipse حدد مركز الإهليلج Specify center of polygon حدد مركز المضلع @@ -1000,7 +998,7 @@ Specify first point on circle: _tan to حدد النقطة الأولى على الدائرة: _تماس إلى Specify first source point حدد نقطة المصدر الأولى Specify height حدد الارتفاع - Specify helix height or حدد ارتفاع الحلزون أو + Specify helix height حدد ارتفاع الحلزون Specify included angle حدد الزاوية المحصورة Specify insertion base point حدد نقطة الأساس للإدراج Specify insertion point حدد نقطة الإدراج @@ -1019,7 +1017,6 @@ Specify new width for all segments حدد عرضاً جديداً لكل المقاطع Specify next point حدد النقطة التالية Specify offset distance حدد مسافة الإزاحة - Specify offset distance or حدد مسافة الإزاحة أو Specify opposite corner حدد الزاوية المقابلة Specify other corner point حدد نقطة الزاوية الأخرى Specify other endpoint of axis حدد نقطة النهاية الأخرى للمحور @@ -1032,7 +1029,6 @@ Specify radius of circle حدد نصف قطر الدائرة Specify rotation angle حدد زاوية التدوير Specify rotation angle of text حدد زاوية تدوير النص - Specify rotation angle or حدد زاوية التدوير أو Specify scale factor حدد معامل المقياس Specify second angle endpoint حدد نقطة نهاية الزاوية الثانية Specify second break point حدد نقطة الفصل الثانية @@ -1065,9 +1061,9 @@ Specify third source point or حدد نقطة المصدر الثالثة أو <متابعة> Specify through point حدد نقطة العبور Specify top diameter حدد القطر العلوي - Specify top radius or حدد نصف القطر العلوي أو + Specify top radius حدد نصف القطر العلوي Specify total angle حدد الزاوية الكلية - Specify total length or حدد الطول الكلي أو + Specify total length حدد الطول الكلي Specify width for rectangles حدد العرض للمستطيلات Sphere كرة Spline سبلاين diff --git a/crates/ui-egui/src/i18n/bs.tsv b/crates/ui-egui/src/i18n/bs.tsv index 460959a33..b349db278 100644 --- a/crates/ui-egui/src/i18n/bs.tsv +++ b/crates/ui-egui/src/i18n/bs.tsv @@ -281,7 +281,7 @@ Enter a vertex editing option Unesite opciju uređivanja tjemena Enter an option Unesite opciju Enter angle of xline Unesite ugao konstrukcijske linije - Enter angle of xline (0) or Unesite ugao konstrukcijske linije (0) ili + Enter angle of xline (0) Unesite ugao konstrukcijske linije (0) Enter area of rectangle in current units Unesite površinu pravougaonika u trenutnim jedinicama Enter attribute prompt Unesite upit atributa Enter attribute tag name Unesite naziv oznake atributa @@ -292,7 +292,7 @@ Enter default attribute value Unesite zadanu vrijednost atributa Enter degree of spline Unesite stepen splajna Enter delta angle Unesite delta ugao - Enter delta length or Unesite delta dužinu ili + Enter delta length Unesite delta dužinu Enter dimension text Unesite tekst kote Enter dimension text (<> = measurement) Unesite tekst kote (<> = mjera) Enter dimension value or [name=expression] Unesite vrijednost kote ili [naziv=izraz] @@ -788,8 +788,8 @@ Select an arc or circle Odaberite luk ili krug Select an arc. Odaberite luk. Select an object Odaberite objekat - Select an object to change or Odaberite objekat za promjenu ili - Select an object to measure or Odaberite objekat za mjerenje ili + Select an object to change Odaberite objekat za promjenu + Select an object to measure Odaberite objekat za mjerenje Select an object. Odaberite objekat. Select an open curve. Odaberite otvorenu krivu. Select an open line, arc, polyline, ellipse arc or spline. Odaberite otvorenu liniju, luk, poliliniju, eliptični luk ili splajn. @@ -803,14 +803,13 @@ Select first line Odaberite prvu liniju Select first line or arc Odaberite prvu liniju ili luk Select first object Odaberite prvi objekat - Select first object or Odaberite prvi objekat ili Select first point Odaberite prvu tačku Add to Working Set Dodaj u radni skup Edit Reference In-Place Uredi referencu na mjestu Save Reference Edits Sačuvaj izmjene reference Working Set Radni skup Xref and Block In-place Editing Uređivanje vanjskih referenci i blokova na mjestu - Select nested objects to copy or Odaberite ugniježđene objekte za kopiranje ili + Select nested objects to copy Odaberite ugniježđene objekte za kopiranje Select object Odaberite objekat Select object to dimension Odaberite objekat za kotiranje Select object to divide Odaberite objekat za dijeljenje @@ -826,7 +825,7 @@ Select one polyline (Multiple is available through the JSON form). Odaberite jednu poliliniju (Višestruko je dostupno putem JSON oblika). Select path curve Odaberite krivu putanje Select point or object Odaberite tačku ili objekat - Select polyline or Odaberite poliliniju ili + Select polyline Odaberite poliliniju Select second line Odaberite drugu liniju Select second line or shift-select to apply corner Odaberite drugu liniju ili Shift+odabir za primjenu ugla Select second object Odaberite drugi objekat @@ -884,9 +883,8 @@ Specify axis endpoint of ellipse Navedite krajnju tačku ose elipse Specify base diameter Navedite prečnik baze Specify base point Navedite baznu tačku - Specify base point or Navedite baznu tačku ili Specify base point or displacement (drag with the middle mouse button for realtime pan) Navedite baznu tačku ili pomak (prevucite srednjim dugmetom miša za pomicanje pogleda u stvarnom vremenu) - Specify base radius or Navedite poluprečnik baze ili + Specify base radius Navedite poluprečnik baze Specify center of donut Navedite središte prstena Specify center of ellipse Navedite središte elipse Specify center of polygon Navedite središte mnogougla @@ -928,7 +926,7 @@ Specify first point on circle: _tan to Navedite prvu tačku na krugu: _tan na Specify first source point Navedite prvu izvornu tačku Specify height Navedite visinu - Specify helix height or Navedite visinu spirale ili + Specify helix height Navedite visinu spirale Specify included angle Navedite obuhvaćeni ugao Specify insertion base point Navedite baznu tačku umetanja Specify insertion point Navedite tačku umetanja @@ -982,7 +980,6 @@ Specify new width for all segments Navedite novu širinu za sve segmente Specify next point Navedite sljedeću tačku Specify offset distance Navedite udaljenost odmaka - Specify offset distance or Navedite udaljenost odmaka ili Specify opposite corner Navedite suprotni ugao Specify other corner point Navedite tačku drugog ugla Specify other endpoint of axis Navedite drugu krajnju tačku ose @@ -995,7 +992,6 @@ Specify radius of circle Navedite poluprečnik kruga Specify rotation angle Navedite ugao rotacije Specify rotation angle of text Navedite ugao rotacije teksta - Specify rotation angle or Navedite ugao rotacije ili Specify scale factor Navedite faktor skale Specify second angle endpoint Navedite drugu krajnju tačku ugla Specify second break point Navedite drugu tačku prekida @@ -1028,9 +1024,9 @@ Specify third source point or Navedite treću izvornu tačku ili Specify through point Navedite tačku kroz koju prolazi Specify top diameter Navedite gornji prečnik - Specify top radius or Navedite gornji poluprečnik ili + Specify top radius Navedite gornji poluprečnik Specify total angle Navedite ukupni ugao - Specify total length or Navedite ukupnu dužinu ili + Specify total length Navedite ukupnu dužinu Specify width for rectangles Navedite širinu za pravougaonike Sphere Sfera Spline Splajn diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 2419bf41f..61dc1b2b6 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -279,7 +279,7 @@ Enter a vertex editing option Zadejte možnost úpravy vrcholů Enter an option Zadejte možnost Enter angle of xline Zadejte úhel přímky - Enter angle of xline (0) or Zadejte úhel přímky (0) nebo + Enter angle of xline (0) Zadejte úhel přímky (0) Enter area of rectangle in current units Zadejte plochu obdélníku v aktuálních jednotkách Enter attribute prompt Zadejte výzvu atributu Enter attribute tag name Zadejte označení atributu @@ -290,7 +290,7 @@ Enter default attribute value Zadejte výchozí hodnotu atributu Enter degree of spline Zadejte stupeň spline Enter delta angle Zadejte změnu úhlu - Enter delta length or Zadejte změnu délky nebo + Enter delta length Zadejte změnu délky Enter dimension text Zadejte text kóty Enter dimension text (<> = measurement) Zadejte text kóty (<> = naměřená hodnota) Enter dimension value or [name=expression] Zadejte hodnotu kóty nebo [name=expression] @@ -786,8 +786,8 @@ Select an arc or circle Vyberte oblouk nebo kružnici Select an arc. Vyberte oblouk. Select an object Vyberte objekt - Select an object to change or Vyberte objekt ke změně nebo - Select an object to measure or Vyberte objekt k měření nebo + Select an object to change Vyberte objekt ke změně + Select an object to measure Vyberte objekt k měření Select an object. Vyberte objekt. Select an open curve. Vyberte otevřenou křivku. Select an open line, arc, polyline, ellipse arc or spline. Vyberte otevřenou úsečku, oblouk, křivku, eliptický oblouk nebo spline. @@ -801,14 +801,13 @@ Select first line Vyberte první úsečku Select first line or arc Vyberte první úsečku nebo oblouk Select first object Vyberte první objekt - Select first object or Vyberte první objekt nebo Select first point Vyberte první bod Add to Working Set Přidat do pracovní sady Edit Reference In-Place Upravit referenci na místě Save Reference Edits Uložit úpravy reference Working Set Pracovní sada Xref and Block In-place Editing Úpravy xref a bloků na místě - Select nested objects to copy or Vyberte vnořené objekty ke kopírování nebo + Select nested objects to copy Vyberte vnořené objekty ke kopírování Select object Vyberte objekt Select object to dimension Vyberte objekt ke kótování Select object to divide Vyberte objekt k dělení @@ -824,7 +823,7 @@ Select one polyline (Multiple is available through the JSON form). Vyberte jednu křivku (možnost Multiple je dostupná ve formě JSON). Select path curve Vyberte křivku trajektorie Select point or object Vyberte bod nebo objekt - Select polyline or Vyberte křivku nebo + Select polyline Vyberte křivku Select second line Vyberte druhou úsečku Select second line or shift-select to apply corner Vyberte druhou úsečku; s klávesou Shift vytvoříte roh Select second object Vyberte druhý objekt @@ -882,9 +881,8 @@ Specify axis endpoint of ellipse Určete koncový bod osy elipsy Specify base diameter Určete průměr základny Specify base point Určete základní bod - Specify base point or Určete základní bod nebo Specify base point or displacement (drag with the middle mouse button for realtime pan) Určete základní bod nebo posunutí (tažením prostředním tlačítkem myši posunete pohled v reálném čase) - Specify base radius or Určete poloměr základny nebo + Specify base radius Určete poloměr základny Specify center of donut Určete střed prstence Specify center of ellipse Určete střed elipsy Specify center of polygon Určete střed mnohoúhelníku @@ -926,7 +924,7 @@ Specify first point on circle: _tan to Určete první bod na kružnici: _tan k Specify first source point Určete první zdrojový bod Specify height Určete výšku - Specify helix height or Určete výšku šroubovice nebo + Specify helix height Určete výšku šroubovice Specify included angle Určete středový úhel Specify insertion base point Určete základní bod vložení Specify insertion point Určete bod vložení @@ -980,7 +978,6 @@ Specify new width for all segments Určete novou šířku všech segmentů Specify next point Určete další bod Specify offset distance Určete vzdálenost ekvidistanty - Specify offset distance or Určete vzdálenost ekvidistanty nebo Specify opposite corner Určete protilehlý roh Specify other corner point Určete bod druhého rohu Specify other endpoint of axis Určete druhý koncový bod osy @@ -993,7 +990,6 @@ Specify radius of circle Určete poloměr kružnice Specify rotation angle Určete úhel otočení Specify rotation angle of text Určete úhel otočení textu - Specify rotation angle or Určete úhel otočení nebo Specify scale factor Určete faktor měřítka Specify second angle endpoint Určete druhý koncový bod úhlu Specify second break point Určete druhý bod přerušení @@ -1026,9 +1022,9 @@ Specify third source point or Určete třetí zdrojový bod nebo Specify through point Určete bod, kterým má procházet Specify top diameter Určete horní průměr - Specify top radius or Určete horní poloměr nebo + Specify top radius Určete horní poloměr Specify total angle Určete celkový úhel - Specify total length or Určete celkovou délku nebo + Specify total length Určete celkovou délku Specify width for rectangles Určete šířku obdélníků Sphere Koule Spline Spline diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 2186fc743..f36e9ed02 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -222,7 +222,7 @@ Enter a vertex editing option Geben Sie eine Option zur Scheitelpunktbearbeitung ein Enter an option Geben Sie eine Option ein Enter angle of xline Geben Sie den Winkel der Konstruktionslinie ein - Enter angle of xline (0) or Geben Sie den Winkel der Konstruktionslinie ein (0) oder + Enter angle of xline (0) Geben Sie den Winkel der Konstruktionslinie ein (0) Enter area of rectangle in current units Geben Sie die Fläche des Rechtecks in den aktuellen Einheiten ein Enter attribute prompt Geben Sie die Attributaufforderung ein Enter attribute tag name Geben Sie den Attribut-Tag-Namen ein @@ -233,7 +233,7 @@ Enter default attribute value Geben Sie den Standard-Attributwert ein Enter degree of spline Geben Sie den Grad des Splines ein Enter delta angle Geben Sie den Delta-Winkel ein - Enter delta length or Geben Sie die Delta-Länge ein oder + Enter delta length Geben Sie die Delta-Länge ein Enter dimension text Geben Sie den Bemaßungstext ein Enter dimension text (<> = measurement) Geben Sie den Bemaßungstext ein (<> = Messwert) Enter dimension value or [name=expression] Geben Sie einen Bemaßungswert oder [name=expression] ein @@ -676,8 +676,8 @@ Select an arc or circle Wählen Sie einen Bogen oder Kreis Select an arc. Wählen Sie einen Bogen. Select an object Wählen Sie ein Objekt - Select an object to change or Wählen Sie ein zu änderndes Objekt oder - Select an object to measure or Wählen Sie ein zu messendes Objekt oder + Select an object to change Wählen Sie ein zu änderndes Objekt + Select an object to measure Wählen Sie ein zu messendes Objekt Select an object. Wählen Sie ein Objekt. Add to Working Set Zum Arbeitssatz hinzufügen Edit Reference In-Place Referenz an Ort und Stelle bearbeiten @@ -696,9 +696,8 @@ Select first line Wählen Sie die erste Linie Select first line or arc Wählen Sie die erste Linie oder den ersten Bogen Select first object Wählen Sie das erste Objekt - Select first object or Wählen Sie das erste Objekt oder Select first point Wählen Sie den ersten Punkt - Select nested objects to copy or Wählen Sie zu kopierende verschachtelte Objekte oder + Select nested objects to copy Wählen Sie zu kopierende verschachtelte Objekte Select object Wählen Sie ein Objekt Select object to dimension Wählen Sie das zu bemaßende Objekt Select object to divide Wählen Sie das zu teilende Objekt @@ -714,7 +713,7 @@ Select one polyline (Multiple is available through the JSON form). Wählen Sie eine Polylinie (Multiple ist über die JSON-Form verfügbar). Select path curve Wählen Sie die Pfadkurve Select point or object Wählen Sie einen Punkt oder ein Objekt - Select polyline or Wählen Sie eine Polylinie oder + Select polyline Wählen Sie eine Polylinie Select second line Wählen Sie die zweite Linie Select second line or shift-select to apply corner Wählen Sie die zweite Linie oder wählen Sie mit der Umschalttaste, um eine Ecke anzuwenden Select second object Wählen Sie das zweite Objekt @@ -767,9 +766,8 @@ Specify axis endpoint of ellipse Geben Sie den Achsenendpunkt der Ellipse an Specify base diameter Geben Sie den Basisdurchmesser an Specify base point Geben Sie den Basispunkt an - Specify base point or Geben Sie den Basispunkt an oder Specify base point or displacement (drag with the middle mouse button for realtime pan) Geben Sie den Basispunkt oder die Verschiebung an (ziehen Sie mit der mittleren Maustaste zum Schwenken in Echtzeit) - Specify base radius or Geben Sie den Basisradius an oder + Specify base radius Geben Sie den Basisradius an Specify center of donut Geben Sie den Mittelpunkt des Rings an Specify center of ellipse Geben Sie den Mittelpunkt der Ellipse an Specify center of polygon Geben Sie den Mittelpunkt des Polygons an @@ -811,7 +809,7 @@ Specify first point on circle: _tan to Geben Sie den ersten Punkt auf dem Kreis an: _tan zu Specify first source point Geben Sie den ersten Quellpunkt an Specify height Geben Sie die Höhe an - Specify helix height or Geben Sie die Höhe der Helix an oder + Specify helix height Geben Sie die Höhe der Helix an Specify included angle Geben Sie den eingeschlossenen Winkel an Specify insertion base point Geben Sie den Einfügebasispunkt an Specify insertion point Geben Sie den Einfügepunkt an @@ -830,7 +828,6 @@ Specify new width for all segments Geben Sie die neue Breite für alle Segmente an Specify next point Geben Sie den nächsten Punkt an Specify offset distance Geben Sie den Versatzabstand an - Specify offset distance or Geben Sie den Versatzabstand an oder Specify opposite corner Geben Sie die gegenüberliegende Ecke an Specify other corner point Geben Sie den anderen Eckpunkt an Specify other endpoint of axis Geben Sie den anderen Endpunkt der Achse an @@ -843,7 +840,6 @@ Specify radius of circle Geben Sie den Radius des Kreises an Specify rotation angle Geben Sie den Drehwinkel an Specify rotation angle of text Geben Sie den Drehwinkel des Textes an - Specify rotation angle or Geben Sie den Drehwinkel an oder Specify scale factor Geben Sie den Skalierfaktor an Specify second angle endpoint Geben Sie den zweiten Endpunkt des Winkels an Specify second break point Geben Sie den zweiten Unterbrechungspunkt an @@ -876,9 +872,9 @@ Specify third source point or Geben Sie den dritten Quellpunkt an oder Specify through point Geben Sie den Durchgangspunkt an Specify top diameter Geben Sie den oberen Durchmesser an - Specify top radius or Geben Sie den oberen Radius an oder + Specify top radius Geben Sie den oberen Radius an Specify total angle Geben Sie den Gesamtwinkel an - Specify total length or Geben Sie die Gesamtlänge an oder + Specify total length Geben Sie die Gesamtlänge an Specify width for rectangles Geben Sie die Breite für Rechtecke an Sphere Kugel Spline Spline diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index 16fcecfeb..528dacf55 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -337,7 +337,7 @@ Enter a vertex editing option Εισαγάγετε επιλογή επεξεργασίας κορυφής Enter an option Εισαγάγετε επιλογή Enter angle of xline Εισαγάγετε γωνία βοηθητικής ευθείας - Enter angle of xline (0) or Εισαγάγετε γωνία βοηθητικής ευθείας (0) ή + Enter angle of xline (0) Εισαγάγετε γωνία βοηθητικής ευθείας (0) Enter area of rectangle in current units Εισαγάγετε το εμβαδόν ορθογωνίου στις τρέχουσες μονάδες Enter attribute prompt Εισαγάγετε μήνυμα προτροπής ιδιότητας Enter attribute tag name Εισαγάγετε όνομα ετικέτας ιδιότητας @@ -348,7 +348,7 @@ Enter default attribute value Εισαγάγετε προεπιλεγμένη τιμή ιδιότητας Enter degree of spline Εισαγάγετε βαθμό καμπύλης spline Enter delta angle Εισαγάγετε μεταβολή γωνίας - Enter delta length or Εισαγάγετε μεταβολή μήκους ή + Enter delta length Εισαγάγετε μεταβολή μήκους Enter dimension text Εισαγάγετε κείμενο διάστασης Enter dimension text (<> = measurement) Εισαγάγετε κείμενο διάστασης (<> = μέτρηση) Enter dimension value or [name=expression] Εισαγάγετε τιμή διάστασης ή [όνομα=έκφραση] @@ -919,8 +919,8 @@ Select an arc or circle Επιλέξτε τόξο ή κύκλο Select an arc. Επιλέξτε τόξο. Select an object Επιλέξτε αντικείμενο - Select an object to change or Επιλέξτε αντικείμενο για αλλαγή ή - Select an object to measure or Επιλέξτε αντικείμενο για μέτρηση ή + Select an object to change Επιλέξτε αντικείμενο για αλλαγή + Select an object to measure Επιλέξτε αντικείμενο για μέτρηση Select an object. Επιλέξτε αντικείμενο. Select an open curve. Επιλέξτε ανοικτή καμπύλη. Select an open line, arc, polyline, ellipse arc or spline. Επιλέξτε ανοικτή γραμμή, τόξο, πολυγραμμή, ελλειπτικό τόξο ή καμπύλη spline. @@ -934,9 +934,8 @@ Select first line Επιλέξτε πρώτη γραμμή Select first line or arc Επιλέξτε πρώτη γραμμή ή τόξο Select first object Επιλέξτε πρώτο αντικείμενο - Select first object or Επιλέξτε πρώτο αντικείμενο ή Select first point Επιλέξτε πρώτο σημείο - Select nested objects to copy or Επιλέξτε ένθετα αντικείμενα για αντιγραφή ή + Select nested objects to copy Επιλέξτε ένθετα αντικείμενα για αντιγραφή Select object Επιλέξτε αντικείμενο Select object to dimension Επιλέξτε αντικείμενο για διαστασιολόγηση Select object to divide Επιλέξτε αντικείμενο για διαίρεση @@ -954,7 +953,7 @@ Select one polyline (Multiple is available through the JSON form). Επιλέξτε μία πολυγραμμή (η επιλογή Multiple διατίθεται μέσω JSON). Select path curve Επιλέξτε καμπύλη διαδρομής Select point or object Επιλέξτε σημείο ή αντικείμενο - Select polyline or Επιλέξτε πολυγραμμή ή + Select polyline Επιλέξτε πολυγραμμή Select second line Επιλέξτε δεύτερη γραμμή Select second line or shift-select to apply corner Επιλέξτε δεύτερη γραμμή ή κρατήστε Shift για εφαρμογή γωνίας Select second object Επιλέξτε δεύτερο αντικείμενο @@ -1036,9 +1035,8 @@ Specify axis endpoint of ellipse Καθορίστε τελικό σημείο άξονα έλλειψης Specify base diameter Καθορίστε διάμετρο βάσης Specify base point Καθορίστε σημείο βάσης - Specify base point or Καθορίστε σημείο βάσης ή Specify base point or displacement (drag with the middle mouse button for realtime pan) Καθορίστε σημείο βάσης ή μετατόπιση (σύρετε με το μεσαίο πλήκτρο του ποντικιού για μετατόπιση όψης σε πραγματικό χρόνο) - Specify base radius or Καθορίστε ακτίνα βάσης ή + Specify base radius Καθορίστε ακτίνα βάσης Specify center of donut Καθορίστε κέντρο δακτυλίου Specify center of ellipse Καθορίστε κέντρο έλλειψης Specify center of polygon Καθορίστε κέντρο πολυγώνου @@ -1080,7 +1078,7 @@ Specify first point on circle: _tan to Καθορίστε πρώτο σημείο επάνω στον κύκλο: _tan προς Specify first source point Καθορίστε πρώτο σημείο προέλευσης Specify height Καθορίστε ύψος - Specify helix height or Καθορίστε ύψος έλικας ή + Specify helix height Καθορίστε ύψος έλικας Specify included angle Καθορίστε περιεχόμενη γωνία Specify insertion base point Καθορίστε σημείο βάσης εισαγωγής Specify insertion point Καθορίστε σημείο εισαγωγής @@ -1099,7 +1097,6 @@ Specify new width for all segments Καθορίστε νέο πλάτος για όλα τα τμήματα Specify next point Καθορίστε επόμενο σημείο Specify offset distance Καθορίστε απόσταση παράλληλης μετατόπισης (Offset) - Specify offset distance or Καθορίστε απόσταση παράλληλης μετατόπισης ή Specify opposite corner Καθορίστε απέναντι γωνία Specify other corner point Καθορίστε το άλλο γωνιακό σημείο Specify other endpoint of axis Καθορίστε το άλλο τελικό σημείο άξονα @@ -1112,7 +1109,6 @@ Specify radius of circle Καθορίστε ακτίνα κύκλου Specify rotation angle Καθορίστε γωνία περιστροφής Specify rotation angle of text Καθορίστε γωνία περιστροφής κειμένου - Specify rotation angle or Καθορίστε γωνία περιστροφής ή Specify scale factor Καθορίστε συντελεστή κλίμακας Specify second angle endpoint Καθορίστε δεύτερο τελικό σημείο γωνίας Specify second break point Καθορίστε δεύτερο σημείο διακοπής @@ -1145,9 +1141,9 @@ Specify third source point or Καθορίστε τρίτο σημείο προέλευσης ή <συνέχεια> Specify through point Καθορίστε σημείο διέλευσης Specify top diameter Καθορίστε άνω διάμετρο - Specify top radius or Καθορίστε άνω ακτίνα ή + Specify top radius Καθορίστε άνω ακτίνα Specify total angle Καθορίστε συνολική γωνία - Specify total length or Καθορίστε συνολικό μήκος ή + Specify total length Καθορίστε συνολικό μήκος Specify width for rectangles Καθορίστε πλάτος ορθογωνίων Sphere Σφαίρα Spherical Σφαιρικό diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 8c45b7f97..457341c36 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -295,7 +295,7 @@ Enter a vertex editing option Introduce una opción de edición de vértices Enter an option Introduce una opción Enter angle of xline Introduce el ángulo de la línea auxiliar - Enter angle of xline (0) or Introduce el ángulo de la línea auxiliar (0) o + Enter angle of xline (0) Introduce el ángulo de la línea auxiliar (0) Enter area of rectangle in current units Introduce el área del rectángulo en las unidades actuales Enter attribute prompt Introduce la solicitud del atributo Enter attribute tag name Introduce la etiqueta del atributo @@ -306,7 +306,7 @@ Enter default attribute value Introduce el valor predeterminado del atributo Enter degree of spline Introduce el grado de la spline Enter delta angle Introduce el incremento angular - Enter delta length or Introduce el incremento de longitud o + Enter delta length Introduce el incremento de longitud Enter dimension text Introduce el texto de cota Enter dimension text (<> = measurement) Introduce el texto de cota (<> = medida) Enter dimension value or [name=expression] Introduce el valor de cota o [nombre=expresión] @@ -885,8 +885,8 @@ Select an arc or circle Selecciona un arco o círculo Select an arc. Selecciona un arco. Select an object Selecciona un objeto - Select an object to change or Selecciona un objeto que modificar o - Select an object to measure or Selecciona un objeto que medir o + Select an object to change Selecciona un objeto que modificar + Select an object to measure Selecciona un objeto que medir Select an object. Selecciona un objeto. Select an open curve. Selecciona una curva abierta. Select an open line, arc, polyline, ellipse arc or spline. Selecciona una línea, arco, polilínea, arco elíptico o spline abierta. @@ -900,9 +900,8 @@ Select first line Selecciona la primera línea Select first line or arc Selecciona la primera línea o arco Select first object Selecciona el primer objeto - Select first object or Selecciona el primer objeto o Select first point Selecciona el primer punto - Select nested objects to copy or Selecciona objetos anidados para copiar o + Select nested objects to copy Selecciona objetos anidados para copiar Select object Selecciona un objeto Select object to dimension Selecciona un objeto para acotar Select object to divide Selecciona un objeto para dividir @@ -918,7 +917,7 @@ Select one polyline (Multiple is available through the JSON form). Selecciona una polilínea (la opción Multiple está disponible en la forma JSON). Select path curve Selecciona la curva del camino Select point or object Selecciona un punto u objeto - Select polyline or Selecciona una polilínea o + Select polyline Selecciona una polilínea Select second line Selecciona la segunda línea Select second line or shift-select to apply corner Selecciona la segunda línea o usa Mayús para aplicar una esquina Select second object Selecciona el segundo objeto @@ -971,9 +970,8 @@ Specify axis endpoint of ellipse Indica el extremo del eje de la elipse Specify base diameter Indica el diámetro de la base Specify base point Indica el punto base - Specify base point or Indica el punto base o Specify base point or displacement (drag with the middle mouse button for realtime pan) Indica el punto base o el desplazamiento (arrastra con el botón central para encuadrar) - Specify base radius or Indica el radio de la base o + Specify base radius Indica el radio de la base Specify center of donut Indica el centro de la arandela Specify center of ellipse Indica el centro de la elipse Specify center of polygon Indica el centro del polígono @@ -1015,7 +1013,7 @@ Specify first point on circle: _tan to Indica el primer punto del círculo: _tan a Specify first source point Indica el primer punto de origen Specify height Indica la altura - Specify helix height or Indica la altura de la hélice o + Specify helix height Indica la altura de la hélice Specify included angle Indica el ángulo incluido Specify insertion base point Indica el punto base de inserción Specify insertion point Indica el punto de inserción @@ -1034,7 +1032,6 @@ Specify new width for all segments Indica la nueva anchura de todos los segmentos Specify next point Indica el siguiente punto Specify offset distance Indica la distancia de desfase - Specify offset distance or Indica la distancia de desfase o Specify opposite corner Indica la esquina opuesta Specify other corner point Indica el punto de la otra esquina Specify other endpoint of axis Indica el otro extremo del eje @@ -1047,7 +1044,6 @@ Specify radius of circle Indica el radio del círculo Specify rotation angle Indica el ángulo de giro Specify rotation angle of text Indica el ángulo de giro del texto - Specify rotation angle or Indica el ángulo de giro o Specify scale factor Indica el factor de escala Specify second angle endpoint Indica el segundo extremo del ángulo Specify second break point Indica el segundo punto de ruptura @@ -1080,9 +1076,9 @@ Specify third source point or Indica el tercer punto de origen o Specify through point Indica el punto a atravesar Specify top diameter Indica el diámetro superior - Specify top radius or Indica el radio superior o + Specify top radius Indica el radio superior Specify total angle Indica el ángulo total - Specify total length or Indica la longitud total o + Specify total length Indica la longitud total Specify width for rectangles Indica la anchura de los rectángulos Sphere Esfera Spline Spline diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 548ed6a66..62c77c3f9 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -221,7 +221,7 @@ Enter a vertex editing option Entrez une option d'édition de sommet Enter an option Entrez une option Enter angle of xline Entrez l'angle de la ligne de construction - Enter angle of xline (0) or Entrez l'angle de la ligne de construction (0) ou + Enter angle of xline (0) Entrez l'angle de la ligne de construction (0) Enter area of rectangle in current units Entrez l'aire du rectangle dans les unités courantes Enter attribute prompt Entrez l'invite de l'attribut Enter attribute tag name Entrez le nom de l'étiquette d'attribut @@ -232,7 +232,7 @@ Enter default attribute value Entrez la valeur par défaut de l'attribut Enter degree of spline Entrez le degré de la spline Enter delta angle Entrez l'écart d'angle - Enter delta length or Entrez l'écart de longueur ou + Enter delta length Entrez l'écart de longueur Enter dimension text Entrez le texte de cotation Enter dimension text (<> = measurement) Entrez le texte de cotation (<> = mesure) Enter dimension value or [name=expression] Entrez la valeur de cotation ou [name=expression] @@ -675,8 +675,8 @@ Select an arc or circle Sélectionner un arc ou un cercle Select an arc. Sélectionner un arc. Select an object Sélectionner un objet - Select an object to change or Sélectionner un objet à modifier ou - Select an object to measure or Sélectionner un objet à mesurer ou + Select an object to change Sélectionner un objet à modifier + Select an object to measure Sélectionner un objet à mesurer Select an object. Sélectionner un objet. Select an open curve. Sélectionner une courbe ouverte. Select an open line, arc, polyline, ellipse arc or spline. Sélectionner une ligne, un arc, une polyligne, un arc elliptique ou une spline ouverts. @@ -690,9 +690,8 @@ Select first line Sélectionner la première ligne Select first line or arc Sélectionner la première ligne ou le premier arc Select first object Sélectionner le premier objet - Select first object or Sélectionner le premier objet ou Select first point Sélectionner le premier point - Select nested objects to copy or Sélectionner des objets imbriqués à copier ou + Select nested objects to copy Sélectionner des objets imbriqués à copier Select object Sélectionner un objet Select object to dimension Sélectionner un objet à coter Select object to divide Sélectionner un objet à diviser @@ -708,7 +707,7 @@ Select one polyline (Multiple is available through the JSON form). Sélectionner une polyligne (l'option Multiple est disponible via le formulaire JSON). Select path curve Sélectionner la courbe de trajectoire Select point or object Sélectionner un point ou un objet - Select polyline or Sélectionner une polyligne ou + Select polyline Sélectionner une polyligne Select second line Sélectionner la deuxième ligne Select second line or shift-select to apply corner Sélectionner la deuxième ligne ou sélectionner avec Maj pour former le coin Select second object Sélectionner le deuxième objet @@ -761,9 +760,8 @@ Specify axis endpoint of ellipse Spécifier l'extrémité de l'axe de l'ellipse Specify base diameter Spécifiez le diamètre de la base Specify base point Spécifiez le point de base - Specify base point or Spécifiez le point de base ou Specify base point or displacement (drag with the middle mouse button for realtime pan) Spécifiez le point de base ou le déplacement (faites glisser avec le bouton central de la souris pour un panoramique en temps réel) - Specify base radius or Spécifiez le rayon de base ou + Specify base radius Spécifiez le rayon de base Specify center of donut Spécifiez le centre de l'anneau Specify center of ellipse Spécifiez le centre de l'ellipse Specify center of polygon Spécifiez le centre du polygone @@ -805,7 +803,7 @@ Specify first point on circle: _tan to Spécifiez le premier point sur le cercle : _tan à Specify first source point Spécifiez le premier point source Specify height Spécifiez la hauteur - Specify helix height or Spécifiez la hauteur de l'hélice ou + Specify helix height Spécifiez la hauteur de l'hélice Specify included angle Spécifiez l'angle inclus Specify insertion base point Spécifiez le point de base d'insertion Specify insertion point Spécifiez le point d'insertion @@ -824,7 +822,6 @@ Specify new width for all segments Spécifiez la nouvelle largeur de tous les segments Specify next point Spécifiez le point suivant Specify offset distance Spécifiez la distance de décalage - Specify offset distance or Spécifiez la distance de décalage ou Specify opposite corner Spécifiez le coin opposé Specify other corner point Spécifiez l'autre point d'angle Specify other endpoint of axis Spécifiez l'autre point final de l'axe @@ -837,7 +834,6 @@ Specify radius of circle Spécifiez le rayon du cercle Specify rotation angle Spécifiez l'angle de rotation Specify rotation angle of text Spécifiez l'angle de rotation du texte - Specify rotation angle or Spécifiez l'angle de rotation ou Specify scale factor Spécifiez le facteur d'échelle Specify second angle endpoint Spécifiez le deuxième point final de l'angle Specify second break point Spécifiez le deuxième point de rupture @@ -870,9 +866,9 @@ Specify third source point or Spécifiez le troisième point source ou Specify through point Spécifiez le point de passage Specify top diameter Spécifiez le diamètre supérieur - Specify top radius or Spécifiez le rayon supérieur ou + Specify top radius Spécifiez le rayon supérieur Specify total angle Spécifiez l'angle total - Specify total length or Spécifiez la longueur totale ou + Specify total length Spécifiez la longueur totale Specify width for rectangles Spécifiez la largeur des rectangles Sphere Sphère Spline Spline diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 926ad0e6c..e486f6337 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -350,7 +350,7 @@ Enter a vertex editing option Válassz egy csúcspont-szerkesztési lehetőséget Enter an option Válassz egy lehetőséget Enter angle of xline Add meg a szerkesztővonal szögét - Enter angle of xline (0) or Add meg a szerkesztővonal szögét (0) + Enter angle of xline (0) Add meg a szerkesztővonal szögét (0) Enter area of rectangle in current units Add meg a téglalap területét az aktuális mértékegységben Enter attribute prompt Add meg az attribútum bekérő szövegét Enter attribute tag name Add meg az attribútum címkéjét @@ -361,7 +361,7 @@ Enter default attribute value Add meg az attribútum alapértelmezett értékét Enter degree of spline Add meg a spline fokszámát Enter delta angle Add meg a szögváltozást - Enter delta length or Add meg a hosszváltozást + Enter delta length Add meg a hosszváltozást Enter dimension text Add meg a méretszámot Enter dimension text (<> = measurement) Add meg a méretszámot (<> = mért érték) Enter dimension value or [name=expression] Add meg a méret értékét vagy [név=kifejezés] @@ -931,8 +931,8 @@ Select an arc or circle Válassz egy ívet vagy kört Select an arc. Válassz egy ívet. Select an object Válassz egy objektumot - Select an object to change or Válaszd ki a módosítandó objektumot - Select an object to measure or Válaszd ki a mérendő objektumot + Select an object to change Válaszd ki a módosítandó objektumot + Select an object to measure Válaszd ki a mérendő objektumot Select an object. Válassz egy objektumot. Select an open curve. Válassz egy nyitott görbét. Select an open line, arc, polyline, ellipse arc or spline. Válassz egy nyitott vonalat, ívet, vonalláncot, ellipszisívet vagy spline-t. @@ -946,9 +946,8 @@ Select first line Válaszd ki az első vonalat Select first line or arc Válaszd ki az első vonalat vagy ívet Select first object Válaszd ki az első objektumot - Select first object or Válaszd ki az első objektumot Select first point Válaszd ki az első pontot - Select nested objects to copy or Válaszd ki a másolandó beágyazott objektumokat + Select nested objects to copy Válaszd ki a másolandó beágyazott objektumokat Select object Válassz objektumot Select object to dimension Válaszd ki a méretezendő objektumot Select object to divide Válaszd ki a felosztandó objektumot @@ -965,7 +964,7 @@ Select one polyline (Multiple is available through the JSON form). Egyetlen vonalláncot válassz (a Multiple a parancs JSON-hívásával érhető el). Select path curve Válaszd ki az útvonalgörbét Select point or object Válassz pontot vagy objektumot - Select polyline or Válassz vonalláncot + Select polyline Válassz vonalláncot Select second line Válaszd ki a második vonalat Select second line or shift-select to apply corner Válaszd ki a második vonalat, Shift+kijelöléssel éles sarkot képezhetsz Select second object Válaszd ki a második objektumot @@ -1046,9 +1045,8 @@ Specify axis endpoint of ellipse Add meg az ellipszis tengelyének végpontját Specify base diameter Add meg az alap átmérőjét Specify base point Add meg a bázispontot - Specify base point or Add meg a bázispontot Specify base point or displacement (drag with the middle mouse button for realtime pan) Add meg a bázispontot vagy az elmozdulást (a középső egérgombbal húzva a nézetet valós időben mozgathatod) - Specify base radius or Add meg az alap sugarát + Specify base radius Add meg az alap sugarát Specify center of donut Add meg a gyűrű középpontját Specify center of ellipse Add meg az ellipszis középpontját Specify center of polygon Add meg a sokszög középpontját @@ -1090,7 +1088,7 @@ Specify first point on circle: _tan to Add meg a kör első pontját: _tan to Specify first source point Add meg az első forráspontot Specify height Add meg a magasságot - Specify helix height or Add meg a csavarvonal magasságát + Specify helix height Add meg a csavarvonal magasságát Specify included angle Add meg a középponti szöget Specify insertion base point Add meg a beszúrási bázispontot Specify insertion point Add meg a beszúrási pontot @@ -1109,7 +1107,6 @@ Specify new width for all segments Add meg az összes szakasz új szélességét Specify next point Add meg a következő pontot Specify offset distance Add meg az eltolási távolságot - Specify offset distance or Add meg az eltolási távolságot Specify opposite corner Add meg az átellenes sarkot Specify other corner point Add meg a másik sarokpontot Specify other endpoint of axis Add meg a tengely másik végpontját @@ -1122,7 +1119,6 @@ Specify radius of circle Add meg a kör sugarát Specify rotation angle Add meg az elforgatási szöget Specify rotation angle of text Add meg a szöveg elforgatási szögét - Specify rotation angle or Add meg az elforgatási szöget Specify scale factor Add meg a léptéktényezőt Specify second angle endpoint Add meg a szög második végpontját Specify second break point Add meg a második megszakítási pontot @@ -1155,9 +1151,9 @@ Specify third source point or Add meg a harmadik forráspontot vagy Specify through point Add meg az átmenő pontot Specify top diameter Add meg a felső átmérőt - Specify top radius or Add meg a felső sugarat + Specify top radius Add meg a felső sugarat Specify total angle Add meg a teljes szöget - Specify total length or Add meg a teljes hosszt + Specify total length Add meg a teljes hosszt Specify width for rectangles Add meg a téglalapok szélességét Sphere Gömb Spherical Gömbszerű diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index cec28d857..b437397b6 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -288,7 +288,7 @@ menu Modify Edita Enter a vertex editing option Digitare un'opzione di modifica dei vertici Enter an option Digitare un'opzione Enter angle of xline Digitare l'angolo della linea di costruzione - Enter angle of xline (0) or Digitare l'angolo della linea di costruzione (0) o + Enter angle of xline (0) Digitare l'angolo della linea di costruzione (0) Enter area of rectangle in current units Digitare l'area del rettangolo nelle unità correnti Enter attribute prompt Digitare il messaggio dell'attributo Enter attribute tag name Digitare il nome dell'etichetta dell'attributo @@ -299,7 +299,7 @@ menu Modify Edita Enter default attribute value Digitare il valore predefinito dell'attributo Enter degree of spline Digitare il grado della spline Enter delta angle Digitare la variazione dell'angolo - Enter delta length or Digitare la variazione di lunghezza o + Enter delta length Digitare la variazione di lunghezza Enter dimension text Digitare il testo della quota Enter dimension text (<> = measurement) Digitare il testo della quota (<> = misura) Enter dimension value or [name=expression] Digitare il valore della quota o [nome=espressione] @@ -797,8 +797,8 @@ menu Modify Edita Select an arc or circle Selezionare un arco o un cerchio Select an arc. Selezionare un arco. Select an object Selezionare un oggetto - Select an object to change or Selezionare l'oggetto da modificare o - Select an object to measure or Selezionare l'oggetto da misurare o + Select an object to change Selezionare l'oggetto da modificare + Select an object to measure Selezionare l'oggetto da misurare Select an object. Selezionare un oggetto. Select an open curve. Selezionare una curva aperta. Select an open line, arc, polyline, ellipse arc or spline. Selezionare una linea, un arco, una polilinea, un arco ellittico o una spline aperti. @@ -811,9 +811,8 @@ menu Modify Edita Select first line Selezionare la prima linea Select first line or arc Selezionare la prima linea o il primo arco Select first object Selezionare il primo oggetto - Select first object or Selezionare il primo oggetto o Select first point Selezionare il primo punto - Select nested objects to copy or Selezionare gli oggetti nidificati da copiare o + Select nested objects to copy Selezionare gli oggetti nidificati da copiare Select object Selezionare l'oggetto Select object to dimension Selezionare l'oggetto da quotare Select object to divide Selezionare l'oggetto da dividere @@ -829,7 +828,7 @@ menu Modify Edita Select one polyline (Multiple is available through the JSON form). Selezionare una polilinea (Multiple è disponibile tramite il modulo JSON). Select path curve Selezionare la curva della traiettoria Select point or object Selezionare un punto o un oggetto - Select polyline or Selezionare la polilinea o + Select polyline Selezionare la polilinea Select second line Selezionare la seconda linea Select second line or shift-select to apply corner Selezionare la seconda linea o selezionare con Maiusc per applicare l'angolo Select second object Selezionare il secondo oggetto @@ -889,9 +888,8 @@ menu Modify Edita Specify axis endpoint of ellipse Specificare l'estremo dell'asse dell'ellisse Specify base diameter Specificare il diametro di base Specify base point Specificare il punto base - Specify base point or Specificare il punto base o Specify base point or displacement (drag with the middle mouse button for realtime pan) Specificare il punto base o lo spostamento (trascinare con il tasto centrale del mouse per il pan in tempo reale) - Specify base radius or Specificare il raggio di base o + Specify base radius Specificare il raggio di base Specify center of donut Specificare il centro dell'anello Specify center of ellipse Specificare il centro dell'ellisse Specify center of polygon Specificare il centro del poligono @@ -933,7 +931,7 @@ menu Modify Edita Specify first point on circle: _tan to Specificare il primo punto sul cerchio: _tan a Specify first source point Specificare il primo punto di origine Specify height Specificare l'altezza - Specify helix height or Specificare l'altezza dell'elica o + Specify helix height Specificare l'altezza dell'elica Specify included angle Specificare l'angolo compreso Specify insertion base point Specificare il punto base di inserimento Specify insertion point Specificare il punto di inserimento @@ -987,7 +985,6 @@ menu Modify Edita Specify new width for all segments Specificare la nuova larghezza di tutti i segmenti Specify next point Specificare il punto successivo Specify offset distance Specificare la distanza di offset - Specify offset distance or Specificare la distanza di offset o Specify opposite corner Specificare l'angolo opposto Specify other corner point Specificare l'altro angolo Specify other endpoint of axis Specificare l'altro estremo dell'asse @@ -1000,7 +997,6 @@ menu Modify Edita Specify radius of circle Specificare il raggio del cerchio Specify rotation angle Specificare l'angolo di rotazione Specify rotation angle of text Specificare l'angolo di rotazione del testo - Specify rotation angle or Specificare l'angolo di rotazione o Specify scale factor Specificare il fattore di scala Specify second angle endpoint Specificare il secondo estremo dell'angolo Specify second break point Specificare il secondo punto di interruzione @@ -1033,9 +1029,9 @@ menu Modify Edita Specify third source point or Specificare il terzo punto di origine o Specify through point Specificare il punto di passaggio Specify top diameter Specificare il diametro superiore - Specify top radius or Specificare il raggio superiore o + Specify top radius Specificare il raggio superiore Specify total angle Specificare l'angolo totale - Specify total length or Specificare la lunghezza totale o + Specify total length Specificare la lunghezza totale Specify width for rectangles Specificare la larghezza dei rettangoli Sphere Sfera Spline Spline diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index f41128ba1..2f269b051 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -281,7 +281,7 @@ Enter a vertex editing option 정점 편집 옵션 입력 Enter an option 옵션 입력 Enter angle of xline 구성선 각도 입력 - Enter angle of xline (0) or 구성선 각도 입력(0) 또는 + Enter angle of xline (0) 구성선 각도 입력(0) Enter area of rectangle in current units 현재 단위로 직사각형 면적 입력 Enter attribute prompt 속성 프롬프트 입력 Enter attribute tag name 속성 태그 이름 입력 @@ -292,7 +292,7 @@ Enter default attribute value 기본 속성 값 입력 Enter degree of spline 스플라인 차수 입력 Enter delta angle 각도 변화량 입력 - Enter delta length or 길이 변화량 입력 또는 + Enter delta length 길이 변화량 입력 Enter dimension text 치수 문자 입력 Enter dimension text (<> = measurement) 치수 문자 입력(<> = 측정값) Enter dimension value or [name=expression] 치수 값 또는 [name=expression] 입력 @@ -788,8 +788,8 @@ Select an arc or circle 호 또는 원 선택 Select an arc. 호를 선택하세요. Select an object 객체 선택 - Select an object to change or 변경할 객체 선택 또는 - Select an object to measure or 측정할 객체 선택 또는 + Select an object to change 변경할 객체 선택 + Select an object to measure 측정할 객체 선택 Select an object. 객체를 선택하세요. Select an open curve. 열린 곡선을 선택하세요. Select an open line, arc, polyline, ellipse arc or spline. 열린 선, 호, 폴리선, 타원 호 또는 스플라인을 선택하세요. @@ -803,9 +803,8 @@ Select first line 첫 번째 선 선택 Select first line or arc 첫 번째 선 또는 호 선택 Select first object 첫 번째 객체 선택 - Select first object or 첫 번째 객체 선택 또는 Select first point 첫 번째 점 선택 - Select nested objects to copy or 복사할 내포된 객체 선택 또는 + Select nested objects to copy 복사할 내포된 객체 선택 Select object 객체 선택 Select object to dimension 치수를 기입할 객체 선택 Select object to divide 등분할할 객체 선택 @@ -821,7 +820,7 @@ Select one polyline (Multiple is available through the JSON form). 폴리선 하나를 선택하세요(다중 선택은 JSON 형식으로 사용할 수 있습니다). Select path curve 경로 곡선 선택 Select point or object 점 또는 객체 선택 - Select polyline or 폴리선 선택 또는 + Select polyline 폴리선 선택 Select second line 두 번째 선 선택 Select second line or shift-select to apply corner 두 번째 선 선택 또는 Shift를 누른 채 선택하여 각진 모서리 적용 Select second object 두 번째 객체 선택 @@ -881,9 +880,8 @@ Specify axis endpoint of ellipse 타원 축 끝점 지정 Specify base diameter 밑면 지름 지정 Specify base point 기준점 지정 - Specify base point or 기준점 지정 또는 Specify base point or displacement (drag with the middle mouse button for realtime pan) 기준점 또는 변위 지정(마우스 가운데 버튼으로 드래그하여 실시간 초점 이동) - Specify base radius or 밑면 반지름 지정 또는 + Specify base radius 밑면 반지름 지정 Specify center of donut 도넛 중심 지정 Specify center of ellipse 타원 중심 지정 Specify center of polygon 다각형 중심 지정 @@ -925,7 +923,7 @@ Specify first point on circle: _tan to 원 위의 첫 번째 점 지정: _tan 접점 Specify first source point 첫 번째 원본점 지정 Specify height 높이 지정 - Specify helix height or 나선 높이 지정 또는 + Specify helix height 나선 높이 지정 Specify included angle 사이각 지정 Specify insertion base point 삽입 기준점 지정 Specify insertion point 삽입점 지정 @@ -979,7 +977,6 @@ Specify new width for all segments 모든 구간의 새 폭 지정 Specify next point 다음 점 지정 Specify offset distance 간격띄우기 거리 지정 - Specify offset distance or 간격띄우기 거리 지정 또는 Specify opposite corner 반대 구석 지정 Specify other corner point 다른 구석점 지정 Specify other endpoint of axis 축의 다른 끝점 지정 @@ -992,7 +989,6 @@ Specify radius of circle 원 반지름 지정 Specify rotation angle 회전 각도 지정 Specify rotation angle of text 문자 회전 각도 지정 - Specify rotation angle or 회전 각도 지정 또는 Specify scale factor 축척 비율 지정 Specify second angle endpoint 두 번째 각도 끝점 지정 Specify second break point 두 번째 끊기점 지정 @@ -1025,9 +1021,9 @@ Specify third source point or 세 번째 원본점 지정 또는 <계속> Specify through point 통과점 지정 Specify top diameter 윗면 지름 지정 - Specify top radius or 윗면 반지름 지정 또는 + Specify top radius 윗면 반지름 지정 Specify total angle 전체 각도 지정 - Specify total length or 전체 길이 지정 또는 + Specify total length 전체 길이 지정 Specify width for rectangles 직사각형 폭 지정 Sphere 구 Spline 스플라인 diff --git a/crates/ui-egui/src/i18n/pt_br.tsv b/crates/ui-egui/src/i18n/pt_br.tsv index 3e16b65cf..3d8f03449 100644 --- a/crates/ui-egui/src/i18n/pt_br.tsv +++ b/crates/ui-egui/src/i18n/pt_br.tsv @@ -291,7 +291,7 @@ Enter a vertex editing option Digite uma opção de edição de vértice Enter an option Digite uma opção Enter angle of xline Digite o ângulo da linha infinita - Enter angle of xline (0) or Digite o ângulo da linha infinita (0) ou + Enter angle of xline (0) Digite o ângulo da linha infinita (0) Enter area of rectangle in current units Digite a área do retângulo nas unidades atuais Enter attribute prompt Digite o texto de solicitação do atributo Enter attribute tag name Digite o nome do rótulo do atributo @@ -302,7 +302,7 @@ Enter default attribute value Digite o valor padrão do atributo Enter degree of spline Digite o grau da spline Enter delta angle Digite o ângulo delta - Enter delta length or Digite o comprimento delta ou + Enter delta length Digite o comprimento delta Enter dimension text Digite o texto da cota Enter dimension text (<> = measurement) Digite o texto da cota (<> = medida) Enter dimension value or [name=expression] Digite o valor da cota ou [nome=expressão] @@ -880,8 +880,8 @@ Select an arc or circle Selecione um arco ou círculo Select an arc. Selecione um arco. Select an object Selecione um objeto - Select an object to change or Selecione um objeto para alterar ou - Select an object to measure or Selecione um objeto para medir ou + Select an object to change Selecione um objeto para alterar + Select an object to measure Selecione um objeto para medir Select an object. Selecione um objeto. Select an open curve. Selecione uma curva aberta. Select an open line, arc, polyline, ellipse arc or spline. Selecione uma linha aberta, arco, polilinha, arco elíptico ou spline. @@ -895,9 +895,8 @@ Select first line Selecione a primeira linha Select first line or arc Selecione a primeira linha ou arco Select first object Selecione o primeiro objeto - Select first object or Selecione o primeiro objeto ou Select first point Selecione o primeiro ponto - Select nested objects to copy or Selecione objetos aninhados para copiar ou + Select nested objects to copy Selecione objetos aninhados para copiar Select object Selecione o objeto Select object to dimension Selecione o objeto a cotar Select object to divide Selecione o objeto a dividir @@ -913,7 +912,7 @@ Select one polyline (Multiple is available through the JSON form). Selecione uma polilinha (a opção Multiple está disponível pela forma JSON). Select path curve Selecione a curva da trajetória Select point or object Selecione um ponto ou objeto - Select polyline or Selecione uma polilinha ou + Select polyline Selecione uma polilinha Select second line Selecione a segunda linha Select second line or shift-select to apply corner Selecione a segunda linha ou use Shift para aplicar o canto Select second object Selecione o segundo objeto @@ -966,9 +965,8 @@ Specify axis endpoint of ellipse Especifique a extremidade do eixo da elipse Specify base diameter Especifique o diâmetro da base Specify base point Especifique o ponto base - Specify base point or Especifique o ponto base ou Specify base point or displacement (drag with the middle mouse button for realtime pan) Especifique o ponto base ou o deslocamento (arraste com o botão do meio do mouse para pan em tempo real) - Specify base radius or Especifique o raio da base ou + Specify base radius Especifique o raio da base Specify center of donut Especifique o centro do anel Specify center of ellipse Especifique o centro da elipse Specify center of polygon Especifique o centro do polígono @@ -1010,7 +1008,7 @@ Specify first point on circle: _tan to Especifique o primeiro ponto no círculo: _tan para Specify first source point Especifique o primeiro ponto de origem Specify height Especifique a altura - Specify helix height or Especifique a altura da hélice ou + Specify helix height Especifique a altura da hélice Specify included angle Especifique o ângulo incluído Specify insertion base point Especifique o ponto base de inserção Specify insertion point Especifique o ponto de inserção @@ -1029,7 +1027,6 @@ Specify new width for all segments Especifique a nova largura para todos os segmentos Specify next point Especifique o próximo ponto Specify offset distance Especifique a distância de offset - Specify offset distance or Especifique a distância de offset ou Specify opposite corner Especifique o canto oposto Specify other corner point Especifique o outro ponto de canto Specify other endpoint of axis Especifique a outra extremidade do eixo @@ -1042,7 +1039,6 @@ Specify radius of circle Especifique o raio do círculo Specify rotation angle Especifique o ângulo de rotação Specify rotation angle of text Especifique o ângulo de rotação do texto - Specify rotation angle or Especifique o ângulo de rotação ou Specify scale factor Especifique o fator de escala Specify second angle endpoint Especifique a segunda extremidade do ângulo Specify second break point Especifique o segundo ponto de quebra @@ -1075,9 +1071,9 @@ Specify third source point or Especifique o terceiro ponto de origem ou Specify through point Especifique o ponto de passagem Specify top diameter Especifique o diâmetro superior - Specify top radius or Especifique o raio superior ou + Specify top radius Especifique o raio superior Specify total angle Especifique o ângulo total - Specify total length or Especifique o comprimento total ou + Specify total length Especifique o comprimento total Specify width for rectangles Especifique a largura para retângulos Sphere Esfera Spline Spline @@ -1257,3 +1253,200 @@ Check for Updates… Verificar atualizações… CADCraft is up to date. O CADCraft está atualizado. Could not check for updates. Não foi possível verificar atualizações. +# Strings the sibling catalogs translate that pt-BR did not yet cover (translated 2026-10-31). + Add: Pick points Adicionar: indicar pontos + Add: Select objects Adicionar: selecionar objetos + Add… Adicionar… + Alias Alias + Alias file: {file} Arquivo de aliases: {file} + Align Multileaders Alinhar multilinhas + Analyze Usage Analisar uso + Angstroms Angströms + Apply to Layout Aplicar à apresentação + Architectural Arquitetônico + Arrow size Tamanho da seta + Associate Associar + Associative Associativo + Astronomical Units Unidades astronômicas + AutoLISP (LSP) AutoLISP (LSP) + Backup copy Cópia de backup + Block to create or edit Bloco a criar ou editar + Bottom left Inferior esquerdo + Bottom right Inferior direito + Boundaries Contornos + Boundaries picked: {n} Contornos selecionados: {n} + Break-line Symbol Símbolo de linha de quebra + built-in integrado + Center the plot Centralizar a plotagem + Centered Centralizado + Centimeters Centímetros + Change Properties Alterar propriedades + Choose the command the alias starts. Escolha o comando que o alias inicia. + Clear Recent Files Limpar arquivos recentes + Click the ruler to add a tab stop, right-click to remove one Clique na régua para adicionar uma parada de tabulação; clique com o botão direito para remover + Click to set new origin Clique para definir a nova origem + Close Block Editor Fechar o editor de blocos + Collect Coletar + Collect Multileaders Coletar multilinhas + Color 1 Cor 1 + Color 2 Cor 2 + Command Comando + contains authoring elements. Open in Block Editor? contém elementos de autoria. Abrir no editor de blocos? + Convert Text to Mtext Converter texto em Mtexto + Create backup copy with each save Criar cópia de backup a cada salvamento + Create separate hatches Criar hachuras separadas + Crossing selection color: Cor da seleção por cruzamento: + Curved Curvo + Custom Personalizado + Customize Personalizar + Decameters Decâmetros + Decimal Decimal + Decimal Degrees Graus decimais + Decimeters Decímetros + Default to boundary extents Padrão para a extensão do contorno + Deg/Min/Sec Gra/Min/Seg + Dim scale overall Escala geral de cotas + Discard Descartar + Don't Save Não salvar + Drag Dynamic Grip Arrastar pinça dinâmica + Drawing Units Unidades do desenho + Dynamic Block Data Dados de bloco dinâmico + Dynamic Block Grips Pinças de bloco dinâmico + Dynamic Block Reference Referência de bloco dinâmico + Edit Block Definition Editar definição de bloco + Edit Command Aliases (PGP)... Editar aliases de comandos (PGP)... + Edit Multileader Editar multilinha + Edit… Editar… + Engineering Engenharia + Enter block names to extract Insira os nomes dos blocos a extrair + Enter geometric characteristic Insira a característica geométrica + Enter name of LISP file to load Insira o nome do arquivo LISP a carregar + Evaluate LISP Avaliar LISP + Exclude: Excluir: + Explode Attributes to Text Explodir atributos em texto + Express Tools Ferramentas Express + Feet Pés + First corner Primeiro canto + Fit to paper Ajustar ao papel + Font Fonte + Fractional Fracionário + Gigameters Gigâmetros + Grads Grados + Grips Pinças + Groups Grupos + Hatch and Gradient Hachura e gradiente + Hatch origin Origem da hachura + Hatch Pick Seleção de hachura + Hatches Hachuras + Hectometers Hectômetros + Hemispherical Hemisférico + Ignore Ignorar + Imperial (inches) Imperial (polegadas) + Implied Loops Laços implícitos + Inches Polegadas + Indicate selection area Indicar área de seleção + Insertion scale Escala de inserção + Interface scale Escala da interface + Inverted Invertido + Island Ilha + Island detection Detecção de ilhas + Italic Itálico + Justify Justificar + Kilometers Quilômetros + Landscape Paisagem + Layouts Apresentações + Light Years Anos-luz + Limits Limites + Load Application... Carregar aplicativo... + Meters Metros + Metric (millimetres) Métrico (milímetros) + Microinches Micropolegadas + Microns Mícrons + Miles Milhas + Millimeters Milímetros + Mils Mils + More than {n} aliases. Mais de {n} aliases. + Move/Copy/Rotate Mover/Copiar/Girar + Multiline text Texto multilinha + Nanometers Nanômetros + New and the first drawing at startup use these units unless a default template is set (QNEWTEMPLATE). Novos desenhos e o primeiro desenho na inicialização usam estas unidades, a menos que um modelo padrão esteja definido (QNEWTEMPLATE). + New block Novo bloco + No alias file loaded. REINIT replaces these aliases with a file's. Nenhum arquivo de aliases carregado. O REINIT substitui estes aliases pelos de um arquivo. + Object grouping Agrupamento de objetos + Object selection limit for display of grips Limite de seleção de objetos para exibir pinças + Objects on locked layers Objetos em camadas bloqueadas + Open in Block Editor Abrir no editor de blocos + Open Recent Abrir recentes + Opposite corner Canto oposto + Orientation Orientação + Origin: {x}, {y} Origem: {x}, {y} + Outer Externo + Overline Sobrelinha + overrides built-in substitui o integrado + Paper size Tamanho do papel + Parsecs Parsecs + Plot area Área de plotagem + Plot object lineweights Plotar espessuras de linha dos objetos + Plot offset Deslocamento da plotagem + Plot transparency Plotar transparência + Portrait Retrato + Precision Precisão + Preview Visualizar + Printer/plotter Impressora/plotter + Radians Radianos + Sample output Amostra de saída + Save alias Salvar alias + Save Block Salvar bloco + Save Block As Salvar bloco como + Save changes to block "{name}"? Salvar alterações no bloco "{name}"? + Save changes to {name}? Salvar alterações em {name}? + Save Layout as Template Salvar apresentação como modelo + Scientific Científico + Select boundaries to remove Selecione contornos para remover + Selection Area Effect Efeito da área de seleção + Selection area opacity: Opacidade da área de seleção: + Selection effect color Cor do efeito de seleção + Selection modes Modos de seleção + Selection preview Visualização da seleção + Selection Preview Filter Filtro de visualização da seleção + Set Dynamic Property Definir propriedade dinâmica + Shape Forma + Sheet Books to PDF... Livros de folhas em PDF... + Show grips Mostrar pinças + Specified origin Origem especificada + Spherical Esférico + Surveyor's Units Unidades de topografia + Tables Tabelas + Text color Cor do texto + This drawing Este desenho + Top left Superior esquerdo + Top right Superior direito + Type an alias name. Digite um nome de alias. + Underline Sublinhado + Unitless Adimensional + Units of new drawings Unidades de novos desenhos + Units to scale inserted content Unidades para dimensionar conteúdo inserido + Unsaved changes Alterações não salvas + US Survey Feet Pés topográficos norte-americanos + US Survey Inch Polegada topográfica norte-americana + US Survey Mile Milha topográfica norte-americana + US Survey Yard Jarda topográfica norte-americana + Use current origin Usar origem atual + Visual Effect Settings Configurações de efeitos visuais + Visual Effect Settings... Configurações de efeitos visuais... + When a command is active Quando um comando está ativo + When no command is active Quando nenhum comando está ativo + Window < Janela < + Window selection color: Cor da seleção por janela: + X offset (mm) Deslocamento X (mm) + Xrefs Referências externas + Y offset (mm) Deslocamento Y (mm) + Yards Jardas + Your changes will be lost if you don't save them. Suas alterações serão perdidas se você não salvá-las. + {alias} is already defined; select it and use Edit. {alias} já está definido; selecione-o e use Editar. + {command} is an unknown command. {command} é um comando desconhecido. +# Strings the sibling catalogs translate that pt-BR did not yet cover (translated 2026-10-31). +menu Dimension Cota +menu Draw Desenho +menu Modify Modificar +menu View Exibir diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 7e4ba21d5..619988f45 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -221,7 +221,7 @@ Enter a vertex editing option Введите параметр редактирования вершины Enter an option Введите параметр Enter angle of xline Введите угол вспомогательной прямой - Enter angle of xline (0) or Введите угол вспомогательной прямой (0) или + Enter angle of xline (0) Введите угол вспомогательной прямой (0) Enter area of rectangle in current units Введите площадь прямоугольника в текущих единицах Enter attribute prompt Введите подсказку атрибута Enter attribute tag name Введите имя тега атрибута @@ -232,7 +232,7 @@ Enter default attribute value Введите значение атрибута по умолчанию Enter degree of spline Введите степень сплайна Enter delta angle Введите изменение угла - Enter delta length or Введите изменение длины или + Enter delta length Введите изменение длины Enter dimension text Введите размерный текст Enter dimension text (<> = measurement) Введите размерный текст (<> = измеренное значение) Enter dimension value or [name=expression] Введите размерное значение или [имя=выражение] @@ -675,8 +675,8 @@ Select an arc or circle Выберите дугу или круг Select an arc. Выберите дугу. Select an object Выберите объект - Select an object to change or Выберите объект для изменения или - Select an object to measure or Выберите объект для измерения или + Select an object to change Выберите объект для изменения + Select an object to measure Выберите объект для измерения Select an object. Выберите объект. Select an open curve. Выберите незамкнутую кривую. Select an open line, arc, polyline, ellipse arc or spline. Выберите незамкнутый отрезок, дугу, полилинию, эллиптическую дугу или сплайн. @@ -690,9 +690,8 @@ Select first line Выберите первый отрезок Select first line or arc Выберите первый отрезок или дугу Select first object Выберите первый объект - Select first object or Выберите первый объект или Select first point Выберите первую точку - Select nested objects to copy or Выберите вложенные объекты для копирования или + Select nested objects to copy Выберите вложенные объекты для копирования Select object Выберите объект Select object to dimension Выберите объект для нанесения размера Select object to divide Выберите объект для деления @@ -708,7 +707,7 @@ Select one polyline (Multiple is available through the JSON form). Выберите одну полилинию (Multiple доступно через JSON). Select path curve Выберите кривую траектории Select point or object Выберите точку или объект - Select polyline or Выберите полилинию или + Select polyline Выберите полилинию Select second line Выберите второй отрезок Select second line or shift-select to apply corner Выберите второй отрезок или выберите с Shift, чтобы построить угол Select second object Выберите второй объект @@ -761,9 +760,8 @@ Specify axis endpoint of ellipse Укажите конечную точку оси эллипса Specify base diameter Укажите базовый диаметр Specify base point Укажите базовую точку - Specify base point or Укажите базовую точку или Specify base point or displacement (drag with the middle mouse button for realtime pan) Укажите базовую точку или смещение (перетаскивайте средней кнопкой мыши для панорамирования) - Specify base radius or Укажите базовый радиус или + Specify base radius Укажите базовый радиус Specify center of donut Укажите центр кольца Specify center of ellipse Укажите центр эллипса Specify center of polygon Укажите центр многоугольника @@ -805,7 +803,7 @@ Specify first point on circle: _tan to Укажите первую точку на круге: _tan к Specify first source point Укажите первую исходную точку Specify height Укажите высоту - Specify helix height or Укажите высоту спирали или + Specify helix height Укажите высоту спирали Specify included angle Укажите угол между сторонами Specify insertion base point Укажите базовую точку вставки Specify insertion point Укажите точку вставки @@ -824,7 +822,6 @@ Specify new width for all segments Укажите новую ширину всех сегментов Specify next point Укажите следующую точку Specify offset distance Укажите расстояние смещения - Specify offset distance or Укажите расстояние смещения или Specify opposite corner Укажите противоположный угол Specify other corner point Укажите другую угловую точку Specify other endpoint of axis Укажите другую конечную точку оси @@ -837,7 +834,6 @@ Specify radius of circle Укажите радиус круга Specify rotation angle Укажите угол поворота Specify rotation angle of text Укажите угол поворота текста - Specify rotation angle or Укажите угол поворота или Specify scale factor Укажите масштабный коэффициент Specify second angle endpoint Укажите вторую конечную точку угла Specify second break point Укажите вторую точку разрыва @@ -870,9 +866,9 @@ Specify third source point or Укажите третью исходную точку или <продолжить> Specify through point Укажите точку, через которую проходит прямая Specify top diameter Укажите диаметр вершины - Specify top radius or Укажите радиус вершины или + Specify top radius Укажите радиус вершины Specify total angle Укажите полный угол - Specify total length or Укажите общую длину или + Specify total length Укажите общую длину Specify width for rectangles Укажите ширину прямоугольников Sphere Сфера Spline Сплайн diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 96114f857..ecfe35b40 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -295,7 +295,7 @@ Enter a vertex editing option Ange ett alternativ för hörnpunktsredigering Enter an option Ange ett alternativ Enter angle of xline Ange konstruktionslinjens vinkel - Enter angle of xline (0) or Ange konstruktionslinjens vinkel (0) eller + Enter angle of xline (0) Ange konstruktionslinjens vinkel (0) Enter area of rectangle in current units Ange rektangelns area i aktuella enheter Enter attribute prompt Ange attributets fråga Enter attribute tag name Ange attributets taggnamn @@ -306,7 +306,7 @@ Enter default attribute value Ange attributets standardvärde Enter degree of spline Ange splinens grad Enter delta angle Ange vinkeländring - Enter delta length or Ange längdändring eller + Enter delta length Ange längdändring Enter dimension text Ange måttal Enter dimension text (<> = measurement) Ange måttal (<> = mätvärde) Enter dimension value or [name=expression] Ange måttvärde eller [namn=uttryck] @@ -878,8 +878,8 @@ Select an arc or circle Markera en båge eller cirkel Select an arc. Markera en båge. Select an object Markera ett objekt - Select an object to change or Markera ett objekt att ändra eller - Select an object to measure or Markera ett objekt att mäta eller + Select an object to change Markera ett objekt att ändra + Select an object to measure Markera ett objekt att mäta Select an object. Markera ett objekt. Select an open curve. Markera en öppen kurva. Select an open line, arc, polyline, ellipse arc or spline. Markera en öppen linje, båge, polylinje, ellipsbåge eller spline. @@ -893,9 +893,8 @@ Select first line Markera första linjen Select first line or arc Markera första linjen eller bågen Select first object Markera första objektet - Select first object or Markera första objektet eller Select first point Ange första punkten - Select nested objects to copy or Markera nästlade objekt att kopiera eller + Select nested objects to copy Markera nästlade objekt att kopiera Select object Markera objekt Select object to dimension Markera objekt att måttsätta Select object to divide Markera objekt att dela in @@ -911,7 +910,7 @@ Select one polyline (Multiple is available through the JSON form). Markera en polylinje (Multiple finns i JSON-formen). Select path curve Markera banans kurva Select point or object Ange punkt eller markera objekt - Select polyline or Markera polylinje eller + Select polyline Markera polylinje Select second line Markera andra linjen Select second line or shift-select to apply corner Markera andra linjen, eller Shift-markera för att skapa hörn Select second object Markera andra objektet @@ -964,9 +963,8 @@ Specify axis endpoint of ellipse Ange ellipsens axeländpunkt Specify base diameter Ange basdiameter Specify base point Ange baspunkt - Specify base point or Ange baspunkt eller Specify base point or displacement (drag with the middle mouse button for realtime pan) Ange baspunkt eller förskjutning (dra med mittenknappen för att panorera i realtid) - Specify base radius or Ange basradie eller + Specify base radius Ange basradie Specify center of donut Ange ringens centrum Specify center of ellipse Ange ellipsens centrum Specify center of polygon Ange polygonens centrum @@ -1008,7 +1006,7 @@ Specify first point on circle: _tan to Ange första punkten på cirkeln: _tan to Specify first source point Ange första källpunkten Specify height Ange höjd - Specify helix height or Ange helixens höjd eller + Specify helix height Ange helixens höjd Specify included angle Ange medelpunktsvinkel Specify insertion base point Ange insättningens baspunkt Specify insertion point Ange insättningspunkt @@ -1027,7 +1025,6 @@ Specify new width for all segments Ange ny bredd för alla segment Specify next point Ange nästa punkt Specify offset distance Ange förskjutningsavstånd - Specify offset distance or Ange förskjutningsavstånd eller Specify opposite corner Ange motsatt hörn Specify other corner point Ange andra hörnpunkten Specify other endpoint of axis Ange axelns andra ändpunkt @@ -1040,7 +1037,6 @@ Specify radius of circle Ange cirkelns radie Specify rotation angle Ange rotationsvinkel Specify rotation angle of text Ange textens rotationsvinkel - Specify rotation angle or Ange rotationsvinkel eller Specify scale factor Ange skalfaktor Specify second angle endpoint Ange vinkelns andra ändpunkt Specify second break point Ange andra brytpunkten @@ -1073,9 +1069,9 @@ Specify third source point or Ange tredje källpunkten eller Specify through point Ange genomgångspunkt Specify top diameter Ange toppdiameter - Specify top radius or Ange toppradie eller + Specify top radius Ange toppradie Specify total angle Ange total vinkel - Specify total length or Ange total längd eller + Specify total length Ange total längd Specify width for rectangles Ange bredd för rektanglar Sphere Sfär Spline Spline diff --git a/crates/ui-egui/src/i18n/tests.rs b/crates/ui-egui/src/i18n/tests.rs index 034f261e1..24fac6a79 100644 --- a/crates/ui-egui/src/i18n/tests.rs +++ b/crates/ui-egui/src/i18n/tests.rs @@ -40,6 +40,17 @@ fn catalog_is_valid_and_preserves_placeholders_and_ellipses() { assert_eq!(tr("unknown", "Open"), "Open"); } +/// A prompt with options is translated without its own "or": the command line adds the +/// translated " or [" before the options ("Select polyline or [Multiple]"). +#[test] +fn prompts_with_options_leave_or_to_the_command_line() { + assert_eq!(format!("{}{}", tr("de", "Select polyline"), tr("de", " or [")), "Wählen Sie eine Polylinie oder ["); + assert_eq!(format!("{}{}", tr("ko", "Specify helix height"), tr("ko", " or [")), "나선 높이 지정 또는 ["); + assert_eq!(format!("{}{}", tr("zh", "Enter delta length"), tr("zh", " or [")), "输入增量长度 或 ["); + assert_eq!(format!("{}{}", tr("vi", "Select polyline"), tr("vi", " or [")), "Chọn polyline hoặc ["); + assert_eq!(format!("{}{}", tr("vi", "Specify base radius"), tr("vi", " or [")), "Chỉ định bán kính đáy hoặc ["); +} + /// What each language shows in English for now. Missing translations never fail a build: /// `cargo xtask i18n`, a step of `cargo xtask ci`, runs this to print the list. #[test] @@ -357,6 +368,35 @@ fn render(app: &mut CadApp, ctx: &egui::Context) -> String { text } +/// The command line in the window draws a prompt's keywords itself; it puts the same words before +/// them as the engine's prompt text: " [" after a prompt for an option ("Enter an option [?/Make/…") +/// and after a question ("Fix any errors detected? [Yes/No]"), " or [" where the keywords are +/// offered besides what is asked ("Specify next point or [Undo]"), " or [" translated. +#[test] +fn the_command_line_says_or_before_keywords_as_the_prompt_does() { + let ctx = egui::Context::default(); + for lang in ["en", "de"] { + let mut app = CadApp::new(Session::new(), Services::default()); + app.run("ui.language", json!({ "lang": lang })).unwrap(); + app.logic(&ctx); + app.session.cmdline("-layer").unwrap(); + let text = render(&mut app, &ctx); + let option = format!("\n{}\n [\n", tr(lang, "Enter an option")); + assert!(text.contains(&option), "{lang}: {option:?} in {text:?}"); + app.session.cancel(); + app.session.cmdline("line").unwrap(); + app.session.cmdline("0,0").unwrap(); + let text = render(&mut app, &ctx); + let besides = format!("\n{}\n{}\n", tr(lang, "Specify next point"), tr(lang, " or [")); + assert!(text.contains(&besides), "{lang}: {besides:?} in {text:?}"); + app.session.cancel(); + app.session.cmdline("audit").unwrap(); + let text = render(&mut app, &ctx); + let question = format!("\n{}\n [\n", tr(lang, "Fix any errors detected?")); + assert!(text.contains(&question), "{lang}: {question:?} in {text:?}"); + } +} + #[test] fn live_switch_translates_the_shell_without_mutating_drawing_or_automation() { let mut app = CadApp::new(Session::new(), Services::default()); diff --git a/crates/ui-egui/src/i18n/tr.tsv b/crates/ui-egui/src/i18n/tr.tsv index 3fed6bc3b..cc8576aa7 100644 --- a/crates/ui-egui/src/i18n/tr.tsv +++ b/crates/ui-egui/src/i18n/tr.tsv @@ -351,7 +351,7 @@ Enter a vertex editing option Bir köşe noktası düzenleme seçeneği girin Enter an option Bir seçenek girin Enter angle of xline Yapı çizgisinin açısını girin - Enter angle of xline (0) or Yapı çizgisinin açısını girin (0) veya + Enter angle of xline (0) Yapı çizgisinin açısını girin (0) Enter area of rectangle in current units Dikdörtgenin alanını geçerli birimlerle girin Enter attribute prompt Öznitelik istemini girin Enter attribute tag name Öznitelik etiket adını girin @@ -362,7 +362,7 @@ Enter default attribute value Varsayılan öznitelik değerini girin Enter degree of spline Spline derecesini girin Enter delta angle Açı farkını girin - Enter delta length or Uzunluk farkını girin veya + Enter delta length Uzunluk farkını girin Enter dimension text Ölçü metnini girin Enter dimension text (<> = measurement) Ölçü metnini girin (<> = ölçülen değer) Enter dimension value or [name=expression] Ölçü değerini girin veya [name=expression] @@ -932,8 +932,8 @@ Select an arc or circle Bir yay veya daire seçin Select an arc. Bir yay seçin. Select an object Bir nesne seçin - Select an object to change or Değiştirilecek nesneyi seçin veya - Select an object to measure or Ölçülecek nesneyi seçin veya + Select an object to change Değiştirilecek nesneyi seçin + Select an object to measure Ölçülecek nesneyi seçin Select an object. Bir nesne seçin. Select an open curve. Açık bir eğri seçin. Select an open line, arc, polyline, ellipse arc or spline. Açık bir çizgi, yay, çoklu çizgi, elips yayı veya spline seçin. @@ -947,9 +947,8 @@ Select first line İlk çizgiyi seçin Select first line or arc İlk çizgiyi veya yayı seçin Select first object İlk nesneyi seçin - Select first object or İlk nesneyi seçin veya Select first point İlk noktayı seçin - Select nested objects to copy or Kopyalanacak iç içe nesneleri seçin veya + Select nested objects to copy Kopyalanacak iç içe nesneleri seçin Select object Nesne seçin Select object to dimension Ölçülendirilecek nesneyi seçin Select object to divide Bölünecek nesneyi seçin @@ -966,7 +965,7 @@ Select one polyline (Multiple is available through the JSON form). Bir çoklu çizgi seçin (Multiple seçeneği JSON biçimiyle kullanılabilir). Select path curve Yol eğrisini seçin Select point or object Nokta veya nesne seçin - Select polyline or Çoklu çizgi seçin veya + Select polyline Çoklu çizgi seçin Select second line İkinci çizgiyi seçin Select second line or shift-select to apply corner İkinci çizgiyi seçin ya da köşe uygulamak için Shift ile seçin Select second object İkinci nesneyi seçin @@ -1047,9 +1046,8 @@ Specify axis endpoint of ellipse Elipsin eksen uç noktasını belirtin Specify base diameter Taban çapını belirtin Specify base point Taban noktasını belirtin - Specify base point or Taban noktasını belirtin veya Specify base point or displacement (drag with the middle mouse button for realtime pan) Taban noktasını veya yer değiştirmeyi belirtin (gerçek zamanlı kaydırma için orta fare düğmesiyle sürükleyin) - Specify base radius or Taban yarıçapını belirtin veya + Specify base radius Taban yarıçapını belirtin Specify center of donut Halkanın merkezini belirtin Specify center of ellipse Elipsin merkezini belirtin Specify center of polygon Çokgenin merkezini belirtin @@ -1091,7 +1089,7 @@ Specify first point on circle: _tan to Daire üzerindeki ilk noktayı belirtin: _tan to Specify first source point İlk kaynak noktayı belirtin Specify height Yüksekliği belirtin - Specify helix height or Helezon yüksekliğini belirtin veya + Specify helix height Helezon yüksekliğini belirtin Specify included angle İç açıyı belirtin Specify insertion base point Ekleme taban noktasını belirtin Specify insertion point Ekleme noktasını belirtin @@ -1110,7 +1108,6 @@ Specify new width for all segments Tüm parçalar için yeni genişliği belirtin Specify next point Sonraki noktayı belirtin Specify offset distance Öteleme uzaklığını belirtin - Specify offset distance or Öteleme uzaklığını belirtin veya Specify opposite corner Karşı köşeyi belirtin Specify other corner point Diğer köşe noktasını belirtin Specify other endpoint of axis Eksenin diğer uç noktasını belirtin @@ -1123,7 +1120,6 @@ Specify radius of circle Dairenin yarıçapını belirtin Specify rotation angle Döndürme açısını belirtin Specify rotation angle of text Metnin döndürme açısını belirtin - Specify rotation angle or Döndürme açısını belirtin veya Specify scale factor Ölçek faktörünü belirtin Specify second angle endpoint Açının ikinci uç noktasını belirtin Specify second break point İkinci kırma noktasını belirtin @@ -1156,9 +1152,9 @@ Specify third source point or Üçüncü kaynak noktayı belirtin veya Specify through point Geçiş noktasını belirtin Specify top diameter Üst çapı belirtin - Specify top radius or Üst yarıçapı belirtin veya + Specify top radius Üst yarıçapı belirtin Specify total angle Toplam açıyı belirtin - Specify total length or Toplam uzunluğu belirtin veya + Specify total length Toplam uzunluğu belirtin Specify width for rectangles Dikdörtgenler için genişliği belirtin Sphere Küre Spherical Küresel diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index bbb70e489..8d8c6b875 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -286,7 +286,7 @@ Enter a vertex editing option Введіть параметр редагування вершини Enter an option Введіть параметр Enter angle of xline Введіть кут допоміжної прямої - Enter angle of xline (0) or Введіть кут допоміжної прямої (0) або + Enter angle of xline (0) Введіть кут допоміжної прямої (0) Enter area of rectangle in current units Введіть площу прямокутника в поточних одиницях Enter attribute prompt Введіть підказку атрибута Enter attribute tag name Введіть ім'я тегу атрибута @@ -297,7 +297,7 @@ Enter default attribute value Введіть типове значення атрибута Enter degree of spline Введіть степінь сплайна Enter delta angle Введіть зміну кута - Enter delta length or Введіть зміну довжини або + Enter delta length Введіть зміну довжини Enter dimension text Введіть розмірний текст Enter dimension text (<> = measurement) Введіть розмірний текст (<> = виміряне значення) Enter dimension value or [name=expression] Введіть розмірне значення або [name=expression] @@ -803,8 +803,8 @@ Select an arc or circle Виберіть дугу або коло Select an arc. Виберіть дугу. Select an object Виберіть об'єкт - Select an object to change or Виберіть об'єкт для зміни або - Select an object to measure or Виберіть об'єкт для вимірювання або + Select an object to change Виберіть об'єкт для зміни + Select an object to measure Виберіть об'єкт для вимірювання Select an object. Виберіть об'єкт. Select an open curve. Виберіть незамкнену криву. Select an open line, arc, polyline, ellipse arc or spline. Виберіть незамкнений відрізок, дугу, полілінію, еліптичну дугу або сплайн. @@ -818,9 +818,8 @@ Select first line Виберіть перший відрізок Select first line or arc Виберіть перший відрізок або дугу Select first object Виберіть перший об'єкт - Select first object or Виберіть перший об'єкт або Select first point Виберіть першу точку - Select nested objects to copy or Виберіть вкладені об'єкти для копіювання або + Select nested objects to copy Виберіть вкладені об'єкти для копіювання Select object Виберіть об'єкт Select object to dimension Виберіть об'єкт для нанесення розміру Select object to divide Виберіть об'єкт для поділу @@ -841,7 +840,7 @@ Select one polyline (Multiple is available through the JSON form). Виберіть одну полілінію (Multiple доступно через JSON). Select path curve Виберіть криву траєкторії Select point or object Виберіть точку або об'єкт - Select polyline or Виберіть полілінію або + Select polyline Виберіть полілінію Select second line Виберіть другий відрізок Select second line or shift-select to apply corner Виберіть другий відрізок або виберіть із Shift, щоб утворити кут Select second object Виберіть другий об'єкт @@ -901,9 +900,8 @@ Specify axis endpoint of ellipse Укажіть кінцеву точку осі еліпса Specify base diameter Укажіть діаметр основи Specify base point Укажіть базову точку - Specify base point or Укажіть базову точку або Specify base point or displacement (drag with the middle mouse button for realtime pan) Укажіть базову точку або зміщення (перетягуйте середньою кнопкою миші для панорамування) - Specify base radius or Укажіть радіус основи або + Specify base radius Укажіть радіус основи Specify center of donut Укажіть центр кільця Specify center of ellipse Укажіть центр еліпса Specify center of polygon Укажіть центр багатокутника @@ -945,7 +943,7 @@ Specify first point on circle: _tan to Укажіть першу точку на колі: _tan до Specify first source point Укажіть першу вихідну точку Specify height Укажіть висоту - Specify helix height or Укажіть висоту спіралі або + Specify helix height Укажіть висоту спіралі Specify included angle Укажіть кут між сторонами Specify insertion base point Укажіть базову точку вставлення Specify insertion point Укажіть точку вставлення @@ -1029,7 +1027,6 @@ Specify new width for all segments Укажіть нову ширину всіх сегментів Specify next point Укажіть наступну точку Specify offset distance Укажіть відстань зміщення - Specify offset distance or Укажіть відстань зміщення або Specify opposite corner Укажіть протилежний кут Specify other corner point Укажіть іншу кутову точку Specify other endpoint of axis Укажіть іншу кінцеву точку осі @@ -1042,7 +1039,6 @@ Specify radius of circle Укажіть радіус кола Specify rotation angle Укажіть кут повороту Specify rotation angle of text Укажіть кут повороту тексту - Specify rotation angle or Укажіть кут повороту або Specify scale factor Укажіть коефіцієнт масштабу Specify second angle endpoint Укажіть другу кінцеву точку кута Specify second break point Укажіть другу точку розриву @@ -1075,9 +1071,9 @@ Specify third source point or Укажіть третю вихідну точку або <продовжити> Specify through point Укажіть точку, через яку проходить пряма Specify top diameter Укажіть діаметр вершини - Specify top radius or Укажіть радіус вершини або + Specify top radius Укажіть радіус вершини Specify total angle Укажіть загальний кут - Specify total length or Укажіть загальну довжину або + Specify total length Укажіть загальну довжину Specify width for rectangles Укажіть ширину прямокутників Sphere Сфера Spline Сплайн diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 8887bb45b..f1b8dca7b 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -280,7 +280,7 @@ Enter a vertex editing option Nhập tùy chọn sửa đỉnh Enter an option Nhập một tùy chọn Enter angle of xline Nhập góc của đường dựng - Enter angle of xline (0) or Nhập góc của đường dựng (0) hoặc + Enter angle of xline (0) Nhập góc của đường dựng (0) Enter area of rectangle in current units Nhập diện tích hình chữ nhật theo đơn vị hiện hành Enter attribute prompt Nhập lời nhắc attribute Enter attribute tag name Nhập tên thẻ attribute @@ -291,7 +291,7 @@ Enter default attribute value Nhập giá trị attribute mặc định Enter degree of spline Nhập bậc của spline Enter delta angle Nhập góc chênh lệch - Enter delta length or Nhập chiều dài chênh lệch hoặc + Enter delta length Nhập chiều dài chênh lệch Enter dimension text Nhập chữ kích thước Enter dimension text (<> = measurement) Nhập chữ kích thước (<> = số đo) Enter dimension value or [name=expression] Nhập giá trị kích thước hoặc [name=expression] @@ -787,8 +787,8 @@ Select an arc or circle Chọn một cung tròn hoặc đường tròn Select an arc. Chọn một cung tròn. Select an object Chọn một đối tượng - Select an object to change or Chọn một đối tượng để thay đổi hoặc - Select an object to measure or Chọn một đối tượng để đo hoặc + Select an object to change Chọn một đối tượng để thay đổi + Select an object to measure Chọn một đối tượng để đo Select an object. Chọn một đối tượng. Select an open curve. Chọn một đường cong hở. Select an open line, arc, polyline, ellipse arc or spline. Chọn một đoạn thẳng, cung tròn, polyline, cung elip hoặc spline hở. @@ -802,14 +802,13 @@ Select first line Chọn đoạn thẳng thứ nhất Select first line or arc Chọn đoạn thẳng hoặc cung tròn thứ nhất Select first object Chọn đối tượng thứ nhất - Select first object or Chọn đối tượng thứ nhất hoặc Select first point Chọn điểm thứ nhất Add to Working Set Thêm vào Working Set Edit Reference In-Place Chỉnh sửa tham chiếu tại chỗ Save Reference Edits Lưu chỉnh sửa tham chiếu Working Set Working Set Xref and Block In-place Editing Chỉnh sửa Xref và Block tại chỗ - Select nested objects to copy or Chọn đối tượng lồng nhau để sao chép hoặc + Select nested objects to copy Chọn đối tượng lồng nhau để sao chép Select object Chọn đối tượng Select object to dimension Chọn đối tượng để ghi kích thước Select object to divide Chọn đối tượng để chia @@ -825,7 +824,7 @@ Select one polyline (Multiple is available through the JSON form). Chọn một polyline (có thể chọn nhiều qua dạng JSON). Select path curve Chọn đường cong làm đường dẫn Select point or object Chọn điểm hoặc đối tượng - Select polyline or Chọn polyline hoặc + Select polyline Chọn polyline Select second line Chọn đoạn thẳng thứ hai Select second line or shift-select to apply corner Chọn đoạn thẳng thứ hai hoặc chọn kèm Shift để áp dụng góc Select second object Chọn đối tượng thứ hai @@ -883,9 +882,8 @@ Specify axis endpoint of ellipse Chỉ định điểm cuối trục của elip Specify base diameter Chỉ định đường kính đáy Specify base point Chỉ định điểm gốc - Specify base point or Chỉ định điểm gốc hoặc Specify base point or displacement (drag with the middle mouse button for realtime pan) Chỉ định điểm gốc hoặc độ dời (kéo bằng nút giữa chuột để pan theo thời gian thực) - Specify base radius or Chỉ định bán kính đáy hoặc + Specify base radius Chỉ định bán kính đáy Specify center of donut Chỉ định tâm vành tròn Specify center of ellipse Chỉ định tâm elip Specify center of polygon Chỉ định tâm đa giác @@ -927,7 +925,7 @@ Specify first point on circle: _tan to Chỉ định điểm thứ nhất trên đường tròn: _tan to Specify first source point Chỉ định điểm nguồn thứ nhất Specify height Chỉ định chiều cao - Specify helix height or Chỉ định chiều cao đường xoắn ốc hoặc + Specify helix height Chỉ định chiều cao đường xoắn ốc Specify included angle Chỉ định góc chắn của cung Specify insertion base point Chỉ định điểm gốc chèn Specify insertion point Chỉ định điểm chèn @@ -981,7 +979,6 @@ Specify new width for all segments Chỉ định bề rộng mới cho tất cả các đoạn Specify next point Chỉ định điểm tiếp theo Specify offset distance Chỉ định khoảng cách offset - Specify offset distance or Chỉ định khoảng cách offset hoặc Specify opposite corner Chỉ định góc đối diện Specify other corner point Chỉ định điểm góc đối diện Specify other endpoint of axis Chỉ định đầu kia của trục @@ -994,7 +991,6 @@ Specify radius of circle Chỉ định bán kính đường tròn Specify rotation angle Chỉ định góc xoay Specify rotation angle of text Chỉ định góc xoay của chữ - Specify rotation angle or Chỉ định góc xoay hoặc Specify scale factor Chỉ định hệ số tỉ lệ Specify second angle endpoint Chỉ định đầu thứ hai của góc Specify second break point Chỉ định điểm ngắt thứ hai @@ -1027,9 +1023,9 @@ Specify third source point or Chỉ định điểm nguồn thứ ba hoặc Specify through point Chỉ định điểm đi qua Specify top diameter Chỉ định đường kính trên - Specify top radius or Chỉ định bán kính trên hoặc + Specify top radius Chỉ định bán kính trên Specify total angle Chỉ định tổng góc - Specify total length or Chỉ định tổng chiều dài hoặc + Specify total length Chỉ định tổng chiều dài Specify width for rectangles Chỉ định bề rộng cho hình chữ nhật Sphere Hình cầu Spline Spline diff --git a/crates/ui-egui/src/i18n/zh.tsv b/crates/ui-egui/src/i18n/zh.tsv index 9ca85fea7..de4e6a633 100644 --- a/crates/ui-egui/src/i18n/zh.tsv +++ b/crates/ui-egui/src/i18n/zh.tsv @@ -222,7 +222,7 @@ Enter a vertex editing option 输入顶点编辑选项 Enter an option 输入选项 Enter angle of xline 输入构造线角度 - Enter angle of xline (0) or 输入构造线角度 (0) 或 + Enter angle of xline (0) 输入构造线角度 (0) Enter area of rectangle in current units 在当前单位中输入矩形面积 Enter attribute prompt 输入属性提示 Enter attribute tag name 输入属性标记名称 @@ -233,7 +233,7 @@ Enter default attribute value 输入默认属性值 Enter degree of spline 输入样条曲线次数 Enter delta angle 输入增量角度 - Enter delta length or 输入增量长度或 + Enter delta length 输入增量长度 Enter dimension text 输入标注文字 Enter dimension text (<> = measurement) 输入标注文字 (<> = 测量值) Enter dimension value or [name=expression] 输入标注值或 [名称=表达式] @@ -669,8 +669,8 @@ Select an arc or circle 选择圆弧或圆 Select an arc. 选择一段圆弧。 Select an object 选择对象 - Select an object to change or Select an object to change or - Select an object to measure or Select an object to measure or + Select an object to change Select an object to change + Select an object to measure Select an object to measure Add to Working Set 添加到工作集 Edit Reference In-Place 就地编辑参照 Save Reference Edits 保存参照编辑 @@ -689,9 +689,8 @@ Select first line 选择第一条直线 Select first line or arc 选择第一条直线或圆弧 Select first object 选择第一个对象 - Select first object or Select first object or Select first point 指定第一点 - Select nested objects to copy or Select nested objects to copy or + Select nested objects to copy Select nested objects to copy Select object 选择对象 Select object to dimension 选择要标注的对象 Select object to divide 选择要定数等分的对象 @@ -707,7 +706,7 @@ Select one polyline (Multiple is available through the JSON form). 选择一条多段线(可通过 JSON 表单选择多个)。 Select path curve 选择路径曲线 Select point or object 选择点或对象 - Select polyline or 选择多段线或 + Select polyline 选择多段线 Select second line 选择第二条直线 Select second line or shift-select to apply corner 选择第二条直线,或按 Shift 键应用角点 Select second object 选择第二个对象 @@ -760,9 +759,8 @@ Specify axis endpoint of ellipse 指定椭圆的轴端点 Specify base diameter 指定底面直径 Specify base point 指定基点 - Specify base point or Specify base point or Specify base point or displacement (drag with the middle mouse button for realtime pan) 指定基点或位移(按住鼠标中键拖动以进行实时平移) - Specify base radius or Specify base radius or + Specify base radius Specify base radius Specify center of donut 指定圆环中心 Specify center of ellipse 指定椭圆中心 Specify center of polygon 指定多边形中心 @@ -804,7 +802,7 @@ Specify first point on circle: _tan to 指定圆上的第一点: _tan 到 Specify first source point 指定第一个源点 Specify height 指定高度 - Specify helix height or Specify helix height or + Specify helix height Specify helix height Specify included angle 指定夹角 Specify insertion base point 指定插入基点 Specify insertion point 指定插入点 @@ -823,7 +821,6 @@ Specify new width for all segments 指定所有段的新宽度 Specify next point 指定下一点 Specify offset distance 指定偏移距离 - Specify offset distance or Specify offset distance or Specify opposite corner 指定对角点 Specify other corner point 指定另一角点 Specify other endpoint of axis 指定轴的另一端点 @@ -836,7 +833,6 @@ Specify radius of circle 指定圆半径 Specify rotation angle 指定旋转角度 Specify rotation angle of text 指定文字旋转角度 - Specify rotation angle or Specify rotation angle or Specify scale factor 指定比例因子 Specify second angle endpoint 指定第二角度端点 Specify second break point 指定第二打断点 @@ -869,9 +865,9 @@ Specify third source point or 指定第三个源点或 <继续> Specify through point 指定通过点 Specify top diameter 指定顶面直径 - Specify top radius or Specify top radius or + Specify top radius Specify top radius Specify total angle 指定总角度 - Specify total length or Specify total length or + Specify total length Specify total length Specify width for rectangles 指定矩形宽度 Sphere 球体 Spline 样条曲线 diff --git a/docs/localization.md b/docs/localization.md index 909fad9f8..998fbe0a0 100644 --- a/docs/localization.md +++ b/docs/localization.md @@ -46,8 +46,8 @@ The translations are original, AI-assisted Korean CAD terminology (for example, 치수, 모깎기, 모따기, 간격띄우기 and 객체 스냅). Independent native proofreading and platform-specific layout/IME validation remain follow-up work. -Brazilian Portuguese has 1,231 catalog rows and also covers the reference catalog and every marked UI -literal: commands, menus, tool groups and tooltips, object snaps, drafting prompts, dialogs and +Brazilian Portuguese has 1,447 catalog rows and also covers the reference catalog, every marked UI +literal and the strings the sibling catalogs translate: commands, menus, tool groups and tooltips, object snaps, drafting prompts, dialogs and Preferences; its gaps are now zero. Its plural rule is `one|other` (0 and 1 are `one`), as CLDR defines for `pt`, and the catalog's accented letters (`Á Â Í Ó Ú à á â ã ç é ê í ó ô õ ú`) render in the bundled fonts. The original catalog was contributed by @WladmirJunior; the remaining rows were completed