feat(locale): localize full interface

This commit is contained in:
Hakan Seven 2026-08-02 22:09:25 +03:00
commit 3e6693b93f
205 changed files with 32367 additions and 3808 deletions

View file

@ -224,10 +224,10 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
let raw = crate::app::expr_eval::eval_to_string(self.command_line.input.trim());
self.command_line.input.clear();
let Ok(v) = raw.parse::<f64>() else {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"{}: expected a number, got \"{raw}\"",
pending.label
));
).as_ref());
return Task::none();
};
let i = self.active_tab;
@ -443,9 +443,9 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
return self.apply_cmd_result(result);
}
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Expected coordinates (x,y) or a number, got: \"{text}\""
));
).as_ref());
return self.focus_cmd_input();
}
if let Some(cmd) = self.command_line.submit() {
@ -519,7 +519,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
}
// Esc cancels a pending system-variable value prompt.
if self.pending_setvar.take().is_some() {
self.command_line.push_info("*Cancel*");
self.command_line.push_info(crate::t!("*Cancel*").as_ref());
return Task::none();
}
// UCS icon: Esc ends any grip drag and clears the selection
@ -548,7 +548,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
sel.middle_down = false;
sel.middle_last_pos = None;
}
self.command_line.push_output("PAN ended.");
self.command_line.push_output(crate::t!("PAN ended.").as_ref());
return Task::none();
}
// Grip popup intercepts Escape — dismisses the menu
@ -738,7 +738,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
names.retain(|n| n != "0" && *n != current);
if names.len() < before {
self.command_line
.push_info("Layer \"0\" and the current layer can't be deleted — skipped.");
.push_info(crate::t!("Layer \"0\" and the current layer can't be deleted — skipped.").as_ref());
}
if names.is_empty() {
return Task::none();
@ -971,7 +971,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
action: item.action,
label,
});
self.command_line.push_info(&format!("{label}:"));
self.command_line.push_info(crate::tf!("{label}:").as_ref());
return self.focus_cmd_input();
}
// Break at vertex replaces the entity with the split pieces —
@ -993,11 +993,11 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
self.tabs[i].dirty = true;
self.refresh_selected_grips();
self.refresh_properties();
self.command_line.push_output("Polyline broken at vertex.");
self.command_line.push_output(crate::t!("Polyline broken at vertex.").as_ref());
}
None => self
.command_line
.push_error("Cannot break at this vertex."),
.push_error(crate::t!("Cannot break at this vertex.").as_ref()),
}
return Task::none();
}
@ -1042,7 +1042,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
self.tabs[i].dirty = dirty_before;
self.refresh_selected_grips();
self.refresh_properties();
self.command_line.push_error("Cannot add a vertex here.");
self.command_line.push_error(crate::t!("Cannot add a vertex here.").as_ref());
return Task::none();
}
self.tabs[i]
@ -1069,7 +1069,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
grip_world,
));
self.command_line
.push_info("Specify new vertex location:");
.push_info(crate::t!("Specify new vertex location:").as_ref());
} else {
if let Some(entity) =
self.tabs[i].scene.document.get_entity_mut(popup.handle)
@ -1083,7 +1083,7 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
self.refresh_selected_grips();
self.refresh_properties();
self.command_line
.push_error("Cannot place the new vertex.");
.push_error(crate::t!("Cannot place the new vertex.").as_ref());
}
return Task::none();
}
@ -2084,9 +2084,9 @@ pub(super) fn on_tab_close(&mut self, idx: usize) -> Task<Message> {
// The block's layer may have been locked while the editor was open —
// refuse to write attributes to a locked-layer block.
if let Some(layer) = self.tabs[i].scene.locked_layer_name(handle) {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Object is on locked layer \"{layer}\" — unlock the layer to edit its attributes."
));
).as_ref());
return Task::none();
}
// Snapshot the working copy so the document can be mutated while the

View file

