mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-02 22:50:27 -06:00
i18n (cs): translate status-bar messages
The status line showed English for the messages the UI composes itself.
Literal messages and templates now go through `tr` at their call sites
("Packaged {count} files into {dir}" and similar), the "<feature>: <error>"
messages share a small `DesignApp::status_error` helper that translates the
feature name, and "Home" is translated too. Engine error texts stay as the
engine wrote them. Adds the Czech strings, the stale-key allow-list entries
and a test for the helper.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
63b0425464
commit
314f82eba0
@@ -121,7 +121,7 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
);
|
||||
ui.add_space(6.0);
|
||||
if icons::button(ui, "share", 22.0, false, crate::i18n::tr(&app.ui.language, "Share")).clicked() {
|
||||
app.status("Export a PDF, IDML or package to share — no cloud account needed.");
|
||||
app.status(crate::i18n::tr(&app.ui.language, "Export a PDF, IDML or package to share — no cloud account needed."));
|
||||
}
|
||||
ui.add_space(8.0);
|
||||
// Always one click away: the ArtCraft community Discord.
|
||||
@@ -157,7 +157,7 @@ pub fn app_bar(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
|
||||
impl DesignApp {
|
||||
fn session_home(&mut self) {
|
||||
self.ui.status = "Home".into();
|
||||
self.ui.status = crate::i18n::tr(&self.ui.language, "Home").into();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ fn user_dictionary(app: &mut DesignApp, ui: &mut egui::Ui, d: &mut Dialog) {
|
||||
Ok(_) => {
|
||||
d.fields.insert("word".into(), json!(""));
|
||||
}
|
||||
Err(e) => app.status(format!("User Dictionary: {e}")),
|
||||
Err(e) => app.status_error("User Dictionary", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1474,7 +1474,7 @@ pub fn show(app: &mut DesignApp, ctx: &egui::Context) {
|
||||
let f = app.session.execute("color.settings", &json!({})).unwrap_or_default();
|
||||
d.fields.insert("profiles".into(), f["profiles"].clone());
|
||||
}
|
||||
Err(e) => app.status(format!("Color Settings: {e}")),
|
||||
Err(e) => app.status_error("Color Settings", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1931,7 +1931,8 @@ pub fn confirm(app: &mut DesignApp) -> Result<Value, String> {
|
||||
json!({"printer": if printer.is_empty() { Value::Null } else { json!(printer) }, "copies": d.n("copies").unwrap_or(1.0).max(1.0) as u64,
|
||||
"pages": pages, "spreads": d.b("spreads"), "marks": d.b("marks"), "bleed": d.b("bleed")}),
|
||||
)?;
|
||||
app.status(format!("Sent {} page(s) to {}", r["pages"], r["printer"].as_str().unwrap_or("the default printer")));
|
||||
let printer = r["printer"].as_str().unwrap_or_else(|| crate::i18n::tr(&app.ui.language, "the default printer"));
|
||||
app.status(crate::i18n::tr(&app.ui.language, "Sent {count} page(s) to {printer}").replace("{count}", &r["pages"].to_string()).replace("{printer}", printer));
|
||||
Ok(r)
|
||||
}
|
||||
"pdfExport" => {
|
||||
|
||||
@@ -3088,6 +3088,19 @@ mod tests {
|
||||
"Text:",
|
||||
"Unsaved Changes",
|
||||
"“{}” has changes that are not saved. Save them before closing?",
|
||||
// Status-bar messages.
|
||||
"Alternate layout",
|
||||
"Couldn't write recovery data: {error}",
|
||||
"Export a PDF, IDML or package to share — no cloud account needed.",
|
||||
"Import cancelled: the originating document has closed",
|
||||
"Invalid panel layout; restored the default dock",
|
||||
"PDF import cancelled: the originating document has closed",
|
||||
"Packaged {count} files into {dir}",
|
||||
"Relinked {count}",
|
||||
"Sent {count} page(s) to {printer}",
|
||||
"the default printer",
|
||||
"{name}: import cancelled while a dialog is open; choose the file again",
|
||||
"{name}: {count} step(s) done",
|
||||
]);
|
||||
// A new English string falls back to English until it is translated, so only stale
|
||||
// entries (keys nothing passes to `tr` any more) fail.
|
||||
|
||||
@@ -1727,6 +1727,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
// Labels the code passes to `tr` that no other catalog has yet.
|
||||
("Activate Panel", "Aktivovat panel"),
|
||||
("Add Anchor Point Tool", "Nástroj Přidat kotevní bod"),
|
||||
("Alternate layout", "Alternativní rozvržení"),
|
||||
("Cell Number:", "Číslo mobilu:"),
|
||||
("Change fill to:", "Změnit výplň na:"),
|
||||
("Change Panel Layout", "Změnit rozvržení panelů"),
|
||||
@@ -1737,6 +1738,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Content Collector Tool", "Nástroj Sběrač obsahu"),
|
||||
("Content Placer Tool", "Nástroj Umísťovač obsahu"),
|
||||
("Convert Direction Point Tool", "Nástroj Převést směrový bod"),
|
||||
("Couldn't write recovery data: {error}", "Nelze zapsat data pro obnovu: {error}"),
|
||||
("Data Fields", "Datová pole"),
|
||||
("Data Merge Options", "Možnosti sloučení dat"),
|
||||
("Delete Anchor Point Tool", "Nástroj Odstranit kotevní bod"),
|
||||
@@ -1749,6 +1751,10 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Email Address:", "E-mailová adresa:"),
|
||||
("Email:", "E-mail:"),
|
||||
("Erase Tool", "Nástroj Guma"),
|
||||
(
|
||||
"Export a PDF, IDML or package to share — no cloud account needed.",
|
||||
"Ke sdílení exportujte PDF, IDML nebo balíček – cloudový účet není potřeba.",
|
||||
),
|
||||
("Eyedropper Tool", "Nástroj Kapátko"),
|
||||
("Find fill:", "Najít výplň:"),
|
||||
("Free Transform Tool", "Nástroj Volná transformace"),
|
||||
@@ -1758,7 +1764,9 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Group with", "Seskupit s"),
|
||||
("H:", "V:"),
|
||||
("Hand Tool", "Nástroj Ruka"),
|
||||
("Import cancelled: the originating document has closed", "Import zrušen: původní dokument byl zavřen"),
|
||||
("Insert Field", "Vložit pole"),
|
||||
("Invalid panel layout; restored the default dock", "Neplatné rozvržení panelů; obnoveno výchozí ukotvení"),
|
||||
("Line Tool", "Nástroj Čára"),
|
||||
("List Composite Fonts", "Vypsat složená písma"),
|
||||
("Measure Tool", "Nástroj Měřidlo"),
|
||||
@@ -1767,7 +1775,9 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Note Tool", "Nástroj Poznámka"),
|
||||
("Object & Layout", "Objekt a rozvržení"),
|
||||
("Organization:", "Organizace:"),
|
||||
("Packaged {count} files into {dir}", "Sbaleno souborů: {count} do {dir}"),
|
||||
("Page Tool", "Nástroj Stránka"),
|
||||
("PDF import cancelled: the originating document has closed", "Import PDF zrušen: původní dokument byl zavřen"),
|
||||
("Pen Tool", "Nástroj Pero"),
|
||||
("Pencil Tool", "Nástroj Tužka"),
|
||||
("Phone:", "Telefon:"),
|
||||
@@ -1777,6 +1787,7 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Preview Record", "Náhled záznamu"),
|
||||
("Rectangle Frame Tool", "Nástroj Obdélníkový rámeček"),
|
||||
("Rectangle Tool", "Nástroj Obdélník"),
|
||||
("Relinked {count}", "Znovu propojeno: {count}"),
|
||||
("Remove Data Source", "Odebrat zdroj dat"),
|
||||
("Remove Field", "Odebrat pole"),
|
||||
("Reset Bar Position", "Obnovit polohu lišty"),
|
||||
@@ -1786,12 +1797,14 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("Scale Tool", "Nástroj Změna měřítka"),
|
||||
("Scissors Tool", "Nástroj Nůžky"),
|
||||
("Selection Tool", "Nástroj Výběr"),
|
||||
("Sent {count} page(s) to {printer}", "Odesláno stránek: {count} (tiskárna: {printer})"),
|
||||
("Set Composite Font", "Nastavit složené písmo"),
|
||||
("Shear Tool", "Nástroj Zkosení"),
|
||||
("Smooth Tool", "Nástroj Vyhladit"),
|
||||
("Stop Preview", "Ukončit náhled"),
|
||||
("Subject:", "Předmět:"),
|
||||
("Text:", "Text:"),
|
||||
("the default printer", "výchozí"),
|
||||
("Type on a Path Tool", "Nástroj Text na cestě"),
|
||||
("Type Tool", "Nástroj Text"),
|
||||
("Unsaved Changes", "Neuložené změny"),
|
||||
@@ -1804,6 +1817,11 @@ pub(super) const TABLE: &[(&str, &str)] = &[
|
||||
("(any)", "(libovolná)"),
|
||||
("(unchanged)", "(beze změny)"),
|
||||
("[No Language]", "[Žádný jazyk]"),
|
||||
(
|
||||
"{name}: import cancelled while a dialog is open; choose the file again",
|
||||
"{name}: import byl zrušen, protože je otevřený dialog; vyberte soubor znovu",
|
||||
),
|
||||
("{name}: {count} step(s) done", "{name}: hotovo kroků: {count}"),
|
||||
("“{}” has changes that are not saved. Save them before closing?", "„{}“ obsahuje neuložené změny. Uložit je před zavřením?"),
|
||||
];
|
||||
|
||||
|
||||
@@ -585,6 +585,12 @@ impl DesignApp {
|
||||
self.ui.status = s.into();
|
||||
}
|
||||
|
||||
/// "<feature>: <error>" in the status bar: the feature name is translated, the engine's own
|
||||
/// error text stays as the engine wrote it.
|
||||
pub fn status_error(&mut self, feature: &str, error: impl std::fmt::Display) {
|
||||
self.ui.status = format!("{}: {error}", crate::i18n::tr(&self.ui.language, feature));
|
||||
}
|
||||
|
||||
/// THE entry point for every action (menus, shortcuts, palette, panels, control channel).
|
||||
pub fn run(&mut self, id: &str, params: Value) -> Result<Value, String> {
|
||||
if let Some(r) = menus::run_ui(self, id, ¶ms) {
|
||||
@@ -655,7 +661,7 @@ impl DesignApp {
|
||||
pub(crate) fn activate_import_target(&mut self, request: &ImportRequest) -> Result<(), String> {
|
||||
let Some(index) = request.target.and_then(|uid| self.session.documents().iter().position(|d| d.uid == uid)) else {
|
||||
let message = "Import cancelled: the originating document has closed";
|
||||
self.status(message);
|
||||
self.status(crate::i18n::tr(&self.ui.language, message));
|
||||
return Err(message.into());
|
||||
};
|
||||
self.run("file.activate", json!({"index": index}))?;
|
||||
@@ -688,7 +694,7 @@ impl DesignApp {
|
||||
if owns_dialog {
|
||||
self.ui.dialog = None;
|
||||
}
|
||||
self.status("PDF import cancelled: the originating document has closed");
|
||||
self.status(crate::i18n::tr(&self.ui.language, "PDF import cancelled: the originating document has closed"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -696,7 +702,10 @@ impl DesignApp {
|
||||
let files = std::mem::take(&mut *inbox.lock().unwrap_or_else(|e| e.into_inner()));
|
||||
for file in files {
|
||||
if self.ui.dialog.is_some() {
|
||||
self.status(format!("{}: import cancelled while a dialog is open; choose the file again", file.name));
|
||||
self.status(
|
||||
crate::i18n::tr(&self.ui.language, "{name}: import cancelled while a dialog is open; choose the file again")
|
||||
.replace("{name}", &file.name),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let name = file.name.clone();
|
||||
@@ -775,7 +784,7 @@ impl DesignApp {
|
||||
if self.session.documents().iter().any(|d| d.is_dirty())
|
||||
&& let Err(e) = self.session.execute("file.recovery.save", &json!({}))
|
||||
{
|
||||
self.status(format!("Couldn't write recovery data: {e}"));
|
||||
self.status(crate::i18n::tr(&self.ui.language, "Couldn't write recovery data: {error}").replace("{error}", &e.to_string()));
|
||||
}
|
||||
}
|
||||
let dt = now - self.last_time;
|
||||
@@ -1265,6 +1274,16 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn status_messages_follow_the_interface_language_but_engine_errors_stay_english() {
|
||||
let mut app = DesignApp::new(Session::new(), Services::default());
|
||||
app.status_error("Table", "No table selected");
|
||||
assert_eq!(app.ui.status, "Table: No table selected");
|
||||
app.ui.language = "cs".into();
|
||||
app.status_error("Table", "No table selected");
|
||||
assert_eq!(app.ui.status, "Tabulka: No table selected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dropping_an_unreadable_file_alerts() {
|
||||
// A document opens, so it says it can't be opened.
|
||||
|
||||
@@ -848,11 +848,11 @@ pub fn run_ui(app: &mut DesignApp, id: &str, p: &Value) -> Option<Result<Value,
|
||||
Some(dir) => {
|
||||
let r = app.run("file.package", json!({"dir": dir}));
|
||||
if let Ok(v) = &r {
|
||||
app.status(format!(
|
||||
"Packaged {} files into {}",
|
||||
v["files"].as_array().map_or(0, |f| f.len()),
|
||||
v["dir"].as_str().unwrap_or("")
|
||||
));
|
||||
app.status(
|
||||
crate::i18n::tr(&app.ui.language, "Packaged {count} files into {dir}")
|
||||
.replace("{count}", &v["files"].as_array().map_or(0, |f| f.len()).to_string())
|
||||
.replace("{dir}", v["dir"].as_str().unwrap_or("")),
|
||||
);
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ pub(crate) fn show(app: &mut DesignApp, ui: &mut egui::Ui) -> bool {
|
||||
let Some(layout) = app.ui.docking.as_ref() else { return false };
|
||||
if !valid(layout) {
|
||||
app.ui.docking = None;
|
||||
app.status("Invalid panel layout; restored the default dock");
|
||||
app.status(crate::i18n::tr(&app.ui.language, "Invalid panel layout; restored the default dock"));
|
||||
return false;
|
||||
}
|
||||
let mut layout = layout.clone();
|
||||
|
||||
@@ -58,10 +58,10 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if has_text {
|
||||
let on = !applied.contains(&c.name);
|
||||
if let Err(e) = app.run("condition.apply", json!({"name": c.name, "on": on})) {
|
||||
app.status(format!("Conditional Text: {e}"));
|
||||
app.status_error("Conditional Text", e);
|
||||
}
|
||||
} else {
|
||||
app.status("Select text to apply a condition".to_string());
|
||||
app.status(crate::i18n::tr(&app.ui.language, "Select text to apply a condition"));
|
||||
}
|
||||
}
|
||||
nr.context_menu(|ui| {
|
||||
@@ -83,7 +83,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))).clicked() && !name.trim().is_empty() {
|
||||
match app.run("condition.new", json!({"name": name.trim()})) {
|
||||
Ok(_) => name.clear(),
|
||||
Err(e) => app.status(format!("Conditional Text: {e}")),
|
||||
Err(e) => app.status_error("Conditional Text", e),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -125,7 +125,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
st.recent.insert(0, c);
|
||||
st.recent.truncate(12);
|
||||
}
|
||||
Err(e) => app.status(format!("Glyphs: {e}")),
|
||||
Err(e) => app.status_error("Glyphs", e),
|
||||
}
|
||||
}
|
||||
crate::rtl::label(
|
||||
|
||||
@@ -34,7 +34,7 @@ pub fn hyperlinks(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
let p = if let Some(m) = url.strip_prefix("mailto:") { json!({"email": m}) } else { json!({"url": url}) };
|
||||
if let Err(e) = app.run("hyperlink.create", p) {
|
||||
app.status(format!("Hyperlinks: {e}"));
|
||||
app.status_error("Hyperlinks", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -176,7 +176,7 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "New"))).clicked() && !name.trim().is_empty() {
|
||||
match app.run("xml.newTag", json!({"name": name.trim()})) {
|
||||
Ok(_) => name.clear(),
|
||||
Err(e) => app.status(format!("Tags: {e}")),
|
||||
Err(e) => app.status_error("Tags", e),
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -232,7 +232,7 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
match app.run("xml.loadDtd", json!({"path": path})) {
|
||||
Ok(_) => problems = None,
|
||||
Err(e) => app.status(format!("Load DTD: {e}")),
|
||||
Err(e) => app.status_error("Load DTD", e),
|
||||
}
|
||||
}
|
||||
let has_dtd = info["dtd"].as_bool().unwrap_or(false);
|
||||
@@ -281,7 +281,7 @@ pub fn tags(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("xml"))
|
||||
&& let Err(e) = app.run("file.importXml", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Import XML: {e}"));
|
||||
app.status_error("Import XML", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -310,7 +310,7 @@ pub fn states(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
.clicked()
|
||||
&& let Err(e) = app.run("states.create", json!({}))
|
||||
{
|
||||
app.status(format!("Object States: {e}"));
|
||||
app.status_error("Object States", e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -398,7 +398,7 @@ pub fn buttons(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if let Some(p) = params
|
||||
&& let Err(e) = app.run("button.set", p)
|
||||
{
|
||||
app.status(format!("Buttons: {e}"));
|
||||
app.status_error("Buttons", e);
|
||||
}
|
||||
crate::rtl::label(
|
||||
ui,
|
||||
@@ -565,7 +565,7 @@ pub fn liquid(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Create"))).clicked()
|
||||
&& let Err(e) = app.run("layout.createAlternate", json!({"name": name, "width": w, "height": h}))
|
||||
{
|
||||
app.status(format!("Alternate layout: {e}"));
|
||||
app.status_error("Alternate layout", e);
|
||||
}
|
||||
ui.data_mut(|x| x.insert_temp(key, (name, w, h)));
|
||||
}
|
||||
@@ -598,7 +598,7 @@ pub fn media(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("place"))
|
||||
&& let Err(e) = app.run("media.options", json!({"poster": {"path": path}}))
|
||||
{
|
||||
app.status(format!("Media: {e}"));
|
||||
app.status_error("Media", e);
|
||||
}
|
||||
if !m["poster"].is_null() && ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "None"))).clicked() {
|
||||
let _ = app.run("media.options", json!({"poster": null}));
|
||||
|
||||
@@ -40,7 +40,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("library"))
|
||||
&& let Err(e) = app.run("library.open", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Library: {e}"));
|
||||
app.status_error("Library", e);
|
||||
}
|
||||
});
|
||||
let Ok(items) = app.session.execute("library.list", &json!({})) else {
|
||||
@@ -51,7 +51,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.add_enabled(has_sel, egui::Button::new(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Add Selection")))).clicked()
|
||||
&& let Err(e) = app.run("library.add", json!({}))
|
||||
{
|
||||
app.status(format!("Library: {e}"));
|
||||
app.status_error("Library", e);
|
||||
}
|
||||
ui.separator();
|
||||
let items = items.as_array().cloned().unwrap_or_default();
|
||||
@@ -77,7 +77,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Place"))).clicked()
|
||||
&& let Err(e) = app.run("library.place", json!({"index": i}))
|
||||
{
|
||||
app.status(format!("Library: {e}"));
|
||||
app.status_error("Library", e);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -93,13 +93,13 @@ pub fn book(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_save.as_mut().and_then(|f| f("Book.dcbook"))
|
||||
&& let Err(e) = app.run("book.new", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Book: {e}"));
|
||||
app.status_error("Book", e);
|
||||
}
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Open…"))).clicked()
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("book"))
|
||||
&& let Err(e) = app.run("book.open", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Book: {e}"));
|
||||
app.status_error("Book", e);
|
||||
}
|
||||
});
|
||||
let Ok(info) = app.session.execute("book.list", &json!({})) else {
|
||||
@@ -145,7 +145,7 @@ pub fn book(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_open.as_mut().and_then(|f| f("open"))
|
||||
&& let Err(e) = app.run("book.add", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Book: {e}"));
|
||||
app.status_error("Book", e);
|
||||
}
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Update Numbering"))).clicked() {
|
||||
let _ = app.run("book.paginate", json!({}));
|
||||
@@ -157,7 +157,7 @@ pub fn book(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some(path) = app.services.pick_save.as_mut().and_then(|f| f("Book.pdf"))
|
||||
&& let Err(e) = app.run("book.exportPdf", json!({"path": path}))
|
||||
{
|
||||
app.status(format!("Book: {e}"));
|
||||
app.status_error("Book", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -202,7 +202,7 @@ pub fn scripts(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
app.ui.scripts.push((name, text));
|
||||
sel = app.ui.scripts.len() - 1;
|
||||
}
|
||||
Err(e) => app.status(format!("Scripts: {e}")),
|
||||
Err(e) => app.status_error("Scripts", e),
|
||||
}
|
||||
}
|
||||
if ui
|
||||
@@ -222,7 +222,11 @@ pub fn scripts(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
&& let Some((name, text)) = app.ui.scripts.get(i).cloned()
|
||||
{
|
||||
match app.run("script.run", json!({"text": text})) {
|
||||
Ok(r) => app.status(format!("{name}: {} step(s) done", r["steps"])),
|
||||
Ok(r) => app.status(
|
||||
crate::i18n::tr(&app.ui.language, "{name}: {count} step(s) done")
|
||||
.replace("{name}", &name)
|
||||
.replace("{count}", &r["steps"].to_string()),
|
||||
),
|
||||
Err(e) => app.status(format!("{name}: {e}")),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
match app.run("note.new", json!({"text": draft.trim()})) {
|
||||
Ok(_) => draft.clear(),
|
||||
Err(e) => app.status(format!("Notes: {e}")),
|
||||
Err(e) => app.status_error("Notes", e),
|
||||
}
|
||||
}
|
||||
ui.data_mut(|d| d.insert_temp(id, draft));
|
||||
|
||||
@@ -780,7 +780,7 @@ fn convert_shape_menu(app: &mut DesignApp, resp: &egui::Response) {
|
||||
] {
|
||||
if ui.button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, label))).clicked() {
|
||||
if let Err(e) = app.run("object.convertShape", json!({"to": to})) {
|
||||
app.status(format!("Convert Shape: {e}"));
|
||||
app.status_error("Convert Shape", e);
|
||||
}
|
||||
ui.close();
|
||||
}
|
||||
@@ -1908,7 +1908,7 @@ pub fn links_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
{
|
||||
let r = app.run("links.relinkFolder", json!({"dir": dir.to_string_lossy()}));
|
||||
if let Ok(v) = r {
|
||||
app.status(format!("Relinked {}", v["relinked"]));
|
||||
app.status(crate::i18n::tr(&app.ui.language, "Relinked {count}").replace("{count}", &v["relinked"].to_string()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Graphic…"))).clicked()
|
||||
&& let Err(e) = app.run("app.graphicCell", json!({}))
|
||||
{
|
||||
app.status(format!("Table: {e}"));
|
||||
app.status_error("Table", e);
|
||||
}
|
||||
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Text"))).clicked() {
|
||||
let _ = app.run("table.textCell", json!({}));
|
||||
@@ -55,7 +55,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
if ui.add_enabled(ok, egui::Button::new(crate::rtl::widget(ui, label)).small()).clicked()
|
||||
&& let Err(e) = app.run(id, json!({"from": from, "to": to}))
|
||||
{
|
||||
app.status(format!("Table: {e}"));
|
||||
app.status_error("Table", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -145,7 +145,7 @@ pub fn show(app: &mut DesignApp, ui: &mut egui::Ui) {
|
||||
.clicked()
|
||||
&& let Err(e) = app.run("table.distributeRows", json!({}))
|
||||
{
|
||||
app.status(format!("Table: {e}"));
|
||||
app.status_error("Table", e);
|
||||
}
|
||||
divider(ui);
|
||||
caption(ui, crate::i18n::tr(&app.ui.language, "Cell Text"));
|
||||
|
||||
Reference in New Issue
Block a user