@ -116,7 +116,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
if self.tabs[self.active_tab].is_start && !matches!(event, ModuleEvent::Command(_)) {
self.ribbon.close_dropdown();
self.command_line
.push_info("No drawing open — use New or Open first.");
.push_info(crate::t!("No drawing open — use New or Open first.").as_ref());
return Task::none();
}
// Dismiss any open dropdown / collapsed-panel flyout on tool use,
@ -141,13 +141,13 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
}
ModuleEvent::OpenFileDialog => {
self.command_line
.push_info("Open DWG/DXF: not yet implemented.");
.push_info(crate::t!("Open DWG/DXF: not yet implemented.").as_ref());
}
ModuleEvent::ClearModels => {
let i = self.active_tab;
self.tabs[i].scene.clear();
self.tabs[i].properties = PropertiesPanel::empty();
self.command_line.push_output("Scene cleared.");
self.command_line.push_output(crate::t!("Scene cleared.").as_ref());
}
ModuleEvent::SetWireframe(w) => {
let i = self.active_tab;
@ -265,7 +265,7 @@ pub(super) fn on_ribbon_tool_click(&mut self, tool_id: String, event: ModuleEven
if self.active_save_jobs.contains_key(&self.tabs[idx].id) {
self.command_line
.push_info("Save already running for this drawing.");
.push_info(crate::t!("Save already running for this drawing.").as_ref());
return Task::none();
}

View file

@ -659,7 +659,10 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
.is_some_and(|(loaded, current)| loaded != current)
{
self.command_line.push_error_once(
"Drawing changed on disk while it was opening; Save will require conflict resolution.",
crate::t!(
"Drawing changed on disk while it was opening; Save will require conflict resolution."
)
.as_ref(),
);
}
self.tabs[i].disk_fingerprint =
@ -667,9 +670,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
match crate::io::edit_lock::EditLease::acquire(path) {
Ok(lease) => {
if let Some(warning) = lease.platform_warning() {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Edit lease active; {warning}. External-change checks remain active."
));
).as_ref());
}
self.tabs[i].edit_lease = Some(lease);
self.tabs[i].edit_lock_conflict = false;
@ -677,16 +680,16 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
Err(crate::io::edit_lock::EditLeaseError::Locked(error)) => {
self.tabs[i].edit_lease = None;
self.tabs[i].edit_lock_conflict = true;
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Opened read-only against other editors: {error}"
));
).as_ref());
}
Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => {
self.tabs[i].edit_lease = None;
self.tabs[i].edit_lock_conflict = false;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
}
}
}
@ -718,22 +721,22 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
Some(Ok(warning)) => {
self.tabs[i].edit_lock_conflict = false;
if let Some(warning) = warning {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{warning}. External-change checks remain active."
));
).as_ref());
}
}
Some(Err(crate::io::edit_lock::EditLeaseError::Locked(error))) => {
self.tabs[i].edit_lock_conflict = true;
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Saved, but the refreshed drawing is locked by another editor: {error}"
));
).as_ref());
}
Some(Err(crate::io::edit_lock::EditLeaseError::Unavailable(error))) => {
self.tabs[i].edit_lock_conflict = false;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
}
None => self.install_native_edit_guard(i, path, None),
}
@ -765,9 +768,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
return Err(crate::io::SaveFailure::file_in_use(error));
}
Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
None
}
}
@ -829,9 +832,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
let warning = lease.platform_warning().map(str::to_owned);
self.tabs[i].edit_lock_conflict = false;
if let Some(warning) = warning {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{warning}. External-change checks remain active."
));
).as_ref());
}
return Ok(());
}
@ -840,9 +843,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
}
Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => {
self.tabs[i].edit_lock_conflict = false;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
return Ok(());
}
}
@ -854,18 +857,18 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.tabs[i].edit_lease = Some(lease);
self.tabs[i].edit_lock_conflict = false;
if let Some(warning) = warning {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{warning}. External-change checks remain active."
));
).as_ref());
}
Ok(())
}
Err(crate::io::edit_lock::EditLeaseError::Locked(error)) => Err(error),
Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => {
self.tabs[i].edit_lock_conflict = false;
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
Ok(())
}
}
@ -883,34 +886,34 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
let timings = caches.timings;
let entity_count = doc.entities().count();
self.command_line
.push_output(&format!("Opened \"{name}\" — {entity_count} entities"));
.push_output(crate::tf!("Opened \"{name}\" — {entity_count} entities").as_ref());
if caches.corrupt_dropped > 0 {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Warning: {} corrupt entities dropped (parser junk — bad normals / counts)",
caches.corrupt_dropped
));
).as_ref());
}
if caches.xref_dropped > 0 {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Warning: {} corrupt xref entities dropped",
caches.xref_dropped
));
).as_ref());
}
for info in &caches.xrefs {
match info.status {
crate::io::xref::XrefStatus::Loaded => {
self.command_line
.push_output(&format!("XREF Loaded \"{}\"", info.name));
.push_output(crate::tf!("XREF Loaded \"{}\"", info.name).as_ref());
}
crate::io::xref::XrefStatus::NotFound => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"XREF Not found: \"{}\" ({})",
info.name, info.path
));
).as_ref());
}
crate::io::xref::XrefStatus::Unloaded => {
self.command_line
.push_info(&format!("XREF Unloaded (skipped): \"{}\"", info.name));
.push_info(crate::tf!("XREF Unloaded (skipped): \"{}\"", info.name).as_ref());
}
}
}
@ -982,10 +985,10 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
let total_ms = open_started
.map(|s| s.elapsed().as_millis() as u32)
.unwrap_or(0);
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
" parse {}ms · purge {}ms · caches {}ms · xref {}ms · total {}ms",
timings.parse_ms, timings.purge_ms, timings.caches_ms, timings.xref_ms, total_ms
));
).as_ref());
// Caches were built on the background thread inside open_path().
self.tabs[i].scene.local_extent_max = caches.local_extent_max;
@ -1209,7 +1212,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
if self.active_save_jobs.contains_key(&tab_id) {
if purpose != crate::app::SavePurpose::Autosave {
self.command_line
.push_info("Save already running for this drawing.");
.push_info(crate::t!("Save already running for this drawing.").as_ref());
}
return Task::none();
}
@ -1218,12 +1221,12 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
&& self.tabs[i].edit_lock_conflict
{
let error = "Drawing edit lock is held by another editor.".to_string();
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Unable to save \"{}\": {error}",
path.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| path.display().to_string())
));
).as_ref());
self.pending_save_failure = Some(crate::app::PendingSaveFailure {
tab_id,
path,
@ -1248,12 +1251,12 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.pending_save_leases.insert(tab_id, lease);
}
Err(crate::io::edit_lock::EditLeaseError::Locked(error)) => {
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Unable to save \"{}\": {error}",
path.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| path.display().to_string())
));
).as_ref());
self.pending_save_failure = Some(crate::app::PendingSaveFailure {
tab_id,
path,
@ -1268,9 +1271,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
return Task::none();
}
Err(crate::io::edit_lock::EditLeaseError::Unavailable(error)) => {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{error}. External-change checks remain active."
));
).as_ref());
}
}
}
@ -1424,9 +1427,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| outcome.path.display().to_string());
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Save stopped: \"{file_name}\" changed outside Open CAD Studio."
));
).as_ref());
self.pending_external_change = Some(crate::app::PendingExternalChange {
tab_id: outcome.tab_id,
path: outcome.path.clone(),
@ -1445,9 +1448,9 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
.file_name()
.map(|name| name.to_string_lossy().into_owned())
.unwrap_or_else(|| outcome.path.display().to_string());
self.command_line.push_error_once(&format!(
self.command_line.push_error_once(crate::tf!(
"Unable to save \"{file_name}\": file is in use by another application."
));
).as_ref());
self.pending_save_failure = Some(crate::app::PendingSaveFailure {
tab_id: outcome.tab_id,
path: outcome.path.clone(),
@ -1470,7 +1473,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
return Task::none();
}
self.command_line
.push_error(&format!("Save failed: {error}"));
.push_error(crate::tf!("Save failed: {error}").as_ref());
return match outcome.continuation {
crate::app::SaveContinuation::CloseTab => {
self.pending_close = Some(crate::app::PendingClose::Tab(i));
@ -1496,7 +1499,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
let mut tasks = Vec::new();
match outcome.purpose {
crate::app::SavePurpose::Autosave => {
self.command_line.push_output("Autosaved 1 drawing");
self.command_line.push_output(crate::t!("Autosaved 1 drawing").as_ref());
}
crate::app::SavePurpose::Manual | crate::app::SavePurpose::SaveAs => {
let path_changed = outcome.set_current_path
@ -1507,7 +1510,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
!native_paths_match(current, &outcome.path)
});
self.command_line
.push_output(&format!("Saved: {}", outcome.path.display()));
.push_output(crate::tf!("Saved: {}", outcome.path.display()).as_ref());
self.recent_thumbs.remove(&outcome.path);
if let Some(previous) = outcome.previous_autosave {
if previous != outcome.path {
@ -1594,7 +1597,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.pending_save_failure = Some(failure);
self.restore_failed_save_continuation(continuation, i);
self.command_line
.push_error_once(&format!("Unable to acquire edit lock: {error}"));
.push_error_once(crate::tf!("Unable to acquire edit lock: {error}").as_ref());
self.active_modal = Some(crate::app::ModalKind::FileInUse);
return Task::none();
}
@ -1690,7 +1693,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
Err(error) => {
self.close_active_modal();
self.command_line
.push_error(&format!("Reload failed: {error}"));
.push_error(crate::tf!("Reload failed: {error}").as_ref());
return Task::none();
}
};
@ -1709,7 +1712,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
pub(super) fn on_save_file(&mut self) -> Task<Message> {
if self.read_only {
self.command_line
.push_error("Read-only session (--read-only): saving is disabled.");
.push_error(crate::t!("Read-only session (--read-only): saving is disabled.").as_ref());
return Task::none();
}
let i = self.active_tab;
@ -1859,11 +1862,11 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
},
Message::WebRecentStored,
);
self.command_line.push_output(&format!("Saved: {filename}"));
self.command_line.push_output(crate::tf!("Saved: {filename}").as_ref());
true
}
Err(e) => {
self.command_line.push_error(&format!("Save failed: {e}"));
self.command_line.push_error(crate::tf!("Save failed: {e}").as_ref());
false
}
};
@ -2163,10 +2166,10 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.tabs[i].dirty = true;
self.tabs[i].scene.bump_geometry_no_blocks();
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Page setup: {w:.1}×{h:.1} mm area={plot_area} \
center={center} rot={rotation}°"
));
).as_ref());
}
}
@ -2178,7 +2181,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.direct_plot_params()
else {
self.command_line
.push_error("Nothing to plot: model space contains no printable geometry.");
.push_error(crate::t!("Nothing to plot: model space contains no printable geometry.").as_ref());
return Task::none();
};
let plot_style = self.dialog_plot_style(&self.plot_dialog);
@ -2221,7 +2224,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
job
else {
self.command_line
.push_error("Plot area is empty. Pick a larger window.");
.push_error(crate::t!("Plot area is empty. Pick a larger window.").as_ref());
return Task::none();
};
let plot_style = self.dialog_plot_style(&self.plot_dialog);
@ -2533,12 +2536,12 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
self.direct_plot_params()
else {
self.command_line
.push_error("Nothing to plot: model space contains no printable geometry.");
.push_error(crate::t!("Nothing to plot: model space contains no printable geometry.").as_ref());
return Task::none();
};
let plot_style = self.dialog_plot_style(&self.plot_dialog);
let options = self.plot_print_options(&self.plot_dialog, group_splits);
self.command_line.push_info("Sending to system printer…");
self.command_line.push_info(crate::t!("Sending to system printer…").as_ref());
background_task(
move || {
iced::futures::executor::block_on(
@ -2561,7 +2564,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
let i = self.active_tab;
if self.tabs[i].scene.current_layout != "Model" {
self.command_line
.push_error("Quick print works in model space.");
.push_error(crate::t!("Quick print works in model space.").as_ref());
return Task::none();
}
let set: std::collections::HashSet<acadrust::Handle> = handles.into_iter().collect();
@ -2593,12 +2596,12 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
};
if !any {
self.command_line
.push_error("Selection has no printable geometry.");
.push_error(crate::t!("Selection has no printable geometry.").as_ref());
return Task::none();
}
if !(x1 > x0 && y1 > y0) {
self.command_line
.push_error("Selection has no printable area.");
.push_error(crate::t!("Selection has no printable area.").as_ref());
return Task::none();
}
// Small margin so the outermost strokes aren't clipped flush to the edge.
@ -2786,7 +2789,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
match crate::io::print_to_printer::open_printer_properties(
self.plot_dialog.printer.as_deref(),
) {
Ok(()) => self.command_line.push_info("Opened printer properties."),
Ok(()) => self.command_line.push_info(crate::t!("Opened printer properties.").as_ref()),
Err(error) => self.command_line.push_error(&error),
}
Task::none()
@ -2924,7 +2927,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
}
M::SetCurrent => {
self.apply_dialog_to_layout();
self.command_line.push_info("Page setup applied to the layout.");
self.command_line.push_info(crate::t!("Page setup applied to the layout.").as_ref());
Task::none()
}
M::NewSetup => {
@ -3327,10 +3330,10 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
fn on_plot_dlg_commit(&mut self, preview: bool) -> Task<Message> {
let d = self.plot_dialog.clone();
if d.style_missing {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Plot style table '{}' is not loaded.",
d.style_name
));
).as_ref());
return Task::none();
}
// Remember the user's print preferences across sessions.
@ -3365,7 +3368,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
)) = job
else {
self.command_line
.push_error("Plot area is empty. Pick a larger window.");
.push_error(crate::t!("Plot area is empty. Pick a larger window.").as_ref());
self.active_modal = Some(crate::app::ModalKind::Plot);
return Task::none();
};
@ -3436,7 +3439,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
}
let opts = self.plot_print_options(&d, group_splits);
self.command_line.push_info("Sending to system printer…");
self.command_line.push_info(crate::t!("Sending to system printer…").as_ref());
let work = move || {
iced::futures::executor::block_on(
crate::io::print_to_printer::print_wires_with(
@ -3692,7 +3695,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
entry.screening = sc.min(100);
}
self.command_line
.push_output(&format!("Plot style ACI {aci} updated."));
.push_output(crate::tf!("Plot style ACI {aci} updated.").as_ref());
}
} else {
// No table loaded: create an identity table and apply.
@ -3714,7 +3717,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
}
self.active_plot_style = Some(table);
self.command_line
.push_output(&format!("Created new CTB table, ACI {aci} updated."));
.push_output(crate::tf!("Created new CTB table, ACI {aci} updated.").as_ref());
}
Task::none()
}
@ -3722,7 +3725,7 @@ pub(super) fn on_open_file(&mut self) -> Task<Message> {
pub(super) fn on_plot_style_panel_save(&mut self) -> Task<Message> {
if self.active_plot_style.is_none() {
self.command_line
.push_error("No plot style table loaded. Load or create one first.");
.push_error(crate::t!("No plot style table loaded. Load or create one first.").as_ref());
return Task::none();
}
let default_name = self

View file

@ -284,7 +284,7 @@ impl OpenCADStudio {
Err(e) => {
crate::scene::text::web_font::insert(script, None);
self.command_line
.push_error(&format!("Font load failed ({script:?}): {e}"));
.push_error(crate::tf!("Font load failed ({script:?}): {e}").as_ref());
}
}
Task::none()
@ -323,10 +323,10 @@ impl OpenCADStudio {
return match std::fs::metadata(&path) {
Ok(m) => self.update(Message::OpenPathPicked(Some((path, m.len())))),
Err(_) => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Recent file no longer exists: {}",
path.display()
));
).as_ref());
Task::none()
}
};
@ -489,7 +489,7 @@ impl OpenCADStudio {
.map(|(_, _, l)| *l)
.unwrap_or("Snap");
self.command_line
.push_info(&format!("Snap override: {label} (next pick only)."));
.push_info(crate::tf!("Snap override: {label} (next pick only).").as_ref());
Task::none()
}
@ -507,10 +507,10 @@ impl OpenCADStudio {
.map(|e| e.to_string_lossy().to_lowercase())
.unwrap_or_default();
if !matches!(ext.as_str(), "dwg" | "dxf" | "bak" | "sv$") {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Unsupported file type: {}",
path.display()
));
).as_ref());
return Task::none();
}
// Already open → switch to its tab; a load in progress →
@ -563,7 +563,7 @@ impl OpenCADStudio {
});
let size_label = format_size(size_bytes);
self.command_line
.push_info(&format!("Opening \"{name}\" ({size_label})…"));
.push_info(crate::tf!("Opening \"{name}\" ({size_label})…").as_ref());
let model_bg = self.default_bg_color.unwrap_or([
33.0 / 255.0,
40.0 / 255.0,
@ -579,7 +579,7 @@ impl OpenCADStudio {
Message::OpenCancel => {
if let Some(p) = self.opening.take() {
self.command_line
.push_info(&format!("Open cancelled: \"{}\"", p.name));
.push_info(crate::tf!("Open cancelled: \"{}\"", p.name).as_ref());
}
self.drain_pending_open()
}
@ -593,7 +593,7 @@ impl OpenCADStudio {
// we suppress the noise.
let was_open = self.opening.take().is_some();
if was_open && e != "Cancelled" {
self.command_line.push_error(&format!("Open failed: {e}"));
self.command_line.push_error(crate::tf!("Open failed: {e}").as_ref());
}
// A drawing that fails to parse must not strand the ones queued
// behind it.
@ -604,9 +604,9 @@ impl OpenCADStudio {
Message::WebRecentStored(result) => match result {
Ok(path) => self.push_recent(path),
Err(error) => {
self.command_line.push_error(&format!(
self.command_line.push_error(crate::tf!(
"Saved download, but recent copy could not be stored: {error}"
));
).as_ref());
Task::none()
}
},
@ -625,7 +625,7 @@ impl OpenCADStudio {
.unwrap_or(&path_str)
.to_string();
self.command_line
.push_output(&format!("IMAGE \"{short}\": {pw}×{ph} px"));
.push_output(crate::tf!("IMAGE \"{short}\": {pw}×{ph} px").as_ref());
let cmd = ImageCommand::new(path_str, pw, ph);
let i = self.active_tab;
self.command_line.push_info(&cmd.prompt());
@ -635,7 +635,7 @@ impl OpenCADStudio {
Message::ImagePickResult(Err(e)) => {
if e != "Cancelled" {
self.command_line.push_error(&format!("IMAGE: {e}"));
self.command_line.push_error(crate::tf!("IMAGE: {e}").as_ref());
}
Task::none()
}
@ -671,7 +671,7 @@ impl OpenCADStudio {
Message::XAttachPickResult(Err(e)) => {
if e != "Cancelled" {
self.command_line.push_error(&format!("XATTACH: {e}"));
self.command_line.push_error(crate::tf!("XATTACH: {e}").as_ref());
}
Task::none()
}
@ -701,13 +701,13 @@ impl OpenCADStudio {
Message::WblockWriteFinished(block_name, path, result) => {
match result {
Ok(()) => self.command_line.push_output(&format!(
Ok(()) => self.command_line.push_output(crate::tf!(
"WBLOCK Saved \"{block_name}\" → \"{}\"",
path.display()
)),
).as_ref()),
Err(error) => self
.command_line
.push_error(&format!("WBLOCK save failed: {error}")),
.push_error(crate::tf!("WBLOCK save failed: {error}").as_ref()),
}
Task::none()
}
@ -739,11 +739,11 @@ impl OpenCADStudio {
.map(|n| n.to_string_lossy().into_owned())
.unwrap_or_else(|| path.to_string_lossy().into_owned());
self.command_line
.push_output(&format!("DATAEXTRACTION {rows} rows → \"{fname}\""));
.push_output(crate::tf!("DATAEXTRACTION {rows} rows → \"{fname}\"").as_ref());
}
Err(e) => self
.command_line
.push_error(&format!("DATAEXTRACTION: write failed: {e}")),
.push_error(crate::tf!("DATAEXTRACTION: write failed: {e}").as_ref()),
}
Task::none()
}
@ -754,7 +754,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].scene.meshes.is_empty() {
self.command_line
.push_error("STLOUT: no 3D mesh data in this drawing.");
.push_error(crate::t!("STLOUT: no 3D mesh data in this drawing.").as_ref());
return Task::none();
}
Task::perform(
@ -780,8 +780,8 @@ impl OpenCADStudio {
match result {
Ok(()) => self
.command_line
.push_output(&format!("STLOUT: exported to \"{}\"", path.display())),
Err(error) => self.command_line.push_error(&format!("STLOUT: {error}")),
.push_output(crate::tf!("STLOUT: exported to \"{}\"", path.display()).as_ref()),
Err(error) => self.command_line.push_error(crate::tf!("STLOUT: {error}").as_ref()),
}
Task::none()
}
@ -791,7 +791,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].scene.meshes.is_empty() {
self.command_line
.push_error("STEPOUT: no 3D mesh data in this drawing.");
.push_error(crate::t!("STEPOUT: no 3D mesh data in this drawing.").as_ref());
return Task::none();
}
Task::perform(
@ -817,8 +817,8 @@ impl OpenCADStudio {
match result {
Ok(()) => self
.command_line
.push_output(&format!("STEPOUT: exported to \"{}\"", path.display())),
Err(error) => self.command_line.push_error(&format!("STEPOUT: {error}")),
.push_output(crate::tf!("STEPOUT: exported to \"{}\"", path.display()).as_ref()),
Err(error) => self.command_line.push_error(crate::tf!("STEPOUT: {error}").as_ref()),
}
Task::none()
}
@ -843,11 +843,11 @@ impl OpenCADStudio {
Message::ObjImportFinished(tab_id, path, result) => {
match result {
Err(error) => self.command_line.push_error(&format!("IMPORTOBJ: {error}")),
Err(error) => self.command_line.push_error(crate::tf!("IMPORTOBJ: {error}").as_ref()),
Ok(mut mesh) => {
let Some(i) = self.tabs.iter().position(|tab| tab.id == tab_id) else {
self.command_line
.push_info("IMPORTOBJ: target drawing was closed.");
.push_info(crate::t!("IMPORTOBJ: target drawing was closed.").as_ref());
return Task::none();
};
let file_stem = path
@ -864,9 +864,9 @@ impl OpenCADStudio {
.meshes
.insert(handle, crate::scene::MeshLodSet::from_single(mesh));
self.tabs[i].dirty = true;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"IMPORTOBJ: imported \"{file_stem}\" as mesh."
));
).as_ref());
}
}
}
@ -878,7 +878,7 @@ impl OpenCADStudio {
Message::SaveAs => {
if self.read_only {
self.command_line
.push_error("Read-only session (--read-only): saving is disabled.");
.push_error(crate::t!("Read-only session (--read-only): saving is disabled.").as_ref());
return Task::none();
}
let i = self.active_tab;
@ -924,7 +924,7 @@ impl OpenCADStudio {
.layers
.sync_with_viewports(&doc_layers, vp_info);
self.command_line
.push_output("Scene cleared. Standard linetypes loaded.");
.push_output(crate::t!("Scene cleared. Standard linetypes loaded.").as_ref());
self.tabs[i].current_path = None;
self.tabs[i].dirty = true;
self.sync_ribbon_layers();
@ -988,7 +988,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if !crate::plugin::try_dispatch(self, i, &line) {
self.command_line
.push_error(&format!("No plugin handled: {command}"));
.push_error(crate::tf!("No plugin handled: {command}").as_ref());
}
}
Task::none()
@ -1138,7 +1138,7 @@ impl OpenCADStudio {
let Some(path) = self.tabs.get(idx).and_then(|tab| tab.current_path.clone())
else {
self.command_line
.push_error("Save the drawing before copying its file path.");
.push_error(crate::t!("Save the drawing before copying its file path.").as_ref());
return Task::none();
};
let full_path = path.canonicalize().unwrap_or_else(|_| {
@ -1151,7 +1151,7 @@ impl OpenCADStudio {
}
});
self.command_line
.push_output(&format!("Copied path: {}", full_path.display()));
.push_output(crate::tf!("Copied path: {}", full_path.display()).as_ref());
return iced::clipboard::write(full_path.to_string_lossy().into_owned())
.discard();
}
@ -1159,7 +1159,7 @@ impl OpenCADStudio {
{
let _ = idx;
self.command_line
.push_error("Full file paths are unavailable in the web application.");
.push_error(crate::t!("Full file paths are unavailable in the web application.").as_ref());
Task::none()
}
}
@ -1170,16 +1170,16 @@ impl OpenCADStudio {
let Some(path) = self.tabs.get(idx).and_then(|tab| tab.current_path.clone())
else {
self.command_line
.push_error("Save the drawing before opening its file location.");
.push_error(crate::t!("Save the drawing before opening its file location.").as_ref());
return Task::none();
};
match crate::sys::reveal_in_file_manager(&path) {
Ok(()) => self
.command_line
.push_output(&format!("Opened file location: {}", path.display())),
.push_output(crate::tf!("Opened file location: {}", path.display()).as_ref()),
Err(error) => self
.command_line
.push_error(&format!("Could not open file location: {error}")),
.push_error(crate::tf!("Could not open file location: {error}").as_ref()),
}
Task::none()
}
@ -1187,7 +1187,7 @@ impl OpenCADStudio {
{
let _ = idx;
self.command_line
.push_error("File locations are unavailable in the web application.");
.push_error(crate::t!("File locations are unavailable in the web application.").as_ref());
Task::none()
}
}
@ -1442,7 +1442,7 @@ impl OpenCADStudio {
self.ribbon.close_dropdown();
if self.tabs[i].is_start {
self.command_line
.push_info("Open or create a drawing to manage layer states.");
.push_info(crate::t!("Open or create a drawing to manage layer states.").as_ref());
return Task::none();
}
let mut names: Vec<String> = self.tabs[i]
@ -1482,7 +1482,7 @@ impl OpenCADStudio {
let name = self.layer_state_name_buf.trim().to_string();
if name.is_empty() {
self.command_line
.push_error("Layer state name cannot be empty.");
.push_error(crate::t!("Layer state name cannot be empty.").as_ref());
return Task::none();
}
let old_name = self.layer_state_selected.clone();
@ -1499,7 +1499,7 @@ impl OpenCADStudio {
});
if duplicate {
self.command_line
.push_error(&format!("Layer state \"{name}\" already exists."));
.push_error(crate::tf!("Layer state \"{name}\" already exists.").as_ref());
return Task::none();
}
@ -1520,7 +1520,7 @@ impl OpenCADStudio {
self.layer_state_selected = Some(name.clone());
self.layer_state_name_buf = name.clone();
self.command_line
.push_output(&format!("LAYERSTATE: saved \"{name}\" in the drawing."));
.push_output(crate::tf!("LAYERSTATE: saved \"{name}\" in the drawing.").as_ref());
Task::none()
}
Message::LayerStateManagerRestore => {
@ -1553,9 +1553,9 @@ impl OpenCADStudio {
.invalidate_layer_dependencies(&layer_names);
self.tabs[i].dirty = true;
self.refresh_layer_panel();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"LAYERSTATE: restored \"{name}\" ({restored} layer(s))."
));
).as_ref());
Task::none()
}
Message::LayerStateManagerDelete => {
@ -1576,7 +1576,7 @@ impl OpenCADStudio {
names.sort_by_key(|name| name.to_lowercase());
self.load_layer_state_editor(names.into_iter().next());
self.command_line
.push_output(&format!("LAYERSTATE: deleted \"{name}\"."));
.push_output(crate::tf!("LAYERSTATE: deleted \"{name}\".").as_ref());
}
Task::none()
}
@ -1587,7 +1587,7 @@ impl OpenCADStudio {
};
let Some(state) = self.tabs[i].scene.document.layer_state(&name) else {
self.command_line
.push_error(&format!("Layer state \"{name}\" was not found."));
.push_error(crate::tf!("Layer state \"{name}\" was not found.").as_ref());
return Task::none();
};
self.layer_state_edit_draft = Some(state);
@ -1730,7 +1730,7 @@ impl OpenCADStudio {
let name = draft.name.trim().to_string();
if name.is_empty() {
self.command_line
.push_error("Layer state name cannot be empty.");
.push_error(crate::t!("Layer state name cannot be empty.").as_ref());
return Task::none();
}
let old_name = self.layer_state_selected.clone();
@ -1747,7 +1747,7 @@ impl OpenCADStudio {
});
if duplicate {
self.command_line
.push_error(&format!("Layer state \"{name}\" already exists."));
.push_error(crate::tf!("Layer state \"{name}\" already exists.").as_ref());
return Task::none();
}
let Some(state) = self.layer_state_edit_draft.take() else {
@ -1775,7 +1775,7 @@ impl OpenCADStudio {
self.layer_state_edit_color_open = None;
self.active_modal = Some(super::ModalKind::LayerStateManager);
self.command_line
.push_output(&format!("LAYERSTATE: updated \"{name}\"."));
.push_output(crate::tf!("LAYERSTATE: updated \"{name}\".").as_ref());
Task::none()
}
Message::LayerStateEditorCancel => {
@ -1829,11 +1829,11 @@ impl OpenCADStudio {
self.tabs[i].scene.invalidate_layer_dependencies(&targets);
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} layer(s) turned {}",
targets.len(),
if on { "on" } else { "off" }
));
).as_ref());
self.sync_ribbon_layers();
}
}
@ -1869,11 +1869,11 @@ impl OpenCADStudio {
// Lock state affects editability, not rendered geometry.
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} layer(s) {}",
targets.len(),
if locked { "locked" } else { "unlocked" }
));
).as_ref());
self.sync_ribbon_layers();
}
}
@ -1904,11 +1904,11 @@ impl OpenCADStudio {
self.tabs[i].scene.invalidate_layer_dependencies(&targets);
self.tabs[i].dirty = true;
self.commit_layer_undo(i, undo);
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"{} layer(s) {}",
targets.len(),
if frozen { "frozen" } else { "thawed" }
));
).as_ref());
self.sync_ribbon_layers();
}
}
@ -2300,7 +2300,7 @@ impl OpenCADStudio {
self.tabs[i].scene.camera.borrow_mut().home_view(r_ucs);
}
self.tabs[i].scene.camera_generation += 1;
self.command_line.push_output("View: Home");
self.command_line.push_output(crate::t!("View: Home").as_ref());
Task::none()
}
@ -2351,11 +2351,11 @@ impl OpenCADStudio {
let mut changed = false;
if name.is_empty() || name == "WCS" {
self.tabs[i].active_ucs = None;
self.command_line.push_output("UCS: World");
self.command_line.push_output(crate::t!("UCS: World").as_ref());
changed = true;
} else if let Some(named) = self.tabs[i].scene.document.ucss.get(&name).cloned() {
self.tabs[i].active_ucs = Some(named);
self.command_line.push_output(&format!("UCS: {}", name));
self.command_line.push_output(crate::tf!("UCS: {}", name).as_ref());
changed = true;
}
if changed {
@ -2511,7 +2511,7 @@ impl OpenCADStudio {
_ => "live",
};
self.command_line
.push_output(&format!("COORDS = {mode} ({label})"));
.push_output(crate::tf!("COORDS = {mode} ({label})").as_ref());
}
Task::none()
}
@ -2700,11 +2700,11 @@ impl OpenCADStudio {
self.active_modal = Some(crate::app::ModalKind::AnnoObjectScale);
} else {
self.command_line
.push_info("The selected object does not support annotation scales.");
.push_info(crate::t!("The selected object does not support annotation scales.").as_ref());
}
} else {
self.command_line
.push_info("Select one object first, then run OBJECTSCALE.");
.push_info(crate::t!("Select one object first, then run OBJECTSCALE.").as_ref());
}
Task::none()
}
@ -3341,7 +3341,7 @@ impl OpenCADStudio {
let to_move: Vec<_> = self.tabs[i].scene.selected.iter().cloned().collect();
if to_move.is_empty() {
self.command_line
.push_error("DRAWORDER: select entities first.");
.push_error(crate::t!("DRAWORDER: select entities first.").as_ref());
} else {
use crate::command::CadCommand;
let cmd = super::commands::DrawOrderRefCommand::new(to_move, above);
@ -3356,7 +3356,7 @@ impl OpenCADStudio {
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
let added = self.tabs[i].scene.select_similar();
self.command_line
.push_output(&format!("Select Similar: {} added.", added));
.push_output(crate::tf!("Select Similar: {} added.", added).as_ref());
self.refresh_properties();
Task::none()
}
@ -3366,7 +3366,7 @@ impl OpenCADStudio {
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
let count = self.tabs[i].scene.invert_selection();
self.command_line
.push_output(&format!("Invert Selection: {} object(s) selected.", count));
.push_output(crate::tf!("Invert Selection: {} object(s) selected.", count).as_ref());
self.refresh_properties();
Task::none()
}
@ -3441,7 +3441,7 @@ impl OpenCADStudio {
state.append,
);
self.command_line
.push_output(&format!("QSELECT: {} object(s) selected.", matched));
.push_output(crate::tf!("QSELECT: {} object(s) selected.", matched).as_ref());
self.refresh_properties();
Task::none()
}
@ -4023,7 +4023,7 @@ impl OpenCADStudio {
if self.tabs[i].scene.delete_layout(&name) {
self.layout_rename_state = None;
self.command_line
.push_output(&format!("Layout \"{name}\" silindi"));
.push_output(crate::tf!("Layout \"{name}\" silindi").as_ref());
self.tabs[i].dirty = true;
}
Task::batch([cancel_task, switch_task])
@ -4061,7 +4061,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].is_start {
self.command_line
.push_info("Open or create a drawing to manage layouts.");
.push_info(crate::t!("Open or create a drawing to manage layouts.").as_ref());
return Task::none();
}
let current = self.tabs[i].scene.current_layout.clone();
@ -4097,9 +4097,9 @@ impl OpenCADStudio {
let new_name = self.layout_manager_rename_buf.trim().to_string();
if old_name == "Model" {
self.command_line
.push_error("Cannot rename the Model layout.");
.push_error(crate::t!("Cannot rename the Model layout.").as_ref());
} else if new_name.is_empty() {
self.command_line.push_error("Layout name cannot be empty.");
self.command_line.push_error(crate::t!("Layout name cannot be empty.").as_ref());
} else if new_name == old_name {
// no-op
} else {
@ -4111,7 +4111,7 @@ impl OpenCADStudio {
self.layout_manager_selected = new_name.clone();
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Layout renamed: '{old_name}' → '{new_name}'"));
.push_output(crate::tf!("Layout renamed: '{old_name}' → '{new_name}'").as_ref());
}
Task::none()
}
@ -4119,7 +4119,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].is_start {
self.command_line
.push_info("Open or create a drawing to add a layout.");
.push_info(crate::t!("Open or create a drawing to add a layout.").as_ref());
return Task::none();
}
let existing = self.tabs[i].scene.layout_names();
@ -4134,9 +4134,9 @@ impl OpenCADStudio {
self.layout_manager_selected = name.clone();
self.layout_manager_rename_buf = name.clone();
self.command_line
.push_output(&format!("Layout '{name}' created."));
.push_output(crate::tf!("Layout '{name}' created.").as_ref());
}
Err(e) => self.command_line.push_error(&format!("LAYOUT: {e}")),
Err(e) => self.command_line.push_error(crate::tf!("LAYOUT: {e}").as_ref()),
}
Task::none()
}
@ -4145,7 +4145,7 @@ impl OpenCADStudio {
let name = self.layout_manager_selected.clone();
if name == "Model" {
self.command_line
.push_error("Cannot delete the Model layout.");
.push_error(crate::t!("Cannot delete the Model layout.").as_ref());
Task::none()
} else {
let deleting_current = self.tabs[i].scene.current_layout == name;
@ -4165,7 +4165,7 @@ impl OpenCADStudio {
self.layout_manager_selected = "Model".to_string();
self.layout_manager_rename_buf = String::new();
self.command_line
.push_output(&format!("Layout '{name}' deleted."));
.push_output(crate::tf!("Layout '{name}' deleted.").as_ref());
Task::batch([cancel_task, switch_task])
}
}
@ -4209,7 +4209,7 @@ impl OpenCADStudio {
let task = self.on_layout_switch(name.clone());
if self.tabs[self.active_tab].scene.current_layout == name {
self.command_line
.push_output(&format!("Switched to layout '{name}'."));
.push_output(crate::tf!("Switched to layout '{name}'.").as_ref());
}
task
}
@ -4273,10 +4273,10 @@ impl OpenCADStudio {
}
Message::AliasEditorApply => {
self.apply_alias_editor_rows();
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"{} alias(es) applied.",
self.command_aliases.len()
));
).as_ref());
Task::none()
}
@ -4334,7 +4334,7 @@ impl OpenCADStudio {
}
Err(error) => self
.command_line
.push_error(&format!("Unable to change UI language: {error}")),
.push_error(crate::tf!("Unable to change UI language: {error}").as_ref()),
}
Task::none()
}
@ -4959,7 +4959,7 @@ impl OpenCADStudio {
let phase = Instant::now();
self.refresh_properties();
let properties_ms = phase.elapsed().as_secs_f64() * 1000.0;
self.command_line.push_output("MSPACE");
self.command_line.push_output(crate::t!("MSPACE").as_ref());
if perf {
crate::perf_record!(
"[perf] viewport-enter total={:.2}ms normalize={:.2}ms display={:.2}ms ucs={:.2}ms properties={:.2}ms handle={}",
@ -4996,7 +4996,7 @@ impl OpenCADStudio {
// Paper space has no UCS — drop the viewport's UCS.
self.tabs[i].refresh_active_ucs();
self.refresh_properties();
self.command_line.push_output("PSPACE");
self.command_line.push_output(crate::t!("PSPACE").as_ref());
if context_changed {
self.sync_dyn_fields();
}
@ -5007,7 +5007,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].scene.current_layout == "Model" {
self.command_line
.push_error("MS is only available in paper space layouts.");
.push_error(crate::t!("MS is only available in paper space layouts.").as_ref());
return Task::none();
}
if self.tabs[i].scene.active_viewport.is_some() {
@ -5018,7 +5018,7 @@ impl OpenCADStudio {
Some(handle) => Task::done(Message::EnterViewport(handle)),
None => {
self.command_line
.push_error("No viewport found in this layout.");
.push_error(crate::t!("No viewport found in this layout.").as_ref());
Task::none()
}
}
@ -5163,7 +5163,7 @@ impl OpenCADStudio {
Ok(msg) => self.command_line.push_info(&msg),
Err(err) => self
.command_line
.push_error(&format!("Could not set default app: {err}")),
.push_error(crate::tf!("Could not set default app: {err}").as_ref()),
}
Task::none()
}
@ -5252,11 +5252,11 @@ impl OpenCADStudio {
Message::PrintToPrinter => self.on_print_to_printer(),
Message::PrintResult(Ok(printer)) => {
self.command_line
.push_info(&format!("Sent to printer: {printer}"));
.push_info(crate::tf!("Sent to printer: {printer}").as_ref());
Task::none()
}
Message::PrintResult(Err(e)) => {
self.command_line.push_error(&format!("Print failed: {e}"));
self.command_line.push_error(crate::tf!("Print failed: {e}").as_ref());
Task::none()
}
@ -5273,7 +5273,7 @@ impl OpenCADStudio {
}
self.plot_dialog.style_name = table.name.clone();
self.plot_dialog.style_missing = false;
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Plot style '{}' loaded ({} color entries).",
table.name,
table
@ -5281,7 +5281,7 @@ impl OpenCADStudio {
.iter()
.filter(|e| e.color.is_some())
.count()
));
).as_ref());
self.active_plot_style = Some(table);
self.plot_dialog.plot_styles = crate::io::plot_style::available_ctb_names();
Task::none()
@ -5291,7 +5291,7 @@ impl OpenCADStudio {
self.active_plot_style = None;
self.plot_dialog.style_name.clear();
self.plot_dialog.style_missing = false;
self.command_line.push_output("Plot style table cleared.");
self.command_line.push_output(crate::t!("Plot style table cleared.").as_ref());
Task::none()
}
@ -5383,12 +5383,12 @@ impl OpenCADStudio {
self.plot_dialog.style_missing = false;
self.plot_dialog.plot_styles =
crate::io::plot_style::available_ctb_names();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Plot style table saved to \"{}\".",
path.display()
));
).as_ref());
}
Err(e) => self.command_line.push_error(&format!("Save error: {e}")),
Err(e) => self.command_line.push_error(crate::tf!("Save error: {e}").as_ref()),
}
}
Task::none()
@ -5416,7 +5416,7 @@ impl OpenCADStudio {
self.tabs[i].scene.document.header.current_text_style_name = name.clone();
self.sync_ribbon_styles();
self.command_line
.push_output(&format!("Current text style: {}", name));
.push_output(crate::tf!("Current text style: {}", name).as_ref());
}
Task::none()
}
@ -5716,7 +5716,7 @@ impl OpenCADStudio {
self.tabs[i].scene.document.header.current_table_style_name = name.clone();
self.ribbon.active_table_style = name.clone();
self.command_line
.push_output(&format!("Current table style: {name}"));
.push_output(crate::tf!("Current table style: {name}").as_ref());
}
Task::none()
}
@ -5745,7 +5745,7 @@ impl OpenCADStudio {
// Staged: persists on Apply.
self.tabs[i].scene.document.header.multiline_style = name.clone();
self.command_line
.push_output(&format!("Current multiline style: {}", name));
.push_output(crate::tf!("Current multiline style: {}", name).as_ref());
}
Task::none()
}
@ -5878,10 +5878,10 @@ impl OpenCADStudio {
self.tabs[i].scene.document.header.current_dimstyle_name =
self.dimstyle_selected.clone();
self.sync_ribbon_styles();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Current dim style set to '{}'.",
self.dimstyle_selected
));
).as_ref());
Task::none()
}
Message::DimStyleDialogDelete => {

View file

@ -368,7 +368,7 @@ impl OpenCADStudio {
ds.dimalt = self.ds_dimalt;
ds.dimapost = self.ds_dimapost.clone();
self.command_line
.push_output(&format!("DimStyle '{}' updated.", self.dimstyle_selected));
.push_output(crate::tf!("DimStyle '{}' updated.", self.dimstyle_selected).as_ref());
}
/// Update a single string buffer field.
@ -687,7 +687,7 @@ pub(super) fn on_text_style_dialog_open(&mut self) -> Task<Message> {
self.tabs[i].active_mleader_style = name.clone();
self.ribbon.active_mleader_style = name.clone();
self.command_line
.push_output(&format!("Current multileader style: {}", name));
.push_output(crate::tf!("Current multileader style: {}", name).as_ref());
}
Task::none()
}

View file

@ -515,7 +515,7 @@ impl OpenCADStudio {
if self.tabs[i].scene.set_active_viewport_render_mode(mode) {
self.tabs[i].scene.bump_geometry_no_blocks();
self.command_line
.push_output(&format!("Viewport visual style: {label}"));
.push_output(crate::tf!("Viewport visual style: {label}").as_ref());
return Task::none();
}
self.tabs[i].render_mode = mode;
@ -533,7 +533,7 @@ impl OpenCADStudio {
// pipeline keys its upload cache off `geometry_epoch`.
self.tabs[i].scene.bump_geometry_no_blocks();
self.command_line
.push_output(&format!("Visual style: {label}"));
.push_output(crate::tf!("Visual style: {label}").as_ref());
Task::none()
}
@ -2616,7 +2616,7 @@ impl OpenCADStudio {
.as_mut()
.map(|c| c.on_structure_pick(pick.handle, center));
self.command_line
.push_info(&format!("{} acquired.", pick.label));
.push_info(crate::tf!("{} acquired.", pick.label).as_ref());
result
} else {
let msg = self.tabs[i]
@ -2745,7 +2745,7 @@ impl OpenCADStudio {
self.tabs[i].active_cmd = Some(cmd);
} else {
self.command_line
.push_error("HATCHEDIT: not a hatch entity.");
.push_error(crate::t!("HATCHEDIT: not a hatch entity.").as_ref());
self.tabs[i].active_cmd = None;
}
}
@ -2772,7 +2772,7 @@ impl OpenCADStudio {
}
result
} else {
self.command_line.push_info("Nothing found at that point.");
self.command_line.push_info(crate::t!("Nothing found at that point.").as_ref());
None
}
} else if self.tabs[i]
@ -2787,7 +2787,7 @@ impl OpenCADStudio {
.as_mut()
.map(|c| c.on_tangent_point(obj, pick_wcs))
} else {
self.command_line.push_info("Select a tangent object.");
self.command_line.push_info(crate::t!("Select a tangent object.").as_ref());
None
}
} else if !self.command_point_allowed(i, world_pt) {
@ -3250,9 +3250,9 @@ impl OpenCADStudio {
// `selection_just_completed`, or a
// gather command (MOVE's "select
// objects") would wrongly finish.
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Object is on locked layer \"{layer}\" — unlock the layer to select or edit it."
));
).as_ref());
} else {
// Individual picks accumulate (issue #47):
// each plain click adds to the selection,
@ -3513,9 +3513,9 @@ impl OpenCADStudio {
// Locked layer: double-click must not open any editor
// (text / attribute / in-place block edit).
if let Some(layer) = self.tabs[i].scene.locked_layer_name(handle) {
self.command_line.push_info(&format!(
self.command_line.push_info(crate::tf!(
"Object is on locked layer \"{layer}\" — unlock the layer to edit it."
));
).as_ref());
return Task::none();
}
// Any text-bearing entity opens its in-place editor
@ -3693,7 +3693,7 @@ impl OpenCADStudio {
self.tabs[i]
.scene
.record_nav_perf(crate::scene::NavPerfOp::Zoom, now);
self.command_line.push_output("Zoom Extents");
self.command_line.push_output(crate::t!("Zoom Extents").as_ref());
}
Task::none()
}
@ -3891,7 +3891,7 @@ impl OpenCADStudio {
}
self.tabs[i].scene.camera_generation += 1;
self.command_line
.push_output(&format!("View: {}", region.label()));
.push_output(crate::tf!("View: {}", region.label()).as_ref());
Task::none()
}
@ -4094,7 +4094,7 @@ impl OpenCADStudio {
.position(|session| session.block_name == name)
else {
self.command_line
.push_error(&format!("BEDIT: block tab \"{name}\" is not open."));
.push_error(crate::tf!("BEDIT: block tab \"{name}\" is not open.").as_ref());
return Task::none();
};
if self.tabs[i].active_block_edit == Some(target_index) {
@ -4156,7 +4156,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].is_start {
self.command_line
.push_info("Open or create a drawing to switch layouts.");
.push_info(crate::t!("Open or create a drawing to switch layouts.").as_ref());
return Task::none();
}
let perf = crate::perf::enabled();
@ -4270,7 +4270,7 @@ impl OpenCADStudio {
let i = self.active_tab;
if self.tabs[i].is_start {
self.command_line
.push_info("Open or create a drawing to add a layout.");
.push_info(crate::t!("Open or create a drawing to add a layout.").as_ref());
return Task::none();
}
let cancel_task = self.cancel_active_command_for_space_change();
@ -4310,15 +4310,15 @@ impl OpenCADStudio {
self.tabs[i].scene.ensure_sheet_viewport(&new_name);
let switch_task = self.on_layout_switch(new_name.clone());
self.tabs[i].scene.fit_all();
self.command_line.push_output(&format!(
self.command_line.push_output(crate::tf!(
"Layout \"{new_name}\" created — use MVIEW to add a viewport"
));
).as_ref());
self.tabs[i].dirty = true;
return Task::batch([cancel_task, switch_task]);
}
Err(e) => self
.command_line
.push_error(&format!("Failed to create layout: {e}")),
.push_error(crate::tf!("Failed to create layout: {e}").as_ref()),
}
cancel_task
}
@ -4342,7 +4342,7 @@ impl OpenCADStudio {
.is_some()
{
self.command_line
.push_error(&format!("\"{}\" name already in use", new_name));
.push_error(crate::tf!("\"{}\" name already in use", new_name).as_ref());
} else {
self.push_undo_snapshot(i, "BLOCK RENAME");
if self.tabs[i].scene.rename_block(&orig, &new_name) {
@ -4358,10 +4358,10 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Block \"{orig}\" → \"{new_name}\""));
.push_output(crate::tf!("Block \"{orig}\" → \"{new_name}\"").as_ref());
} else {
self.command_line
.push_error(&format!("Could not rename block \"{orig}\""));
.push_error(crate::tf!("Could not rename block \"{orig}\"").as_ref());
}
}
return Task::none();
@ -4373,7 +4373,7 @@ impl OpenCADStudio {
.any(|n| *n == new_name);
if exists {
self.command_line
.push_error(&format!("\"{}\" name already in use", new_name));
.push_error(crate::tf!("\"{}\" name already in use", new_name).as_ref());
} else {
self.push_undo_snapshot(i, "LAYOUT RENAME");
self.tabs[i].scene.rename_layout(&orig, &new_name);
@ -4382,7 +4382,7 @@ impl OpenCADStudio {
}
self.tabs[i].dirty = true;
self.command_line
.push_output(&format!("Layout \"{orig}\" → \"{new_name}\""));
.push_output(crate::tf!("Layout \"{orig}\" → \"{new_name}\"").as_ref());
}
}
}