diff --git a/.gitignore b/.gitignore index 07d2ffd67..8d25c3a24 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ packaging/env.sh /packaging/linux/flatpak/cargo-sources.json /build-flatpak/ /.flatpak-builder/ +out-ru-i18n/ diff --git a/Cargo.lock b/Cargo.lock index e2bc79659..ad2e9089b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -905,6 +905,7 @@ dependencies = [ "log", "rfd", "serde_json", + "sys-locale", "winit", "winresource", ] @@ -4304,6 +4305,15 @@ dependencies = [ "syn 3.0.6", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + [[package]] name = "tempfile" version = "3.27.0" diff --git a/apps/deckcraft-web/Cargo.toml b/apps/deckcraft-web/Cargo.toml index 7014421d8..fa1171ed3 100644 --- a/apps/deckcraft-web/Cargo.toml +++ b/apps/deckcraft-web/Cargo.toml @@ -27,4 +27,4 @@ rfd = { workspace = true } wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" js-sys = "0.3" -web-sys = { version = "0.3", features = ["Window", "Document", "Element", "HtmlElement", "HtmlCanvasElement", "HtmlAnchorElement", "Blob", "BlobPropertyBag", "Url", "Location", "CssStyleDeclaration"] } +web-sys = { version = "0.3", features = ["Window", "Navigator", "Document", "Element", "HtmlElement", "HtmlCanvasElement", "HtmlAnchorElement", "Blob", "BlobPropertyBag", "Url", "Location", "CssStyleDeclaration"] } diff --git a/apps/deckcraft-web/src/web.rs b/apps/deckcraft-web/src/web.rs index dabad8af5..93fef2756 100644 --- a/apps/deckcraft-web/src/web.rs +++ b/apps/deckcraft-web/src/web.rs @@ -38,6 +38,7 @@ pub fn start() { } let inbox: Inbox = Inbox::default(); let mut app = SlideApp::new(Session::new(), services(inbox.clone(), cc.egui_ctx.clone())); + app.services.system_locale = web_sys::window().and_then(|w| w.navigator().language()); let q = query(); if !q.contains("blank") { if let Err(e) = deckcraft_engine::sample::open_sample(&mut app.session) { @@ -118,10 +119,10 @@ fn services(inbox: Inbox, ctx: egui::Context) -> Services { let inbox = open_inbox.clone(); let ctx = ctx.clone(); let dialog = match purpose { - "picture" => rfd::AsyncFileDialog::new().add_filter("Pictures", PICTURE_EXTS), - "audio" => rfd::AsyncFileDialog::new().add_filter("Audio", AUDIO_EXTS), - "video" => rfd::AsyncFileDialog::new().add_filter("Video", VIDEO_EXTS), - _ => rfd::AsyncFileDialog::new().add_filter("Presentations", PRESENTATION_EXTS), + "picture" => rfd::AsyncFileDialog::new().add_filter(deckcraft_ui_egui::i18n::tr("Pictures"), PICTURE_EXTS), + "audio" => rfd::AsyncFileDialog::new().add_filter(deckcraft_ui_egui::i18n::tr("Audio"), AUDIO_EXTS), + "video" => rfd::AsyncFileDialog::new().add_filter(deckcraft_ui_egui::i18n::tr("Video"), VIDEO_EXTS), + _ => rfd::AsyncFileDialog::new().add_filter(deckcraft_ui_egui::i18n::tr("Presentations"), PRESENTATION_EXTS), }; wasm_bindgen_futures::spawn_local(async move { let Some(file) = dialog.pick_file().await else { diff --git a/apps/deckcraft/Cargo.toml b/apps/deckcraft/Cargo.toml index 26ea30812..bbfaf9db0 100644 --- a/apps/deckcraft/Cargo.toml +++ b/apps/deckcraft/Cargo.toml @@ -11,6 +11,7 @@ default-run = "deckcraft" workspace = true [dependencies] +sys-locale = "0.3.2" deckcraft-engine = { workspace = true } deckcraft-ui-egui = { workspace = true } deckcraft-media = { workspace = true } diff --git a/apps/deckcraft/src/main.rs b/apps/deckcraft/src/main.rs index ef80daaa6..2a9e7e874 100644 --- a/apps/deckcraft/src/main.rs +++ b/apps/deckcraft/src/main.rs @@ -92,21 +92,22 @@ fn save_prefs(app: &SlideApp) { fn services() -> Services { Services { + system_locale: sys_locale::get_locale(), pick_open: Some(Box::new(|purpose: &str| { let d = rfd::FileDialog::new(); let d = match purpose { - "picture" => d.add_filter("Pictures", &["png", "jpg", "jpeg", "gif", "webp", "bmp", "tif", "tiff"]), + "picture" => d.add_filter(deckcraft_ui_egui::i18n::tr("Pictures"), &["png", "jpg", "jpeg", "gif", "webp", "bmp", "tif", "tiff"]), "audio" => d.add_filter( - "Audio", + deckcraft_ui_egui::i18n::tr("Audio"), &["wav", "mp3", "m4a", "m4b", "aac", "flac", "ogg", "oga", "opus", "aif", "aiff", "aifc", "caf", "wma", "weba", "mka"], ), - "video" => d.add_filter("Video", &["mp4", "m4v", "mov", "webm", "mkv", "wmv"]), + "video" => d.add_filter(deckcraft_ui_egui::i18n::tr("Video"), &["mp4", "m4v", "mov", "webm", "mkv", "wmv"]), "theme" => d.add_filter("Themes and presentations", &["thmx", "pptx", "potx", "ppsx"]).add_filter("Office Theme", &["thmx"]), _ => d - .add_filter("Presentations", &["deckcraft", "pptx", "potx", "ppsx"]) + .add_filter(deckcraft_ui_egui::i18n::tr("Presentations"), &["deckcraft", "pptx", "potx", "ppsx"]) .add_filter("DeckCraft", &["deckcraft"]) .add_filter("PowerPoint", &["pptx", "potx", "ppsx"]) - .add_filter("Outline", &["txt", "md"]), + .add_filter(deckcraft_ui_egui::i18n::tr("Outline"), &["txt", "md"]), }; d.pick_file().map(|p| p.to_string_lossy().to_string()) })), @@ -243,7 +244,8 @@ fn main() -> eframe::Result { if let Ok(v) = app.session.execute("file.recovery.open", &serde_json::json!({})) && let Some(n) = v.get("opened").and_then(|o| o.as_array()).map(Vec::len).filter(|n| *n > 0) { - app.set_status(format!("Recovered {n} unsaved presentation{} from the last session", if n == 1 { "" } else { "s" })); + deckcraft_ui_egui::i18n::set_current(app.ui.interface_language.resolve(app.services.system_locale.as_deref())); + app.set_status(deckcraft_ui_egui::i18n::recovered(n)); } } app.integrated_titlebar = cfg!(target_os = "macos"); diff --git a/crates/render/src/lib.rs b/crates/render/src/lib.rs index 93b0dc955..b8bd9a225 100644 --- a/crates/render/src/lib.rs +++ b/crates/render/src/lib.rs @@ -214,6 +214,8 @@ pub struct RenderOpts<'a> { pub scale: f64, /// Editor view: placeholder prompts and dashed placeholder outlines. pub edit: bool, + /// Optional interface prompt provider; custom layout prompts and document text stay intact. + pub placeholder_prompt: Option &'static str>, /// Draw shapes marked hidden (Selection pane) — the editor hides them like the show does. pub show_hidden: bool, /// Per-shape animation state. @@ -245,6 +247,7 @@ impl Default for RenderOpts<'_> { RenderOpts { scale: 1.0, edit: false, + placeholder_prompt: None, show_hidden: false, state: None, skip: &[], @@ -1331,7 +1334,7 @@ impl Renderer { } } else if f.opts.edit && s.ph.is_some() { let kind = s.ph_type().unwrap_or(PhType::Body); - let prompt_body = prompt_body(rctx, s, kind); + let prompt_body = prompt_body(rctx, s, kind, f.opts.placeholder_prompt.map(|prompt| prompt(kind))); if !prompt_body.is_empty() { let grey = Rgba::rgb(0x59, 0x59, 0x59); draw_text(ctx, rctx, s, &prompt_body, tr, m, &f.fields, Some(grey)); @@ -1995,7 +1998,7 @@ fn arrowheads(ctx: &mut RenderContext, rctx: &Ctx, line: &Line, ph: Option } /// The prompt shown in an empty placeholder, formatted like its content would be. -fn prompt_body(rctx: &Ctx, s: &Shape, kind: PhType) -> TextBody { +fn prompt_body(rctx: &Ctx, s: &Shape, kind: PhType, interface_prompt: Option<&str>) -> TextBody { // Layout/master prompt text when the layout supplies a custom one. let (lp, _) = resolve::parents(rctx, s); let custom = lp.and_then(|l| l.ph.as_ref().filter(|p| p.has_custom_prompt).and(l.text.as_ref())).filter(|t| !t.is_empty()); @@ -2005,7 +2008,7 @@ fn prompt_body(rctx: &Ctx, s: &Shape, kind: PhType) -> TextBody { if matches!(rctx.owner, resolve::Owner::Layout | resolve::Owner::Master) { return TextBody::default(); } - let txt = kind.prompt(); + let txt = interface_prompt.unwrap_or_else(|| kind.prompt()); if txt.is_empty() || kind.is_footer_kind() { return TextBody::default(); } diff --git a/crates/render/src/tests.rs b/crates/render/src/tests.rs index 05d7c91ab..7fdd09b86 100644 --- a/crates/render/src/tests.rs +++ b/crates/render/src/tests.rs @@ -880,6 +880,28 @@ fn hyperlinks_draw_in_the_hyperlink_colour_underlined() { assert_eq!(diff(&own, &px(&run_deck(RunProps { fill: red, underline: Some("sng".into()), ..Default::default() }))), 0); } +#[test] +fn interface_placeholder_prompts_preserve_custom_prompts_and_document_data() { + let mut p = Presentation::default(); + let slide = p.slides.first().unwrap(); + let shape = slide.shapes.iter().find(|shape| shape.ph_type() == Some(PhType::Title) || shape.ph_type() == Some(PhType::CtrTitle)).unwrap(); + let c = Ctx::for_slide(&p, slide).unwrap(); + let before = p.clone(); + assert_eq!(prompt_body(&c, shape, PhType::Title, Some("Натисніть, щоб додати заголовок")).text(), "Натисніть, щоб додати заголовок"); + assert_eq!(p, before); + + let layout_id = slide.layout; + let master = Arc::make_mut(p.masters.first_mut().unwrap()); + let layout = master.layouts.iter_mut().find(|layout| layout.id == layout_id).unwrap(); + let shape = layout.shapes.iter_mut().find(|shape| shape.ph_type() == Some(PhType::Title) || shape.ph_type() == Some(PhType::CtrTitle)).unwrap(); + shape.ph.as_mut().unwrap().has_custom_prompt = true; + shape.text = Some(TextBody::from_text("Click to add title")); + let slide = p.slides.first().unwrap(); + let shape = slide.shapes.iter().find(|shape| shape.ph_type() == Some(PhType::Title) || shape.ph_type() == Some(PhType::CtrTitle)).unwrap(); + let c = Ctx::for_slide(&p, slide).unwrap(); + assert_eq!(prompt_body(&c, shape, PhType::Title, Some("Натисніть, щоб додати заголовок")).text(), "Click to add title"); +} + #[test] fn a_linear_gradient_ramps_like_powerpoint() { // Black to white, left to right: PowerPoint draws 105 a quarter of the way and 186 half way diff --git a/crates/render/src/transition.rs b/crates/render/src/transition.rs index bd6e33175..55cacf236 100644 --- a/crates/render/src/transition.rs +++ b/crates/render/src/transition.rs @@ -101,6 +101,7 @@ fn copy_opts<'a>(o: &RenderOpts<'a>) -> RenderOpts<'a> { RenderOpts { scale: o.scale, edit: o.edit, + placeholder_prompt: o.placeholder_prompt, show_hidden: o.show_hidden, state: o.state, skip: o.skip, diff --git a/crates/ui-egui/src/canvas.rs b/crates/ui-egui/src/canvas.rs index ba66aad81..3ff9c19f0 100644 --- a/crates/ui-egui/src/canvas.rs +++ b/crates/ui-egui/src/canvas.rs @@ -102,7 +102,7 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { let Some(st) = app.session.active() else { return }; if st.doc.slides.is_empty() && st.selection.target == Target::Slides { let resp = ui.allocate_rect(avail, Sense::click()); - ui.painter().text(avail.center(), Align2::CENTER_CENTER, "Click to add first slide", theme::font(22.0), t.text_dim); + ui.painter().text(avail.center(), Align2::CENTER_CENTER, crate::i18n::tr("Click to add first slide"), theme::font(22.0), t.text_dim); if resp.clicked() { let _ = app.run("slide.new", json!({"layout": "title"})); } @@ -454,7 +454,7 @@ fn ruler(p: &egui::Painter, avail: Rect, slide: Rect, scale: f32, t: &Tokens) { }; p.line_segment([pos2(x, top.max.y - h), pos2(x, top.max.y)], Stroke::new(1.0, t.text_faint)); if k % 4 == 0 { - p.text(pos2(x + 2.0, top.min.y + 1.0), Align2::LEFT_TOP, format!("{}", k / 4), theme::font(8.0), t.text_dim); + p.text(pos2(x + 2.0, top.min.y + 1.0), Align2::LEFT_TOP, (k / 4).to_string(), theme::font(8.0), t.text_dim); } k += 1; } @@ -1175,7 +1175,7 @@ fn context_menu(app: &mut SlideApp, resp: &egui::Response) { } let has_sel = app.session.active().is_some_and(|d| !d.selection.shapes.is_empty()); for (l, id) in [("Cut", "edit.cut"), ("Copy", "edit.copy"), ("Paste", "edit.paste")] { - if ui.add_enabled(crate::ribbon::enabled(app, id), egui::Button::new(l)).clicked() { + if ui.add_enabled(crate::ribbon::enabled(app, id), egui::Button::new(crate::i18n::tr(l))).clicked() { let _ = app.run(id, json!({})); ui.close(); } @@ -1184,59 +1184,59 @@ fn context_menu(app: &mut SlideApp, resp: &egui::Response) { // Right-clicking the text being edited keeps it (`PointerKind::ContextClick`): text items. let editing = app.session.active().is_some_and(|d| d.selection.text.as_ref().is_some_and(|t| !t.notes)); if editing { - if ui.button("Paragraph…").clicked() { + if ui.button(crate::i18n::tr("Paragraph…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("paragraph")); ui.close(); } for (l, id) in [("Bullets", "format.bullets"), ("Numbering", "format.numbering")] { - if ui.add_enabled(crate::ribbon::enabled(app, id), egui::Button::new(l)).clicked() { + if ui.add_enabled(crate::ribbon::enabled(app, id), egui::Button::new(crate::i18n::tr(l))).clicked() { let _ = app.run(id, json!({})); ui.close(); } } - if ui.button("Link…").clicked() { + if ui.button(crate::i18n::tr("Link…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("hyperlink")); ui.close(); } ui.separator(); - if ui.button("Format Shape…").clicked() { + if ui.button(crate::i18n::tr("Format Shape…")).clicked() { let _ = app.run("view.pane", json!({"pane": "format"})); ui.close(); } } else if has_sel { - if ui.button("Edit Text").clicked() { + if ui.button(crate::i18n::tr("Edit Text")).clicked() { let _ = app.run("text.edit", json!({})); ui.close(); } if crate::ribbon::enabled(app, "shape.editPoints") && app.session.active().is_some_and(|d| d.selection.shapes.len() == 1 && d.selected_shapes().iter().all(|s| !s.is_line())) - && ui.button("Edit Points").clicked() + && ui.button(crate::i18n::tr("Edit Points")).clicked() { let _ = app.run("shape.editPoints", json!({"on": true})); ui.close(); } - if ui.button("Font…").clicked() { + if ui.button(crate::i18n::tr("Font…")).clicked() { let _ = app.run("format.fontDialog", json!({})); ui.close(); } - if ui.button("Paragraph…").clicked() { + if ui.button(crate::i18n::tr("Paragraph…")).clicked() { let _ = app.run("format.paragraphDialog", json!({})); ui.close(); } - ui.menu_button("Bring to Front", |ui| { + ui.menu_button(crate::i18n::tr("Bring to Front"), |ui| { crate::ribbon::menu_item(app, ui, crate::icons::Icon::BringToFront, "Bring to Front", "arrange.bringToFront", json!({})); crate::ribbon::menu_item(app, ui, crate::icons::Icon::BringForward, "Bring Forward", "arrange.bringForward", json!({})); }); - ui.menu_button("Send to Back", |ui| { + ui.menu_button(crate::i18n::tr("Send to Back"), |ui| { crate::ribbon::menu_item(app, ui, crate::icons::Icon::SendToBack, "Send to Back", "arrange.sendToBack", json!({})); crate::ribbon::menu_item(app, ui, crate::icons::Icon::SendBackward, "Send Backward", "arrange.sendBackward", json!({})); }); - ui.menu_button("Group", |ui| { + ui.menu_button(crate::i18n::tr("Group"), |ui| { crate::ribbon::menu_item(app, ui, crate::icons::Icon::Group, "Group", "arrange.group", json!({})); crate::ribbon::menu_item(app, ui, crate::icons::Icon::Ungroup, "Ungroup", "arrange.ungroup", json!({})); }); let locked = app.session.active().is_some_and(|d| d.selected_shapes().iter().all(|s| s.locked)); - if ui.button(if locked { "Unlock" } else { "Lock" }).clicked() { + if ui.button(if locked { crate::i18n::tr("Unlock") } else { crate::i18n::tr("Lock") }).clicked() { let _ = app.run("shape.lock", json!({"locked": !locked})); ui.close(); } @@ -1244,32 +1244,32 @@ fn context_menu(app: &mut SlideApp, resp: &egui::Response) { .session .active() .is_some_and(|d| d.selected_shapes().iter().any(|s| matches!(s.kind, deckcraft_model::ShapeKind::Picture { .. }))); - if picture && ui.button("Change Picture…").clicked() { + if picture && ui.button(crate::i18n::tr("Change Picture…")).clicked() { let _ = app.run("app.changePictureDialog", json!({})); ui.close(); } - if ui.button("Link…").clicked() { + if ui.button(crate::i18n::tr("Link…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("hyperlink")); ui.close(); } - if ui.button("Edit Alt Text…").clicked() { + if ui.button(crate::i18n::tr("Edit Alt Text…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("altText")); ui.close(); } - if ui.button("Set as Default Shape").clicked() { + if ui.button(crate::i18n::tr("Set as Default Shape")).clicked() { let _ = app.run("shape.setDefault", json!({})); ui.close(); } - if ui.button("Size and Position…").clicked() { + if ui.button(crate::i18n::tr("Size and Position…")).clicked() { let _ = app.run("shape.sizePosition", json!({})); ui.close(); } - if ui.button("Format Shape…").clicked() { + if ui.button(crate::i18n::tr("Format Shape…")).clicked() { let _ = app.run("view.pane", json!({"pane": "format"})); ui.close(); } } else { - ui.menu_button("Layout", |ui| { + ui.menu_button(crate::i18n::tr("Layout"), |ui| { let layouts: Vec<(String, u32)> = app .session .active() @@ -1282,28 +1282,28 @@ fn context_menu(app: &mut SlideApp, resp: &egui::Response) { } } }); - ui.menu_button("Grid and Guides", |ui| { + ui.menu_button(crate::i18n::tr("Grid and Guides"), |ui| { let mut on = app.ui.guides; - if ui.checkbox(&mut on, "Guides").clicked() { + if ui.checkbox(&mut on, crate::i18n::tr("Guides")).clicked() { let _ = app.run("view.guides", json!({"on": on})); } for (label, vertical) in [("Add Vertical Guide", true), ("Add Horizontal Guide", false)] { - if ui.button(label).clicked() { + if ui.button(crate::i18n::tr(label)).clicked() { let _ = app.run("guide.add", json!({"vertical": vertical})); let _ = app.run("view.guides", json!({"on": true})); ui.close(); } } }); - if ui.button("Reset Slide").clicked() { + if ui.button(crate::i18n::tr("Reset Slide")).clicked() { let _ = app.run("slide.reset", json!({})); ui.close(); } - if ui.button("Format Background…").clicked() { + if ui.button(crate::i18n::tr("Format Background…")).clicked() { let _ = app.run("view.pane", json!({"pane": "background"})); ui.close(); } - if ui.button("New Comment").clicked() { + if ui.button(crate::i18n::tr("New Comment")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("comment")); ui.close(); } diff --git a/crates/ui-egui/src/credits.rs b/crates/ui-egui/src/credits.rs index 765dec19d..b7f01233b 100644 --- a/crates/ui-egui/src/credits.rs +++ b/crates/ui-egui/src/credits.rs @@ -123,18 +123,20 @@ impl Contributor { /// One line with everything we know, for tooltips. pub fn summary(&self) -> String { - format!( + crate::i18n::format( "@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {}", - self.login, - self.prs, - self.commits, - group(self.lines_added), - group(self.lines_deleted), - signed(self.lines_delta()), - self.binary_added, - self.binary_deleted, - day(self.first_commit), - day(self.last_commit), + &[ + (self.login).to_string(), + (self.prs).to_string(), + (self.commits).to_string(), + (group(self.lines_added)).to_string(), + (group(self.lines_deleted)).to_string(), + (signed(self.lines_delta())).to_string(), + (self.binary_added).to_string(), + (self.binary_deleted).to_string(), + (day(self.first_commit)).to_string(), + (day(self.last_commit)).to_string(), + ], ) } } @@ -215,39 +217,43 @@ pub fn contributors_ui(ui: &mut egui::Ui) { let id = egui::Id::new("credits_view"); let mut v = ui.data_mut(|d| d.get_temp::(id)).unwrap_or_default(); ui.horizontal_wrapped(|ui| { - ui.label("Show"); + ui.label(crate::i18n::tr("Show")); for m in NameMode::ALL { - if ui.selectable_label(v.names == m, m.label()).clicked() { + if ui.selectable_label(v.names == m, crate::i18n::tr(m.label())).clicked() { v.names = m; } } ui.separator(); - ui.label("Sort"); - egui::ComboBox::from_id_salt("credits_sort").selected_text(v.key.label().0).show_ui(ui, |ui| { + ui.label(crate::i18n::tr("Sort")); + egui::ComboBox::from_id_salt("credits_sort").selected_text(crate::i18n::tr(v.key.label().0)).show_ui(ui, |ui| { for k in SortKey::ALL { - if ui.selectable_label(v.key == k, k.label().0).clicked() { + if ui.selectable_label(v.key == k, crate::i18n::tr(k.label().0)).clicked() { v.key = k; v.ascending = k.default_ascending(); } } }); - if ui.button(if v.ascending { "▲" } else { "▼" }).on_hover_text("Reverse the order").clicked() { + if ui.button(if v.ascending { "▲" } else { "▼" }).on_hover_text(crate::i18n::tr("Reverse the order")).clicked() { v.ascending = !v.ascending; } ui.separator(); - if ui.selectable_label(!v.table, "Grab bag").clicked() { + if ui.selectable_label(!v.table, crate::i18n::tr("Grab bag")).clicked() { v.table = false; } - if ui.selectable_label(v.table, "Table").clicked() { + if ui.selectable_label(v.table, crate::i18n::tr("Table")).clicked() { v.table = true; } }); let list = sorted(CONTRIBUTORS, v.names, v.key, v.ascending); - ui.label(RichText::new(format!("{} contributors · {} commits", list.len(), group(TOTAL_COMMITS))).small().weak()); + ui.label( + RichText::new(crate::i18n::format("{} contributors · {} commits", &[(list.len()).to_string(), (group(TOTAL_COMMITS)).to_string()])) + .small() + .weak(), + ); ui.separator(); egui::ScrollArea::both().auto_shrink([false, false]).show(ui, |ui| { if list.is_empty() { - ui.label("No contributor data was built into this copy."); + ui.label(crate::i18n::tr("No contributor data was built into this copy.")); } else if v.table { table(ui, &list, &mut v); } else { @@ -268,7 +274,11 @@ fn table(ui: &mut egui::Ui, list: &[&Contributor], v: &mut View) { egui::Grid::new("credits_table").striped(true).num_columns(SortKey::ALL.len()).show(ui, |ui| { for k in SortKey::ALL { let arrow = if v.key == k { if v.ascending { " ▲" } else { " ▼" } } else { "" }; - if ui.button(RichText::new(format!("{}{arrow}", k.label().1)).strong()).on_hover_text(k.label().0).clicked() { + if ui + .button(RichText::new(format!("{}{arrow}", crate::i18n::tr(k.label().1))).strong()) + .on_hover_text(crate::i18n::tr(k.label().0)) + .clicked() + { if v.key == k { v.ascending = !v.ascending; } else { @@ -297,14 +307,14 @@ fn table(ui: &mut egui::Ui, list: &[&Contributor], v: &mut View) { /// About ▸ Models: AI models credited in Co-Authored-By trailers. pub fn models_ui(ui: &mut egui::Ui) { if MODELS.is_empty() { - ui.label("No model credits were built into this copy."); + ui.label(crate::i18n::tr("No model credits were built into this copy.")); return; } let assisted: u64 = MODELS.iter().map(|m| m.commits).max().unwrap_or(0).max(1); egui::ScrollArea::both().auto_shrink([false, false]).show(ui, |ui| { egui::Grid::new("credits_models").striped(true).num_columns(6).show(ui, |ui| { for h in ["Company", "Model", "Version", "Commits", "% of all commits", "Lines +/−"] { - ui.label(RichText::new(h).strong()); + ui.label(RichText::new(crate::i18n::tr(h)).strong()); } ui.end_row(); for m in MODELS { diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 576a22979..d1c47b559 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -79,7 +79,7 @@ pub fn show(app: &mut SlideApp, ctx: &egui::Context) { let Some(mut d) = app.dialog.take() else { return }; let mut open = true; let mut close = false; - let mut window = egui::Window::new(title(&d.id)) + let mut window = egui::Window::new(crate::i18n::tr(title(&d.id))) .id(egui::Id::new(("dialog", d.id.clone()))) .collapsible(false) .resizable(false) @@ -128,12 +128,14 @@ fn buttons(ui: &mut Ui, ok_label: &str) -> (bool, bool) { ui.add_space(8.0); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { let t = Tokens::get(ui.ctx()); - if ui.add(egui::Button::new(egui::RichText::new(ok_label).color(t.accent_text)).fill(t.accent).min_size(vec2(72.0, 24.0))).clicked() + if ui + .add(egui::Button::new(egui::RichText::new(crate::i18n::tr(ok_label)).color(t.accent_text)).fill(t.accent).min_size(vec2(72.0, 24.0))) + .clicked() || ui.input(|i| i.key_pressed(egui::Key::Enter)) { ok = true; } - if ui.add(egui::Button::new("Cancel").min_size(vec2(72.0, 24.0))).clicked() { + if ui.add(egui::Button::new(crate::i18n::tr("Cancel")).min_size(vec2(72.0, 24.0))).clicked() { cancel = true; } }); @@ -168,7 +170,7 @@ fn restore_preferences(app: &mut SlideApp, d: &Dialog) { fn field(ui: &mut Ui, d: &mut Dialog, label: &str, key: &str, default: &str) { let mut v = d.get(key, default); ui.horizontal(|ui| { - ui.add_sized(vec2(120.0, 20.0), egui::Label::new(label)); + ui.add_sized(vec2(120.0, 20.0), egui::Label::new(crate::i18n::tr(label))); ui.add(egui::TextEdit::singleline(&mut v).desired_width(180.0)); }); d.fields.insert(key.into(), v); @@ -188,7 +190,7 @@ fn alt_text_starts_decorative(decorative: impl IntoIterator) -> boo fn check(ui: &mut Ui, d: &mut Dialog, label: &str, key: &str, default: bool) -> bool { let mut v = d.get(key, if default { "1" } else { "0" }) == "1"; - ui.checkbox(&mut v, label); + ui.checkbox(&mut v, crate::i18n::tr(label)); d.fields.insert(key.into(), if v { "1".into() } else { "0".into() }); v } @@ -1039,17 +1041,20 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { } "slideSize" => { let cur = app.session.active().map(|s| s.doc.slide_size).unwrap_or(deckcraft_model::defaults::WIDE); - ui.label("Slides sized for:"); + ui.label(crate::i18n::tr("Slides sized for:")); let preset = d.get("preset", ""); - egui::ComboBox::from_id_salt("sizes").selected_text(if preset.is_empty() { "Custom" } else { &preset }).show_ui(ui, |ui| { - for (label, w, h) in deckcraft_model::defaults::SLIDE_SIZES { - if ui.selectable_label(preset == *label, *label).clicked() { - d.fields.insert("preset".into(), label.to_string()); - d.fields.insert("w".into(), format!("{:.2}", w / 72.0)); - d.fields.insert("h".into(), format!("{:.2}", h / 72.0)); + egui::ComboBox::from_id_salt("sizes").selected_text(crate::i18n::tr(if preset.is_empty() { "Custom" } else { &preset })).show_ui( + ui, + |ui| { + for (label, w, h) in deckcraft_model::defaults::SLIDE_SIZES { + if ui.selectable_label(preset == *label, crate::i18n::tr(label)).clicked() { + d.fields.insert("preset".into(), label.to_string()); + d.fields.insert("w".into(), format!("{:.2}", w / 72.0)); + d.fields.insert("h".into(), format!("{:.2}", h / 72.0)); + } } - } - }); + }, + ); field(ui, d, "Width (in):", "w", &format!("{:.2}", cur.width / 72.0)); field(ui, d, "Height (in):", "h", &format!("{:.2}", cur.height / 72.0)); let (w, h) = (num(d, "w", cur.width / 72.0), num(d, "h", cur.height / 72.0)); @@ -1084,9 +1089,9 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let mut apply_all = false; let mut apply = false; ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - apply_all = ui.button("Apply to All").clicked(); - apply = ui.button("Apply").clicked(); - if ui.button("Cancel").clicked() { + apply_all = ui.button(crate::i18n::tr("Apply to All")).clicked(); + apply = ui.button(crate::i18n::tr("Apply")).clicked(); + if ui.button(crate::i18n::tr("Cancel")).clicked() { d.fields.insert("cancel".into(), "1".into()); } }); @@ -1106,13 +1111,13 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let slide_default = seed.slide.to_string(); let mode = d.get("mode", seed.mode); ui.horizontal(|ui| { - if ui.selectable_label(mode == "url", "Web Page or File").clicked() { + if ui.selectable_label(mode == "url", crate::i18n::tr("Web Page or File")).clicked() { d.fields.insert("mode".into(), "url".into()); } - if ui.selectable_label(mode == "slide", "This Document").clicked() { + if ui.selectable_label(mode == "slide", crate::i18n::tr("This Document")).clicked() { d.fields.insert("mode".into(), "slide".into()); } - if ui.selectable_label(mode == "email", "Email Address").clicked() { + if ui.selectable_label(mode == "email", crate::i18n::tr("Email Address")).clicked() { d.fields.insert("mode".into(), "email".into()); } }); @@ -1152,13 +1157,13 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { "setupShow" => { let sh = app.session.active().map(|s| s.doc.show.clone()).unwrap_or_default(); let ty = d.get("type", &sh.show_type); - ui.label("Show type"); + ui.label(crate::i18n::tr("Show type")); for (l, v) in [ ("Presented by a speaker (full screen)", "speaker"), ("Browsed by an individual (window)", "browsed"), ("Browsed at a kiosk (full screen)", "kiosk"), ] { - if ui.radio(ty == v, l).clicked() { + if ui.radio(ty == v, crate::i18n::tr(l)).clicked() { d.fields.insert("type".into(), v.into()); } } @@ -1195,21 +1200,31 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); return true; } - let what = if names.len() == 1 { format!("“{}”", names[0]) } else { format!("{} presentations", names.len()) }; - ui.label(egui::RichText::new(format!("Do you want to save the changes you made to {what}?")).strong()); - ui.label("Your changes will be lost if you don't save them."); + let what = if names.len() == 1 { + format!("“{}”", names[0]) + } else { + crate::i18n::count(names.len(), ("presentation", "presentations"), ["презентації", "презентацій", "презентацій"], ["презентацию", "презентации", "презентаций"], ("presentación", "presentaciones"), ("présentation", "présentations"), ("apresentação", "apresentações"), ("Präsentation", "Präsentationen")) + }; + ui.label( + egui::RichText::new(crate::i18n::format("Do you want to save the changes you made to {what}?", std::slice::from_ref(&what))).strong(), + ); + ui.label(crate::i18n::tr("Your changes will be lost if you don't save them.")); ui.add_space(8.0); let mut done = false; ui.horizontal(|ui| { let t = Tokens::get(ui.ctx()); - if ui.add(egui::Button::new("Don't Save").min_size(vec2(84.0, 24.0))).clicked() { + if ui.add(egui::Button::new(crate::i18n::tr("Don't Save")).min_size(vec2(84.0, 24.0))).clicked() { let _ = app.session.execute("file.recovery.discard", &json!({})); app.quit_confirmed = true; ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); done = true; } ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - let save = ui.add(egui::Button::new(egui::RichText::new("Save").color(t.accent_text)).fill(t.accent).min_size(vec2(72.0, 24.0))); + let save = ui.add( + egui::Button::new(egui::RichText::new(crate::i18n::tr("Save")).color(t.accent_text)) + .fill(t.accent) + .min_size(vec2(72.0, 24.0)), + ); if save.clicked() || ui.input(|i| i.key_pressed(egui::Key::Enter)) { if app.save_all() { app.quit_confirmed = true; @@ -1217,7 +1232,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { } done = true; } - if ui.add(egui::Button::new("Cancel").min_size(vec2(72.0, 24.0))).clicked() { + if ui.add(egui::Button::new(crate::i18n::tr("Cancel")).min_size(vec2(72.0, 24.0))).clicked() { done = true; } }); @@ -1238,7 +1253,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { done = true; } ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - let save = ui.add(egui::Button::new(egui::RichText::new("Save").color(t.accent_text)).fill(t.accent).min_size(vec2(72.0, 24.0))); + let save = ui.add(egui::Button::new(egui::RichText::new(crate::i18n::tr("Save")).color(t.accent_text)).fill(t.accent).min_size(vec2(72.0, 24.0))); if save.clicked() || ui.input(|i| i.key_pressed(egui::Key::Enter)) { app.save(); // In the browser a save is a download: the presentation stays "unsaved". @@ -1248,7 +1263,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { } done = true; } - if ui.add(egui::Button::new("Cancel").min_size(vec2(72.0, 24.0))).clicked() { + if ui.add(egui::Button::new(crate::i18n::tr("Cancel")).min_size(vec2(72.0, 24.0))).clicked() { done = true; } }); @@ -1258,7 +1273,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { "zoom" => zoom_dialog(app, ui, d), "comment" => { let mut v = d.get("text", ""); - ui.add(egui::TextEdit::multiline(&mut v).hint_text("Start a conversation").desired_rows(4).desired_width(320.0)); + ui.add(egui::TextEdit::multiline(&mut v).hint_text(crate::i18n::tr("Start a conversation")).desired_rows(4).desired_width(320.0)); d.fields.insert("text".into(), v.clone()); let (ok, cancel) = buttons(ui, "Post"); if ok && !v.trim().is_empty() { @@ -1500,7 +1515,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { (cur, deco) }) .unwrap_or_default(); - ui.label("How would you describe this object and its context to someone who is blind or has low vision?"); + ui.label(crate::i18n::tr("How would you describe this object and its context to someone who is blind or has low vision?")); let mut v = d.get("text", &cur); ui.add(egui::TextEdit::multiline(&mut v).desired_rows(4).desired_width(340.0)); d.fields.insert("text".into(), v.clone()); @@ -1512,7 +1527,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ok || cancel } "outline" => { - ui.label("Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets."); + ui.label(crate::i18n::tr("Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets.")); let mut v = d.get("text", ""); ui.add(egui::TextEdit::multiline(&mut v).desired_rows(10).desired_width(380.0).code_editor()); d.fields.insert("text".into(), v.clone()); @@ -1540,7 +1555,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { "paragraph" => paragraph_dialog(app, ui, d), "tabs" => tabs_dialog(app, ui, d), "export" => { - ui.label("Export the presentation as:"); + ui.label(crate::i18n::tr("Export the presentation as:")); let fmt = d.get("fmt", "pdf"); for (l, f) in [ ("PDF document (.pdf)", "pdf"), @@ -1551,7 +1566,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ("Outline (.txt)", "outline"), ("Animated GIF (.gif)", "gif"), ] { - if ui.radio(fmt == f, l).clicked() { + if ui.radio(fmt == f, crate::i18n::tr(l)).clicked() { d.fields.insert("fmt".into(), f.into()); } } @@ -1559,7 +1574,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { if fmt == "pdf" { ui.add_space(4.0); ui.horizontal(|ui| { - ui.label("Print layout:"); + ui.label(crate::i18n::tr("Print layout:")); egui::ComboBox::from_id_salt("pdf_layout") .selected_text(match pdf_layout.as_str() { "notes" => "Notes Pages", @@ -1582,14 +1597,14 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ("h6", "Handouts (6 slides per page)"), ("h9", "Handouts (9 slides per page)"), ] { - if ui.selectable_label(pdf_layout == k, l).clicked() { + if ui.selectable_label(pdf_layout == k, crate::i18n::tr(l)).clicked() { d.fields.insert("pdfLayout".into(), k.into()); } } }); }); let mut hidden = d.get("pdfHidden", "false") == "true"; - if ui.checkbox(&mut hidden, "Include hidden slides").changed() { + if ui.checkbox(&mut hidden, crate::i18n::tr("Include hidden slides")).changed() { d.fields.insert("pdfHidden".into(), hidden.to_string()); } } @@ -1671,7 +1686,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { cancel } "symbol" => { - ui.label("Click a symbol to insert it at the insertion point."); + ui.label(crate::i18n::tr("Click a symbol to insert it at the insertion point.")); let groups: [(&str, &str); 6] = [ ("Punctuation", "–—‘’“”…•·§¶†‡‰′″‹›«»¡¿"), ("Currency", "$€£¥¢₹₩₽₺₿"), @@ -1681,7 +1696,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ("Shapes", "■□▪▫▲△▶▷▼▽◀◁◆◇○●◎★☆✓✔✗✘♠♣♥♦"), ]; for (g, chars) in groups { - ui.label(egui::RichText::new(g).font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr(g)).font(theme::bold(12.0))); ui.horizontal_wrapped(|ui| { for c in chars.chars() { if ui.add(egui::Button::new(egui::RichText::new(c.to_string()).size(16.0)).min_size(vec2(26.0, 26.0))).clicked() { @@ -1697,7 +1712,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ok || cancel } "equation" => { - ui.label("Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a)."); + ui.label(crate::i18n::tr("Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a).")); let mut v = d.get("eq", ""); ui.add(egui::TextEdit::singleline(&mut v).desired_width(340.0).font(theme::font(15.0))); d.fields.insert("eq".into(), v.clone()); @@ -1765,7 +1780,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ), }; if list.is_empty() { - ui.label("The spelling check is complete. No issues found."); + ui.label(crate::i18n::tr("The spelling check is complete. No issues found.")); } let mut add_ignore = None; egui::ScrollArea::vertical().max_height(320.0).show(ui, |ui| { @@ -1774,8 +1789,11 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let slide = item.get("slide").cloned().unwrap_or_default(); let shape = item.get("shape").cloned().unwrap_or_default(); ui.horizontal(|ui| { - ui.label(format!("Slide {}: “{w}”", slide.as_u64().unwrap_or(0) + 1)); - if ui.small_button("Go to").clicked() { + ui.label(crate::i18n::format( + "Slide {}: “{w}”", + &[(slide.as_u64().unwrap_or(0) + 1).to_string(), w.to_string()], + )); + if ui.small_button(crate::i18n::tr("Go to")).clicked() { let _ = app.run("slide.go", json!({"index": slide})); let _ = app.run("edit.select", json!({"ids": [shape]})); } @@ -1885,18 +1903,22 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let v = app.session.execute("review.accessibility", &json!({})).unwrap_or_default(); let list = v.as_array().cloned().unwrap_or_default(); if list.is_empty() { - ui.label("No accessibility issues found. People with disabilities should not have difficulty reading this document."); + ui.label(crate::i18n::tr( + "No accessibility issues found. People with disabilities should not have difficulty reading this document.", + )); } egui::ScrollArea::vertical().max_height(300.0).show(ui, |ui| { for item in &list { ui.horizontal(|ui| { - ui.label(format!( + ui.label(crate::i18n::format( "Slide {}: {}{}", - item.get("slide").and_then(Value::as_u64).unwrap_or(0) + 1, - item.get("issue").and_then(Value::as_str).unwrap_or(""), - item.get("name").and_then(Value::as_str).map(|n| format!(" — {n}")).unwrap_or_default() + &[ + (item.get("slide").and_then(Value::as_u64).unwrap_or(0) + 1).to_string(), + (item.get("issue").and_then(Value::as_str).unwrap_or("")).to_string(), + (item.get("name").and_then(Value::as_str).map(|n| format!(" — {n}")).unwrap_or_default()).to_string(), + ], )); - if ui.small_button("Go to").clicked() { + if ui.small_button(crate::i18n::tr("Go to")).clicked() { let _ = app.run("slide.go", json!({"index": item.get("slide").cloned().unwrap_or_default()})); if let Some(id) = item.get("shape") { let _ = app.run("edit.select", json!({"ids": [id]})); @@ -1913,7 +1935,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let (cur, np) = selected_language(app); let lang = d.get("lang", &cur); let mut no_proof = d.get("noProof", if np { "1" } else { "" }) == "1"; - ui.label("Mark selected text as:"); + ui.label(crate::i18n::tr("Mark selected text as:")); egui::ScrollArea::vertical().max_height(220.0).show(ui, |ui| { // The selection's own language first when the list doesn't have it. let own = (!crate::squiggles::LANGS.iter().any(|(_, t)| t.eq_ignore_ascii_case(&cur))).then(|| (cur.clone(), cur.clone())); @@ -1943,12 +1965,16 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let mut started = false; for s in &shows { ui.horizontal(|ui| { - ui.label(format!("{} ({} slides)", s.name, s.slides.len())); + ui.label(format!( + "{} ({})", + s.name, + crate::i18n::count(s.slides.len(), ("slide", "slides"), ["слайд", "слайди", "слайдів"], ["слайд", "слайда", "слайдов"], ("diapositiva", "diapositivas"), ("diapositive", "diapositives"), ("slide", "slides"), ("Folie", "Folien")) + )); if ui.small_button("Show").clicked() { run(app, "show.start", json!({"custom": s.name})); started = true; } - if ui.small_button("Delete").clicked() { + if ui.small_button(crate::i18n::tr("Delete")).clicked() { let _ = app.run("show.customShow", json!({"name": s.name, "delete": true})); } }); @@ -1973,11 +1999,11 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { .find_map(|x| if let deckcraft_model::ShapeKind::Chart(c) = &x.kind { Some(((**c).clone(), x.id)) } else { None }) }); let Some((c, id)) = ch else { - ui.label("Select a chart first."); + ui.label(crate::i18n::tr("Select a chart first.")); let (ok, cancel) = buttons(ui, "Close"); return ok || cancel; }; - ui.label("Edit the data: first row = series names, first column = categories."); + ui.label(crate::i18n::tr("Edit the data: first row = series names, first column = categories.")); let mut grid: Vec> = d.params.get("grid").and_then(|g| serde_json::from_value(g.clone()).ok()).unwrap_or_else(|| { let mut g = vec![std::iter::once(String::new()).chain(c.series.iter().map(|s| s.name.clone())).collect::>()]; for (i, cat) in c.categories.iter().enumerate() { @@ -1998,11 +2024,11 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { } }); ui.horizontal(|ui| { - if ui.button("+ Row").clicked() { + if ui.button(crate::i18n::tr("+ Row")).clicked() { let n = grid.first().map(|r| r.len()).unwrap_or(2); grid.push(vec![String::new(); n]); } - if ui.button("+ Series").clicked() { + if ui.button(crate::i18n::tr("+ Series")).clicked() { for r in grid.iter_mut() { r.push(String::new()); } @@ -2040,7 +2066,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ok || cancel } "smartart" => { - ui.label("Pick a graphic; type one item per line."); + ui.label(crate::i18n::tr("Pick a graphic; type one item per line.")); let kind = d.get("kind", "process"); ui.horizontal_wrapped(|ui| { for (k, l) in [ @@ -2051,7 +2077,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { ("pyramid", "Pyramid"), ("matrix", "Matrix"), ] { - if ui.selectable_label(kind == k, l).clicked() { + if ui.selectable_label(kind == k, crate::i18n::tr(l)).clicked() { d.fields.insert("kind".into(), k.into()); } } @@ -2070,7 +2096,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let tab = d.get("tab", "about"); ui.horizontal(|ui| { for (k, l) in [("about", "About"), ("contributors", "Contributors"), ("models", "Models")] { - if ui.selectable_label(tab == k, l).clicked() { + if ui.selectable_label(tab == k, crate::i18n::tr(l)).clicked() { d.fields.insert("tab".into(), k.into()); } } @@ -2137,9 +2163,9 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { if d.params.get("before").is_none() { d.params = json!({ "before": preferences_snapshot(app) }); } - ui.label(egui::RichText::new("General").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("General")).font(theme::bold(13.0))); let mut dark = app.ui.brightness == theme::Brightness::Dark; - if ui.checkbox(&mut dark, "Dark appearance").changed() { + if ui.checkbox(&mut dark, crate::i18n::tr("Dark appearance")).changed() { let _ = app.run("view.dark", json!({"on": dark})); } // While the pointer holds the slider its value only waits in the dialog: applying it @@ -2147,7 +2173,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { // on release, and at once from the keyboard. let pending = d.fields.get("uiScale").and_then(|v| v.parse::().ok()); let mut scale = pending.unwrap_or(app.ui.ui_scale); - let r = ui.add(egui::Slider::new(&mut scale, 0.75..=1.75).text("Interface size")); + let r = ui.add(egui::Slider::new(&mut scale, 0.75..=1.75).text(crate::i18n::tr("Interface size"))); if r.is_pointer_button_down_on() { if r.changed() || pending.is_some() { d.fields.insert("uiScale".into(), scale.to_string()); @@ -2158,12 +2184,12 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { } d.fields.remove("uiScale"); } - ui.label(egui::RichText::new("Editing").font(theme::bold(13.0))); - ui.checkbox(&mut app.session.prefs.smart_guides, "Show smart guides"); - ui.checkbox(&mut app.session.prefs.snap_to_grid, "Snap objects to grid"); - ui.checkbox(&mut app.session.prefs.smart_quotes, "Replace straight quotes with smart quotes"); + ui.label(egui::RichText::new(crate::i18n::tr("Editing")).font(theme::bold(13.0))); + ui.checkbox(&mut app.session.prefs.smart_guides, crate::i18n::tr("Show smart guides")); + ui.checkbox(&mut app.session.prefs.snap_to_grid, crate::i18n::tr("Snap objects to grid")); + ui.checkbox(&mut app.session.prefs.smart_quotes, crate::i18n::tr("Replace straight quotes with smart quotes")); ui.horizontal(|ui| { - ui.checkbox(&mut app.session.prefs.autocorrect, "AutoCorrect as you type"); + ui.checkbox(&mut app.session.prefs.autocorrect, crate::i18n::tr("AutoCorrect as you type")); if ui.button("AutoCorrect Options…").clicked() { *d = Dialog::new("autocorrect"); } @@ -2172,7 +2198,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { return false; } ui.horizontal(|ui| { - ui.label("Your name (comments):"); + ui.label(crate::i18n::tr("Your name (comments):")); ui.text_edit_singleline(&mut app.session.prefs.author); }); let (ok, cancel) = buttons(ui, "Done"); @@ -2186,7 +2212,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { "themeFonts" => theme_fonts_dialog(app, ui, d), "dateTime" => date_time_dialog(app, ui, d), _ => { - ui.label(format!("“{}” is not available yet.", d.id)); + ui.label(crate::i18n::format("“{}” is not available yet.", std::slice::from_ref(&d.id))); let (ok, cancel) = buttons(ui, "OK"); ok || cancel } @@ -2607,17 +2633,21 @@ pub fn about(_app: &mut SlideApp, ui: &mut Ui) { ui.vertical_centered(|ui| { let (r, _) = ui.allocate_exact_size(vec2(64.0, 64.0), Sense::hover()); paint_logo(ui.painter(), r); - ui.label(egui::RichText::new("DeckCraft").font(theme::bold(22.0))); + ui.label(egui::RichText::new(crate::i18n::tr("DeckCraft")).font(theme::bold(22.0))); ui.label(egui::RichText::new(version_line()).color(t.text_dim)); ui.add_space(6.0); - ui.label("Presentations and slide shows, rebuilt from scratch in pure Rust."); - ui.label("An open-source, clean-room project. Not affiliated with Microsoft."); + ui.label(crate::i18n::tr("Presentations and slide shows, rebuilt from scratch in pure Rust.")); + ui.label(crate::i18n::tr("An open-source, clean-room project. Not affiliated with Microsoft.")); ui.add_space(6.0); - ui.hyperlink_to("Join our community on Discord", deckcraft_engine::links::DISCORD); + ui.hyperlink_to(crate::i18n::tr("Join our community on Discord"), deckcraft_engine::links::DISCORD); ui.hyperlink_to("getartcraft.com/apps/deckcraft", deckcraft_engine::links::APP_PAGE); - ui.hyperlink_to("Source on GitHub", deckcraft_engine::links::GITHUB); + ui.hyperlink_to(crate::i18n::tr("Source on GitHub"), deckcraft_engine::links::GITHUB); ui.add_space(6.0); - ui.label(egui::RichText::new("MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors").size(11.0).color(t.text_faint)); + ui.label( + egui::RichText::new(crate::i18n::tr("MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors")) + .size(11.0) + .color(t.text_faint), + ); }); } @@ -2625,7 +2655,7 @@ pub fn about(_app: &mut SlideApp, ui: &mut Ui) { /// from `[workspace.package] version` (the single source of truth, `cargo xtask version`); the /// release workflow sets `DECKCRAFT_BUILD_SHA` / `DECKCRAFT_BUILD_DATE` at build time. pub fn version_line() -> String { - let mut s = format!("Version {}", env!("CARGO_PKG_VERSION")); + let mut s = crate::i18n::format("Version {}", &[(env!("CARGO_PKG_VERSION")).to_string()]); let sha = option_env!("DECKCRAFT_BUILD_SHA").map(|s| s.get(..9).unwrap_or(s)).filter(|s| !s.is_empty()); let date = option_env!("DECKCRAFT_BUILD_DATE").filter(|s| !s.is_empty()); match (sha, date) { diff --git a/crates/ui-egui/src/fillui.rs b/crates/ui-egui/src/fillui.rs index 584d309aa..b63a6ab89 100644 --- a/crates/ui-egui/src/fillui.rs +++ b/crates/ui-egui/src/fillui.rs @@ -110,7 +110,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> let mut sel: usize = ui.data_mut(|d| d.get_temp(sel_id).unwrap_or(0)).min(g.stops.len().saturating_sub(1)); // Preset variations of the first stop's colour. - ui.label("Preset gradients"); + ui.label(crate::i18n::tr("Preset gradients")); ui.horizontal_wrapped(|ui| { let base = g.stops.first().map(|s| s.color.clone()).unwrap_or(ColorRef::scheme(SchemeSlot::Accent1)); let mut light = base.clone(); @@ -167,7 +167,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> GradientShape::Path { .. } => "Radial", }; ui.horizontal(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Type")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Type"))); egui::ComboBox::from_id_salt((id, "kind")).selected_text(kind).width(120.0).show_ui(ui, |ui| { for k in ["Linear", "Radial", "Rectangular", "Path"] { if ui.selectable_label(kind == k, k).clicked() && kind != k { @@ -187,12 +187,12 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> }); }); ui.horizontal_wrapped(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Direction")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Direction"))); match &g.shape { GradientShape::Linear { angle, .. } => { for (l, a) in DIRECTIONS_LINEAR { let on = (angle - a).abs() < 0.5; - if ui.selectable_label(on, l).on_hover_text(format!("{a}°")).clicked() { + if ui.selectable_label(on, crate::i18n::tr(l)).on_hover_text(format!("{a}°")).clicked() { out = Some(Gradient { shape: GradientShape::Linear { angle: a, scaled: false }, ..g.clone() }); } } @@ -200,7 +200,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> GradientShape::Path { path, focus } => { for (l, f) in DIRECTIONS_PATH { let on = focus.iter().zip(f).all(|(a, b)| (a - b).abs() < 1e-3); - if ui.selectable_label(on, l.trim_start_matches("From ")).on_hover_text(l).clicked() { + if ui.selectable_label(on, l.trim_start_matches("From ")).on_hover_text(crate::i18n::tr(l)).clicked() { out = Some(Gradient { shape: GradientShape::Path { path: path.clone(), focus: f }, ..g.clone() }); } } @@ -209,7 +209,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> }); if let GradientShape::Linear { angle, .. } = &g.shape { ui.horizontal(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Angle")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Angle"))); if let Some(a) = widgets::spinner(ui, &format!("{id}-angle"), *angle, 15.0, "°", 70.0) { out = Some(Gradient { shape: GradientShape::Linear { angle: a.rem_euclid(360.0), scaled: false }, ..g.clone() }); } @@ -218,7 +218,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> // Stop bar: click to add, drag a stop to move it. ui.add_space(4.0); - ui.label("Gradient stops"); + ui.label(crate::i18n::tr("Gradient stops")); let (bar, bar_resp) = ui.allocate_exact_size(vec2(ui.available_width().min(260.0), 18.0), Sense::click()); paint_bar(ui, bar, g, sc); let (marks, _) = ui.allocate_exact_size(vec2(bar.width(), 14.0), Sense::hover()); @@ -274,7 +274,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> // The selected stop. if let Some(s) = g.stops.get(sel) { ui.horizontal(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Color")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Color"))); let (sw, _) = ui.allocate_exact_size(vec2(18.0, 18.0), Sense::hover()); ui.painter().rect(sw, CornerRadius::same(3), c32(&s.color, sc), Stroke::new(1.0, t.border), egui::StrokeKind::Inside); let r = widgets::drop_button(ui, "", vec2(24.0, 20.0), true); @@ -286,7 +286,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> } }); let can_remove = g.stops.len() > 2; - if ui.add_enabled(can_remove, egui::Button::new("Remove stop")).clicked() { + if ui.add_enabled(can_remove, egui::Button::new(crate::i18n::tr("Remove stop"))).clicked() { let mut ng = g.clone(); ng.stops.remove(sel); sel = sel.saturating_sub(1); @@ -294,7 +294,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> } }); ui.horizontal(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Position")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Position"))); if let Some(v) = widgets::spinner(ui, &format!("{id}-pos-{sel}"), (s.pos * 100.0).round(), 5.0, "%", 70.0) { let mut ng = g.clone(); ng.stops[sel].pos = (v / 100.0).clamp(0.0, 1.0); @@ -303,7 +303,7 @@ pub fn gradient_editor(ui: &mut Ui, id: &str, g: &Gradient, sc: &ColorScheme) -> } }); ui.horizontal(|ui| { - ui.add_sized(vec2(70.0, 20.0), egui::Label::new("Transparency")); + ui.add_sized(vec2(70.0, 20.0), egui::Label::new(crate::i18n::tr("Transparency"))); let key = ui.id().with((id, "tr", sel)); let mut tr: f32 = ui.data_mut(|d| d.get_temp(key).unwrap_or(((1.0 - alpha_of(&s.color)) * 100.0) as f32)); let r = ui.add(egui::Slider::new(&mut tr, 0.0..=100.0).suffix("%")); diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs new file mode 100644 index 000000000..760bcede4 --- /dev/null +++ b/crates/ui-egui/src/i18n.rs @@ -0,0 +1,519 @@ +//! Interface text only: presentation content, file names and command identifiers stay intact. + +use std::cell::Cell; +use std::collections::HashMap; +use std::sync::OnceLock; + +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Language { + #[default] + System, + En, + Uk, + Ru, + Es, + Fr, + Pt, + De, +} + +impl Language { + pub const ALL: [Self; 8] = [Self::System, Self::En, Self::Uk, Self::Ru, Self::Es, Self::Fr, Self::Pt, Self::De]; + + pub fn label(self) -> &'static str { + match self { + Self::System => tr("System language"), + Self::En => "English", + Self::Uk => "Українська", + Self::Ru => "Русский", + Self::Es => "Español", + Self::Fr => "Français", + Self::Pt => "Português", + Self::De => "Deutsch", + } + } + + pub fn from_locale(locale: &str) -> Self { + let language = locale.split(['-', '_', '.', '@']).next().unwrap_or(""); + match language.to_ascii_lowercase().as_str() { + "uk" => Self::Uk, + "ru" => Self::Ru, + "es" => Self::Es, + "fr" => Self::Fr, + "pt" => Self::Pt, + "de" => Self::De, + _ => Self::En, + } + } + + pub fn resolve(self, locale: Option<&str>) -> Self { + if self == Self::System { Self::from_locale(locale.unwrap_or("")) } else { self } + } +} + +thread_local! { + static CURRENT: Cell = const { Cell::new(Language::En) }; +} + +pub fn current() -> Language { + CURRENT.get() +} + +pub fn set_current(language: Language) { + CURRENT.set(language); +} + +const UK_CATALOG: &str = include_str!("i18n/uk.tsv"); +const RU_CATALOG: &str = include_str!("i18n/ru.tsv"); +const ES_CATALOG: &str = include_str!("i18n/es.tsv"); +const FR_CATALOG: &str = include_str!("i18n/fr.tsv"); +const PT_CATALOG: &str = include_str!("i18n/pt.tsv"); +const DE_CATALOG: &str = include_str!("i18n/de.tsv"); + +static UK: OnceLock> = OnceLock::new(); +static RU: OnceLock> = OnceLock::new(); +static ES: OnceLock> = OnceLock::new(); +static FR: OnceLock> = OnceLock::new(); +static PT: OnceLock> = OnceLock::new(); +static DE: OnceLock> = OnceLock::new(); + +fn parse_catalog(text: &str) -> HashMap { + text.lines() + .filter(|line| !line.is_empty() && !line.starts_with('#')) + .filter_map(|line| line.split_once('\t')) + .map(|(source, text)| (source.replace("\\n", "\n"), text.replace("\\n", "\n"))) + .collect() +} + +fn catalog(language: Language) -> Option<&'static HashMap> { + match language { + Language::Uk => Some(UK.get_or_init(|| parse_catalog(UK_CATALOG))), + Language::Ru => Some(RU.get_or_init(|| parse_catalog(RU_CATALOG))), + Language::Es => Some(ES.get_or_init(|| parse_catalog(ES_CATALOG))), + Language::Fr => Some(FR.get_or_init(|| parse_catalog(FR_CATALOG))), + Language::Pt => Some(PT.get_or_init(|| parse_catalog(PT_CATALOG))), + Language::De => Some(DE.get_or_init(|| parse_catalog(DE_CATALOG))), + _ => None, + } +} + +/// Exact lookup at an explicit interface boundary; unknown text falls back to English. +pub fn tr(text: &str) -> &str { + match catalog(CURRENT.get()) { + Some(catalog) => catalog.get(text).map(String::as_str).unwrap_or(text), + None => text, + } +} + +/// Context-specific interface label with the original English source as fallback. +pub fn tr_context<'a>(source: &'a str, key: &str) -> &'a str { + match catalog(CURRENT.get()) { + Some(catalog) => catalog.get(key).map(String::as_str).unwrap_or(source), + None => source, + } +} + +pub fn placeholder_prompt(kind: deckcraft_model::PhType) -> &'static str { + tr(kind.prompt()) +} + +/// Substitute already-formatted values without interpreting their contents as interface text. +pub fn format(source: &str, values: &[String]) -> String { + let text = tr(source); + let mut out = String::new(); + let mut rest = text; + let mut index = 0; + while let Some(start) = rest.find('{') { + out.push_str(rest.get(..start).unwrap_or("")); + let tail = rest.get(start + 1..).unwrap_or(""); + if let Some(after) = tail.strip_prefix('{') { + out.push('{'); + rest = after; + } else if let Some(end) = tail.find('}') { + out.push_str(values.get(index).map(String::as_str).unwrap_or("")); + index += 1; + rest = tail.get(end + 1..).unwrap_or(""); + } else { + out.push_str(rest); + return out; + } + } + out.push_str(&rest.replace("}}", "}")); + out +} + +/// "{n} {word}" with the word inflected for the interface language: English (one, other), +/// Ukrainian and Russian (one, few, many), Spanish, French, Portuguese and German (one, other; +/// French keeps the singular for 0). +#[allow(clippy::too_many_arguments)] +pub fn count( + n: usize, + english: (&str, &str), + ukrainian: [&str; 3], + russian: [&str; 3], + spanish: (&str, &str), + french: (&str, &str), + portuguese: (&str, &str), + german: (&str, &str), +) -> String { + let word = match CURRENT.get() { + Language::Uk => slavic(n, ukrainian), + Language::Ru => slavic(n, russian), + Language::Es => one_other(n, spanish), + Language::Fr => if n <= 1 { french.0 } else { french.1 }, + Language::Pt => one_other(n, portuguese), + Language::De => one_other(n, german), + Language::En | Language::System => if n == 1 { english.0 } else { english.1 }, + }; + format!("{n} {word}") +} + +/// Ukrainian/Russian integer forms: 1/21; 2–4/22–24; 0/5–19. +fn slavic<'a>(n: usize, forms: [&'a str; 3]) -> &'a str { + match (n % 10, n % 100) { + (1, last) if last != 11 => forms[0], + (2..=4, last) if !(12..=14).contains(&last) => forms[1], + _ => forms[2], + } +} + +fn one_other<'a>(n: usize, forms: (&'a str, &'a str)) -> &'a str { + if n == 1 { forms.0 } else { forms.1 } +} + +/// Recovery notice includes object forms per language. +pub fn recovered(n: usize) -> String { + let amount = count( + n, + ("unsaved presentation", "unsaved presentations"), + ["незбережену презентацію", "незбережені презентації", "незбережених презентацій"], + ["несохраненную презентацию", "несохраненные презентации", "несохраненных презентаций"], + ("presentación sin guardar", "presentaciones sin guardar"), + ("présentation non enregistrée", "présentations non enregistrées"), + ("apresentação não salva", "apresentações não salvas"), + ("nicht gespeicherte Präsentation", "nicht gespeicherte Präsentationen"), + ); + format("Recovered {} from the last session", &[amount]) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// The languages that ship a catalog. + const TRANSLATED: [Language; 6] = [Language::Uk, Language::Ru, Language::Es, Language::Fr, Language::Pt, Language::De]; + + fn placeholders(text: &str) -> Vec<&str> { + let mut out = vec![]; + let mut rest = text; + while let Some((_, tail)) = rest.split_once('{') { + if let Some(tail) = tail.strip_prefix('{') { + rest = tail; + continue; + } + if let Some((field, tail)) = tail.split_once('}') { + out.push(field); + rest = tail; + } else { + break; + } + } + out + } + + #[test] + fn all_command_menu_and_gallery_labels_are_translated() { + for language in TRANSLATED { + let catalog = catalog(language).unwrap(); + let mut required = vec![]; + required.extend(crate::UI_COMMANDS.iter().map(|c| c.1)); + required.extend(deckcraft_engine::Session::new().commands().into_iter().map(|c| c.label)); + for (menu, items) in crate::menus::menu_tree() { + required.push(menu); + required.extend(items.into_iter().filter(|(label, _)| *label != "-").map(|(label, _)| label)); + } + required.extend(deckcraft_geom::preset::CATALOG.iter().map(|shape| shape.label)); + required.extend(deckcraft_geom::preset::Category::ALL.iter().map(|category| category.label())); + required.extend(deckcraft_model::anim::ANIMATIONS.iter().map(|effect| effect.1)); + required.extend(deckcraft_model::anim::TRANSITIONS.iter().flat_map(|effect| [effect.1, effect.2])); + required.extend(deckcraft_model::chart::ChartType::MAIN.iter().map(|kind| kind.label())); + required.extend(deckcraft_model::defaults::SLIDE_SIZES.iter().map(|size| size.0)); + required.extend(deckcraft_color::STANDARD_COLORS.iter().map(|color| color.1)); + required.extend(deckcraft_color::SchemeSlot::THEME.iter().map(|slot| slot.label())); + required.extend(["@ribbon:Home", "@ribbon:Insert"]); + for option in deckcraft_model::anim::TRANSITIONS + .iter() + .flat_map(|effect| effect.4) + .chain(deckcraft_model::anim::ANIMATIONS.iter().flat_map(|effect| effect.5)) + { + let label = crate::ribbon::option_label(option); + if !label.is_empty() && !label.chars().all(|c| c.is_ascii_digit()) { + assert!(catalog.contains_key(&label), "missing effect option: {option}: {label}"); + } + } + let missing: Vec<_> = required.into_iter().filter(|key| !catalog.contains_key(*key)).collect(); + assert!(missing.is_empty(), "missing visible metadata in {language:?}: {missing:?}"); + } + } + + #[test] + fn every_literal_translation_call_has_a_catalog_entry() { + for source in [ + include_str!("canvas.rs"), + include_str!("credits.rs"), + include_str!("dialogs.rs"), + include_str!("fillui.rs"), + include_str!("lib.rs"), + include_str!("media.rs"), + include_str!("menus.rs"), + include_str!("panes.rs"), + include_str!("ribbon.rs"), + include_str!("show.rs"), + include_str!("sorter.rs"), + include_str!("status.rs"), + include_str!("thumbs.rs"), + include_str!("widgets.rs"), + include_str!("../../../apps/deckcraft/src/main.rs"), + include_str!("../../../apps/deckcraft-web/src/web.rs"), + ] { + for prefix in ["i18n::tr(\"", "i18n::format(\""] { + let mut rest = source.split("#[cfg(test)]").next().unwrap_or(source); + while let Some((_, tail)) = rest.split_once(prefix) { + let mut escaped = false; + let end = tail + .char_indices() + .find_map(|(index, c)| { + if escaped { + escaped = false; + None + } else if c == '\\' { + escaped = true; + None + } else if c == '\"' { + Some(index) + } else { + None + } + }) + .unwrap(); + let key: String = serde_json::from_str(&format!("\"{}\"", &tail[..end])).unwrap(); + for language in TRANSLATED { + assert!( + catalog(language).unwrap().contains_key(&key), + "missing literal translation in {language:?}: {key}" + ); + } + rest = &tail[end + 1..]; + } + } + } + } + + #[test] + fn language_command_keeps_document_data_and_identifiers_intact() { + let mut app = crate::SlideApp::new(deckcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", serde_json::json!({})).unwrap(); + app.run("insert.textBox", serde_json::json!({"text": "File {customer} / Звіт", "rect": [1, 2, 100, 40]})).unwrap(); + let before = serde_json::to_value(&app.session.active().unwrap().doc).unwrap(); + app.run("app.language", serde_json::json!({"language": "uk"})).unwrap(); + assert_eq!(app.ui.interface_language, Language::Uk); + assert_eq!(tr("File"), "Файл"); + assert_eq!(before, serde_json::to_value(&app.session.active().unwrap().doc).unwrap()); + assert!(app.run("app.language", serde_json::json!({"language": "invalid"})).is_err()); + assert_eq!(app.ui.interface_language, Language::Uk); + app.run("app.language", serde_json::json!({"language": "ru"})).unwrap(); + assert_eq!(app.ui.interface_language, Language::Ru); + assert_eq!(tr("File"), "Файл"); + set_current(Language::En); + } + + #[test] + fn bundled_ui_fonts_cover_the_interface_alphabets_without_system_fonts() { + let ctx = egui::Context::default(); + crate::theme::install_fonts(&ctx); + let mut output = ctx.run_ui(egui::RawInput::default(), |ui| { + for family in [egui::FontFamily::Proportional, egui::FontFamily::Name("bold".into()), egui::FontFamily::Monospace] { + // egui 0.36 has_glyph() can report a valid fallback face as a replacement. + // Check the configured fallback and its actual font charmap below instead. + let fallback_installed = ui.ctx().fonts_mut(|fonts| { + fonts.definitions().families.get(&family).is_some_and(|names| names.iter().any(|name| name == "Ubuntu-Light")) + }); + assert!(fallback_installed, "missing bundled Ukrainian fallback in {family:?}"); + } + }); + output.textures_delta.clear(); + let db = deckcraft_fonts::FontDb::with_font_dirs(vec![]); + let face = db.face(deckcraft_fonts::LAST_RESORT_FAMILY, "Regular"); + let letters: std::collections::HashSet<_> = TRANSLATED + .into_iter() + .filter_map(catalog) + .flat_map(|catalog| catalog.values().flat_map(|value| value.chars())) + .chain("ҐґЄєІіЇї".chars()) + .filter(|c| ('\u{0400}'..='\u{04ff}').contains(c)) + .collect(); + for c in letters { + assert_ne!(face.glyph_for(c), 0, "missing document fallback glyph: {c}"); + } + } + + // An explicit local visual check; the generated PNGs stay outside the repository. + #[test] + #[ignore = "writes translation review screenshots; run explicitly with DECKCRAFT_I18N_SHOTS"] + fn translated_interface_preview() { + let dir = std::env::var("DECKCRAFT_I18N_SHOTS").unwrap(); + std::fs::create_dir_all(&dir).unwrap(); + for (code, language) in + [("en", Language::En), ("uk", Language::Uk), ("ru", Language::Ru), ("es", Language::Es), ("fr", Language::Fr), ("pt", Language::Pt), ("de", Language::De)] + { + for (name, dialog) in [("editor", None), ("preferences", Some("preferences")), ("table", Some("table"))] { + let mut app = crate::SlideApp::new(deckcraft_engine::Session::new(), crate::Services::default()); + app.run("file.new", serde_json::json!({})).unwrap(); + app.ui.interface_language = language; + app.dialog = dialog.map(crate::dialogs::Dialog::new); + let mut harness = egui_kittest::Harness::builder().with_size(egui::vec2(1440.0, 900.0)).build_ui(|ui| { + app.logic(ui.ctx()); + app.ui(ui); + }); + harness.run_steps(6); + harness.render().unwrap().save(format!("{dir}/{code}-{name}.png")).unwrap(); + } + } + set_current(Language::En); + } + + #[test] + fn locales_and_preferences_are_backward_compatible() { + for (locale, expected) in [ + ("uk", Language::Uk), + ("uk-UA", Language::Uk), + ("uk_UA.UTF-8", Language::Uk), + ("UK_ua@euro", Language::Uk), + ("ru", Language::Ru), + ("ru-RU", Language::Ru), + ("es", Language::Es), + ("es-MX", Language::Es), + ("fr", Language::Fr), + ("fr_FR.UTF-8", Language::Fr), + ("pt", Language::Pt), + ("pt-BR", Language::Pt), + ("de", Language::De), + ("de-AT", Language::De), + ] { + assert_eq!(Language::from_locale(locale), expected); + } + for locale in ["", "en-US", "ukrainian"] { + assert_eq!(Language::from_locale(locale), Language::En); + } + assert_eq!(Language::Uk.resolve(Some("en")), Language::Uk); + assert_eq!(Language::Ru.resolve(Some("uk")), Language::Ru); + let old: crate::UiState = serde_json::from_str("{}").unwrap(); + assert_eq!(old.interface_language, Language::System); + let mut ui = old; + ui.interface_language = Language::Ru; + let round_trip: crate::UiState = serde_json::from_str(&serde_json::to_string(&ui).unwrap()).unwrap(); + assert_eq!(round_trip.interface_language, Language::Ru); + } + + #[test] + fn catalog_is_unique_complete_and_preserves_placeholders() { + let source_count = |text: &str| text.lines().filter(|line| !line.is_empty() && !line.starts_with('#')).count(); + let expected = source_count(UK_CATALOG); + for (constant, text) in [ + (UK_CATALOG, "uk"), + (RU_CATALOG, "ru"), + (ES_CATALOG, "es"), + (FR_CATALOG, "fr"), + (PT_CATALOG, "pt"), + (DE_CATALOG, "de"), + ] { + assert_eq!(source_count(constant), expected, "{text} catalog row count"); + let mut seen = std::collections::HashSet::new(); + for (line_no, line) in constant.lines().enumerate() { + if line.is_empty() || line.starts_with('#') { + continue; + } + let (source, text) = line.split_once('\t').unwrap(); + assert!(seen.insert(source), "{text}: duplicate on {}: {source}", line_no + 1); + assert!(!text.trim().is_empty(), "{text}: empty translation: {source}"); + assert_eq!(placeholders(source), placeholders(text), "{text}: placeholder names/order/format: {source}"); + } + } + } + + #[test] + fn lookup_and_format_preserve_user_values_and_fallbacks() { + set_current(Language::Uk); + assert_eq!(tr("File"), "Файл"); + assert_eq!(tr_context("Insert", "@ribbon:Insert"), "Вставлення"); + assert_eq!(tr("Insert"), "Вставити"); + assert_eq!(tr("a user-defined slide title"), "a user-defined slide title"); + let user = "File {user} / Звіт.pptx".to_string(); + assert!(format("Saved {path}", std::slice::from_ref(&user)).ends_with(&user)); + set_current(Language::Ru); + assert_eq!(tr("File"), "Файл"); + set_current(Language::En); + assert_eq!(tr("File"), "File"); + } + + #[test] + fn ukrainian_integer_counts_cover_teens_and_large_values() { + set_current(Language::Uk); + for (n, word) in [ + (0, "слайдів"), + (1, "слайд"), + (2, "слайди"), + (4, "слайди"), + (5, "слайдів"), + (11, "слайдів"), + (12, "слайдів"), + (14, "слайдів"), + (21, "слайд"), + (24, "слайди"), + (111, "слайдів"), + ] { + assert_eq!( + count(n, ("slide", "slides"), ["слайд", "слайди", "слайдів"], ["слайд", "слайда", "слайдов"], ("diapositiva", "diapositivas"), ("diapositive", "diapositives"), ("slide", "slides"), ("Folie", "Folien")), + format!("{n} {word}") + ); + } + set_current(Language::En); + } + + #[test] + fn russian_and_western_counts_use_their_own_forms() { + let forms = |n| count(n, ("slide", "slides"), ["слайд", "слайди", "слайдів"], ["слайд", "слайда", "слайдов"], ("diapositiva", "diapositivas"), ("diapositive", "diapositives"), ("slide", "slides"), ("Folie", "Folien")); + set_current(Language::Ru); + for (n, word) in [ + (0, "слайдов"), + (1, "слайд"), + (2, "слайда"), + (4, "слайда"), + (5, "слайдов"), + (11, "слайдов"), + (12, "слайдов"), + (14, "слайдов"), + (21, "слайд"), + (22, "слайда"), + (24, "слайда"), + (25, "слайдов"), + (111, "слайдов"), + ] { + assert_eq!(forms(n), format!("{n} {word}")); + } + set_current(Language::De); + assert_eq!(forms(0), "0 Folien"); + assert_eq!(forms(1), "1 Folie"); + assert_eq!(forms(3), "3 Folien"); + set_current(Language::Fr); + assert_eq!(forms(0), "0 diapositive"); + assert_eq!(forms(1), "1 diapositive"); + assert_eq!(forms(3), "3 diapositives"); + set_current(Language::Es); + assert_eq!(forms(0), "0 diapositivas"); + assert_eq!(forms(1), "1 diapositiva"); + set_current(Language::En); + } +} diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv new file mode 100644 index 000000000..9017aecad --- /dev/null +++ b/crates/ui-egui/src/i18n/de.tsv @@ -0,0 +1,1408 @@ +# German interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Feste Angabe (leer = automatisch aktualisieren): + Footer text: Fußzeilentext: + Present Präsentieren + pt pt + — Edited — Bearbeitet +"Not Allowed" Symbol Symbol „Nicht erlaubt“ +% of all commits % aller Commits ++ New Comment + Neuer Kommentar ++ New Slide + Neue Folie ++ Row + Zeile ++ Series + Datenreihe ++Bin +Intervall +100% Stacked Bar 100 % gestapelte Balken +100% Stacked Column 100 % gestapelte Säulen +35mm Slides 35-mm-Folien +@ribbon:Home Start +@ribbon:Insert Einfügen +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{}: Pull Requests (PRs): {}, Commits: {}, Zeilen: +{} / −{} (Δ {}), Binärdateien: +{} / −{}, {} – {} +A3 Paper (297x420 mm) A3-Papier (297×420 mm) +A4 Paper (210x297 mm) A4-Papier (210×297 mm) +Aa Aa +Abc Abc +About Über +About DeckCraft Über DeckCraft +Accent 1 Akzent 1 +Accent 2 Akzent 2 +Accent 3 Akzent 3 +Accent 4 Akzent 4 +Accent 5 Akzent 5 +Accent 6 Akzent 6 +Accessibility Checker Barrierefreiheitsprüfung +Across Quer +Action Aktion +Action Button: Custom Interaktive Schaltfläche: Benutzerdefiniert +Action Button: Document Interaktive Schaltfläche: Dokument +Action Button: Get Information Interaktive Schaltfläche: Informationen abrufen +Action Button: Go Back Interaktive Schaltfläche: Zurück +Action Button: Go Back or Previous Interaktive Schaltfläche: Zurück oder Vorherige +Action Button: Go Forward or Next Interaktive Schaltfläche: Vorwärts oder Nächste +Action Button: Go Home Interaktive Schaltfläche: Startseite +Action Button: Go to Beginning Interaktive Schaltfläche: Zum Anfang +Action Button: Go to End Interaktive Schaltfläche: Zum Ende +Action Button: Help Interaktive Schaltfläche: Hilfe +Action Button: Sound Interaktive Schaltfläche: Sound +Action Button: Video Interaktive Schaltfläche: Video +Action Button: {k} Interaktive Schaltfläche: {k} +Action Buttons Interaktive Schaltflächen +Add Animation Animation hinzufügen +Add Section Abschnitt hinzufügen +Add\nAnimation Animation hinzufügen +Address: Adresse: +Adjust Shape Form anpassen +After Previous Nach vorheriger +After: Nachher: +Airplane Flugzeug +Align Ausrichten +Align Bottom Unten ausrichten +Align Center Zentriert ausrichten +Align Left Links ausrichten +Align Middle Mitte ausrichten +Align Right Rechts ausrichten +Align Text Text ausrichten +Align Top Oben ausrichten +Alt Text Alternativtext +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Alternativtext +An open-source, clean-room project. Not affiliated with Microsoft. Ein quelloffenes, unabhängiges Projekt. Keine Verbindung zu Microsoft. +Angle Winkel +Animation Gallery Animationskatalog +Animation Pane Animationsbereich +Animation Styles Animationsformatvorlagen +Animation\nPane Animationsbereich +Animations Animationen +Animation Painter Animation übertragen +Apply Animation Animation anwenden +Play/Pause GIF GIF abspielen/anhalten +Animations on Slide Animationen auf der Folie +Appear Einblenden +Apply Anwenden +Apply To All Auf alle anwenden +Apply to All Auf alle anwenden +Apply\nTo All Auf alle anwenden +Arc Bogen +Arcs Bögen +Area Fläche +Arrange Anordnen +Arrow Pfeil +Arrow at end Pfeil am Ende +Arrow at start Pfeil am Anfang +Arrow: Bent Pfeil: Gewinkelt +Arrow: Bent-Up Pfeil: Gewinkelt nach oben +Arrow: Chevron Pfeil: Chevron +Arrow: Down Pfeil: nach unten +Arrow: Left Pfeil: nach links +Arrow: Left-Right Pfeil: nach links und rechts +Arrow: Left-Right-Up Pfeil: Links-Rechts-Oben +Arrow: Left-Up Pfeil: Links-Oben +Arrow: Notched Right Pfeil: Rechts gekerbt +Arrow: Pentagon Pfeil: Fünfeck +Arrow: Quad Pfeil: Vierfach +Arrow: Right Pfeil: nach rechts +Arrow: Striped Right Pfeil: Rechts gestreift +Arrow: U-Turn Pfeil: Kehre +Arrow: Up Pfeil: nach oben +Arrow: Up-Down Pfeil: nach oben und unten +Arrows Pfeile +Arrows at both ends Pfeile an beiden Enden +As One Object Als ein Objekt +Audio Audio +Audio from File… Audio aus Datei… +AutoCorrect as you type AutoKorrektur während der Eingabe +Autofit Automatische Anpassung +Automatic Automatisch +B4 (ISO) Paper (250x353 mm) B4-Papier (ISO) (250×353 mm) +B5 (ISO) Paper (176x250 mm) B5-Papier (ISO) (176×250 mm) +Background Hintergrund +Background Styles Hintergrundformatvorlagen +Background\nStyles Hintergrundformatvorlagen +Backspace Rücktaste +Banded Columns Gebänderte Spalten +Banded Rows Gebänderte Zeilen +Banner Banner +Basic Cycle Einfacher Zyklus +Basic List Einfache Liste +Basic Process Einfacher Prozess +Basic Shapes Standardformen +Before text (in): Vor dem Text (Zoll): +Bevel Abflachung +Binary assets added Hinzugefügte Binärdateien +Binary assets removed Entfernte Binärdateien +Black Left Über Schwarz nach links +Black Pen Schwarzer Stift +Black Right Über Schwarz nach rechts +Blinds Jalousie +Block Arc Blockbogen +Block Arrows Blockpfeile +Blue Blau +Blue Pen Blauer Stift +Bold Fett +Bold Flash Kräftiges Aufblitzen +Both Beide +Bottom Unten +Bounce Springen +Box Box +Box In Box von innen +Box Out Box von außen +Box and Whisker Kastengrafik +Brightness Helligkeit +Brightness {:+}% Helligkeit {:+} % +Bring Forward Ebene nach vorne +Bring to Front In den Vordergrund +Bring\nForward Ebene nach vorne +Browsed at a kiosk (full screen) Ansicht an einem Kiosk (Vollbild) +Browsed by an individual (window) Ansicht durch eine Einzelperson (Fenster) +Bubble Blase +Bullets Aufzählungszeichen +Burst Ausbruch +By Paragraph Nach Absatz +Callout: Down Arrow Legende: Pfeil nach unten +Callout: Left Arrow Legende: Pfeil nach links +Callout: Line Legende: Linie +Callout: Right Arrow Legende: Pfeil nach rechts +Callout: Up Arrow Legende: Pfeil nach oben +Callouts Legenden +Cameo Cameo +Camera capture is not available yet Kameraaufnahme ist noch nicht verfügbar +Cancel Abbrechen +Capitalize Each Word Jedes Wort groß +Caps Großbuchstaben +Center Zentrieren +Centered Zentriert +Change Case Groß-/Kleinschreibung ändern +Change Chart Type Diagrammtyp ändern +Change Picture Bild ändern +Change Shape Form ändern +Change\nChart Type Diagrammtyp ändern +Character Spacing Zeichenabstand +Characters Zeichen +Chart Diagramm +Chart Data Diagrammdaten +Chart Design Diagrammentwurf +Chart Elements Diagrammelemente +Chart… Diagramm… +Check Accessibility Barrierefreiheit überprüfen +Check\nAccessibility Barrierefreiheit überprüfen +Checkerboard Schachbrett +Chevron Chevron +Choose a SmartArt Graphic SmartArt-Grafik auswählen +Chord Sehne +Circle Kreis +Circle In Kreis von innen +Circle Out Kreis von außen +Clear All Formatting Gesamte Formatierung löschen +Click a symbol to insert it at the insertion point. Klicken Sie auf ein Symbol, um es an der Einfügemarke einzufügen. +Click icon to add SmartArt graphic Klicken Sie auf das Symbol, um eine SmartArt-Grafik hinzuzufügen +Click icon to add chart Klicken Sie auf das Symbol, um ein Diagramm hinzuzufügen +Click icon to add media Klicken Sie auf das Symbol, um Medien hinzuzufügen +Click icon to add picture Klicken Sie auf das Symbol, um ein Bild hinzuzufügen +Click icon to add table Klicken Sie auf das Symbol, um eine Tabelle hinzuzufügen +Click to add first slide Klicken Sie, um die erste Folie hinzuzufügen +Click to add notes Klicken Sie, um Notizen hinzuzufügen +Click to add subtitle Klicken Sie, um Untertitel hinzuzufügen +Click to add text Klicken Sie, um Text hinzuzufügen +Click to add title Klicken Sie, um Titel hinzuzufügen +Click to edit Master text styles Klicken Sie, um die Textformatvorlagen des Masters zu bearbeiten +Click to edit Master title style Klicken Sie, um die Titelformatvorlage des Masters zu bearbeiten +Clock Uhr +Clockwise Im Uhrzeigersinn +Close Schließen +Close Master View Masteransicht schließen +Close\nMaster View Masteransicht schließen +Cloud Wolke +Clustered Bar Gruppierte Balken +Clustered Column Gruppierte Säulen +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Menüband reduzieren +Color Farbe +Color Pulse Farbpuls +Colors Farben +Columns Spalten +Comb Kamm +Combo Kombi +Command Palette Befehlspalette +Comment Kommentar +Comments Kommentare +Commits Commits +Community Links Community-Links +Company Firma +Complementary Color Komplementärfarbe +Connect Shapes Formen verbinden +Connection Sites Verbindungspunkte +Connector: Curved Verbinder: gekrümmt +Connector: Elbow Verbinder: gewinkelt +Connector: Elbow (one bend) Verbinder: gewinkelt (ein Knick) +Content Inhalt +Contrast Kontrast +Contrast {:+}% Kontrast {:+} % +Contributors Mitwirkende +Conveyor Förderband +Copy Kopieren +Corrections Korrekturen +Couldn't save AutoRecover information: {e} AutoWiederherstellen-Informationen konnten nicht gespeichert werden: {e} +Counter Clockwise Gegen den Uhrzeigersinn +Cover Abdecken +Create Erstellen +Crop Zuschneiden +Crop 10% each side Je Seite 10 % zuschneiden +Crop 20% each side Je Seite 20 % zuschneiden +Crop to Shape In Form zuschneiden +Cross Kreuz +Crush Zerdrücken +Ctrl+ Strg+ +Cube Würfel +Currency Währung +Curtains Vorhänge +Custom Benutzerdefiniert +Custom Path Benutzerdefinierter Pfad +Custom Show Benutzerdefinierte Bildschirmpräsentation +Custom Show 1 Benutzerdefinierte Bildschirmpräsentation 1 +Custom Shows Benutzerdefinierte Bildschirmpräsentationen +Custom Slide Show Benutzerdefinierte Bildschirmpräsentation +Custom\nShow Benutzerdefinierte Bildschirmpräsentation +Cut Ausschneiden +Cylinder Zylinder +Dark Blue Dunkelblau +Dark Mode Dunkelmodus +Dark Red Dunkelrot +Dark appearance Dunkles Erscheinungsbild +Dark\nMode Dunkelmodus +Darken Abdunkeln +Dash Strich +Dash Dot Strichpunkt +Dashes Striche +Database Datenbank +Date Datum +Date & Time Datum und Uhrzeit +Date &\nTime Datum und Uhrzeit +Date and Time Datum und Uhrzeit +Date and time Datum und Uhrzeit +Decagon Zehneck +Decision Entscheidung +DeckCraft DeckCraft +Decrease Font Size Schriftgrad verkleinern +Decrease List Level Listenebene verringern +Delay: Verzögerung: +Delete Löschen +Delete Columns Spalten löschen +Delete Comment Kommentar löschen +Delete Layout Layout löschen +Delete Rows Zeilen löschen +Delete Slide Folie löschen +Delete Table Tabelle löschen +Delete Text Text löschen +Desaturate Entsättigen +Deselect Auswahl aufheben +Design Entwurf +Design Ideas Designideen +Design\nIdeas Designideen +Deutsch Deutsch +Diagonal Stripe Diagonaler Streifen +Diamond Raute +Diamond In Raute von innen +Diamond Out Raute von außen +Direction Richtung +Disappear Verschwinden +Discard Recovered Presentations Wiederhergestellte Präsentationen verwerfen +Display name Anzeigename +Dissolve Auflösen +Dissolve In Auflösen von innen +Dissolve Out Auflösen von außen +Distribute Verteilen +Distribute Columns Spalten verteilen +Distribute Horizontally Horizontal verteilen +Distribute Rows Zeilen verteilen +Distribute Vertically Vertikal verteilen +Division Sign Geteiltzeichen +Do not Autofit Nicht automatisch anpassen +Do you want to save the changes you made to {what}? Möchten Sie die an {what} vorgenommenen Änderungen speichern? +Document Dokument +Dodecagon Zwölfeck +Don't Save Nicht speichern +Don't show on title slide Nicht auf der Titelfolie anzeigen +Done Fertig +Donut Ring +Doors Türen +Double Brace Doppelte geschweifte Klammer +Double Bracket Doppelte eckige Klammer +Double Wave Doppelte Welle +Doughnut Ring +Down Nach unten +Drape Drapieren +Draw Zeichnen +Drop Shadow Rectangle Rechteck mit Schlagschatten +Duplicate Duplizieren +Duplicate Selected Slides Ausgewählte Folien duplizieren +Duplicate Slide Folie duplizieren +Duration: Dauer: +Dynamic Content Dynamischer Inhalt +Edit Bearbeiten +Edit Alt Text… Alternativtext bearbeiten… +Edit Data Daten bearbeiten +Edit Shape Form bearbeiten +Edit Text Text bearbeiten +Edit the data: first row = series names, first column = categories. Bearbeiten Sie die Daten: erste Zeile = Reihennamen, erste Spalte = Kategorien. +Edit\nData Daten bearbeiten +Edit\nShape Form bearbeiten +Editing Bearbeitung +Effect Options Effektoptionen +Effect\nOptions Effektoptionen +Effects Effekte +Email Address E-Mail-Adresse +Email address: E-Mail-Adresse: +Emphasis Hervorgehoben +End Ende +End Show Bildschirmpräsentation beenden +End of slide show Ende der Bildschirmpräsentation +End of slide show, click to exit. Ende der Bildschirmpräsentation. Zum Beenden klicken. +End trim (s): Ende zuschneiden (s): +English (United Kingdom) Englisch (Großbritannien) +English (United States) Englisch (USA) +Enter Eingabe +Entrance Eingang +Equals Gleich +Equation Gleichung +Equation Shapes Gleichungsformen +Eraser Radiergummi +Escape Esc +Español Español +Exciting Spektakulär +Exit Beenden +Expand Erweitern +Explosion: 14 Points Explosion: 14 Spitzen +Explosion: 8 Points Explosion: 8 Spitzen +Export Exportieren +Export the presentation as: Präsentation exportieren als: +Exported {path} Exportiert: {path} +Export… Exportieren… +Fade Verblassen +Fade in (s): Einblenden (s): +Fade out (s): Ausblenden (s): +Fall Over Umfallen +Ferris Wheel Riesenrad +File Datei +Fill Füllung +Fill & Line Füllung und Linie +Fill Color Füllfarbe +Filled Radar Gefülltes Netz +Find… Suchen… +First Erste +First Column Erste Spalte +First Slide Erste Folie +First commit Erster Commit +Fit Anpassen +Fit slide to current window Folie an das aktuelle Fenster anpassen +Fit to Window An Fenster anpassen +Fit to\nWindow An Fenster anpassen +Flash Blitz +Flip Spiegeln +Flip Horizontal Horizontal spiegeln +Flip Vertical Vertikal spiegeln +Float In Schweben von innen +Float Out Schweben von außen +Flowchart Flussdiagramm +Flowchart: Alternate Process Flussdiagramm: Alternativer Prozess +Flowchart: Card Flussdiagramm: Karte +Flowchart: Collate Flussdiagramm: Kollationieren +Flowchart: Connector Flussdiagramm: Verbinder +Flowchart: Data Flussdiagramm: Daten +Flowchart: Decision Flussdiagramm: Entscheidung +Flowchart: Delay Flussdiagramm: Verzögerung +Flowchart: Direct Access Storage Flussdiagramm: Direktzugriffsspeicher +Flowchart: Display Flussdiagramm: Anzeige +Flowchart: Document Flussdiagramm: Dokument +Flowchart: Extract Flussdiagramm: Extrahieren +Flowchart: Internal Storage Flussdiagramm: Interner Speicher +Flowchart: Magnetic Disk Flussdiagramm: Magnetplatte +Flowchart: Manual Input Flussdiagramm: Manuelle Eingabe +Flowchart: Manual Operation Flussdiagramm: Manueller Vorgang +Flowchart: Merge Flussdiagramm: Zusammenführen +Flowchart: Multidocument Flussdiagramm: Mehrfachdokument +Flowchart: Off-page Connector Flussdiagramm: Verbinder außerhalb der Seite +Flowchart: Or Flussdiagramm: Oder +Flowchart: Predefined Process Flussdiagramm: Vordefinierter Prozess +Flowchart: Preparation Flussdiagramm: Vorbereitung +Flowchart: Process Flussdiagramm: Prozess +Flowchart: Punched Tape Flussdiagramm: Lochstreifen +Flowchart: Sequential Access Storage Flussdiagramm: Sequenzieller Speicher +Flowchart: Sort Flussdiagramm: Sortieren +Flowchart: Stored Data Flussdiagramm: Gespeicherte Daten +Flowchart: Summing Junction Flussdiagramm: Summierungsstelle +Flowchart: Terminator Flussdiagramm: Start/Ende +Fly In Einfliegen +Fly Out Ausfliegen +Fly Through Durchfliegen +Folded Corner Abgeknickte Ecke +Follow the layout Wie im Layout +Followed Hyperlink Besuchter Hyperlink +Font Schriftart +Font Color Schriftfarbe +Font Size Schriftgrad +Fonts Schriftarten +Footer Fußzeile +Foreground Vordergrund +Format Format +Format Background Hintergrund formatieren +Format Background… Hintergrund formatieren… +Format Painter Format übertragen +Format Painter (double-click to keep it on) Format übertragen (Doppelklick zum Dauerhaftaktivieren) +Format Pane Formatierungsbereich +Format Shape Form formatieren +Format Shape… Form formatieren… +Format\nBackground Hintergrund formatieren +Format\nPane Formatierungsbereich +Formatting State Formatierungszustand +Fracture Bruch +Frame Rahmen +Français Français +Freeform Freihandform +From Von +From Beginning Von Anfang an +From Bottom Von unten +From Bottom Left Von unten links +From Bottom Right Von unten rechts +From Current Slide Von aktueller Folie +From Left Von links +From Right Von rechts +From Top Von oben +From Top Left Von oben links +From Top Right Von oben rechts +From bottom left Von unten links +From bottom right Von unten rechts +From center Von der Mitte +From top left Von oben links +From top right Von oben rechts +From\nBeginning Von Anfang an +From\nCurrent Slide Von aktueller Folie +Full Vollständig +Full Page Slides Folien in voller Seitengröße +Funnel Trichter +Gallery Katalog +General Allgemein +Get Text Text abrufen +Glitter Glitzern +Glow Leuchten +Go to Gehe zu +Go to Slide Zu Folie wechseln +Grab bag Gemischtes +Gradient fill Verlaufsfüllung +Gradient stops Verlaufspunkte +Gradient… Verlauf… +Grayscale Graustufen +Greek Griechisch +Green Grün +Gridlines Gitternetzlinien +Group Gruppieren +Group Objects Objekte gruppieren +Grow & Turn Vergrößern und drehen +Grow/Shrink Vergrößern/Verkleinern +Guides Führungslinien +Half Halb +Half Frame Halber Rahmen +Handout Master Handzettelmaster +Handout Master (coming soon) Handzettelmaster (in Kürze) +Handout\nMaster Handzettelmaster +Handouts (1 slide per page) Handzettel (1 Folie pro Seite) +Handouts (2 slides per page) Handzettel (2 Folien pro Seite) +Handouts (3 slides per page) Handzettel (3 Folien pro Seite) +Handouts (4 slides per page) Handzettel (4 Folien pro Seite) +Handouts (6 slides per page) Handzettel (6 Folien pro Seite) +Handouts (9 slides per page) Handzettel (9 Folien pro Seite) +Header Kopfzeile +Header & Footer Kopf- und Fußzeile +Header &\nFooter Kopf- und Fußzeile +Header Row Kopfzeile +Header and Footer Kopf- und Fußzeile +Header and Footer… Kopf- und Fußzeile… +Heart Herz +Height Höhe +Height (in): Höhe (Zoll): +Height: Höhe: +Help Hilfe +Heptagon Siebeneck +Hexagon Sechseck +Hide All Alles ausblenden +Hide Background Graphics Hintergrundgrafiken ausblenden +Hide During Show Während der Präsentation ausblenden +Hide Slide Folie ausblenden +Hide background graphics Hintergrundgrafiken ausblenden +Hide\nSlide Folie ausblenden +Hierarchy Hierarchie +High Hoch +Highlighter Textmarker +Histogram Histogramm +Home Startseite +Honeycomb Honigwabe +Horizontal Horizontal +Horz In Horizontal von innen +Horz Out Horizontal von außen +How would you describe this object and its context to someone who is blind or has low vision? Wie würden Sie dieses Objekt und seinen Kontext einer blinden oder sehbehinderten Person beschreiben? +Hyperlink Hyperlink +Icons Symbole +In Von innen +In Bounce Von innen mit Sprung +Include hidden slides Ausgeblendete Folien einbeziehen +Increase Font Size Schriftgrad vergrößern +Increase List Level Listenebene erhöhen +Ink to Math Freihand in Gleichung +Ink to Math (coming soon) Freihand in Gleichung (in Kürze) +Ink to Shape Freihand in Form +Ink to Shape (coming soon) Freihand in Form (in Kürze) +Ink to Text Freihand in Text +Ink to Text (coming soon) Freihand in Text (in Kürze) +Ink to\nMath Freihand in Gleichung +Ink to\nShape Freihand in Form +Ink to\nText Freihand in Text +Inner Innen +Insert Einfügen +Insert Above Oben einfügen +Insert Below Unten einfügen +Insert Hyperlink Hyperlink einfügen +Insert Layout Layout einfügen +Insert Left Links einfügen +Insert Placeholder Platzhalter einfügen +Insert Right Rechts einfügen +Insert Table Tabelle einfügen +Insert Table… Tabelle einfügen… +Insert picture from file… Bild aus Datei einfügen… +Insert\nAbove Oben einfügen +Insert\nBelow Unten einfügen +Insert\nLayout Layout einfügen +Insert\nLeft Links einfügen +Insert\nPlaceholder Platzhalter einfügen +Insert\nRight Rechts einfügen +Inspect Presentation Präsentation prüfen +Inspect Shape Form prüfen +Inspect Slide Folie prüfen +Interface Language Sprache der Benutzeroberfläche +Interface language: Sprache der Benutzeroberfläche: +Interface size Größe der Benutzeroberfläche +Isosceles Triangle Gleichschenkliges Dreieck +Italiano Italiano +Italic Kursiv +JPEG image (current slide) JPEG-Bild (aktuelle Folie) +Join our community on Discord Treten Sie unserer Community auf Discord bei +Join the ArtCraft community on Discord Treten Sie der ArtCraft-Community auf Discord bei +Justify Blocksatz +L-Shape L-Form +Language Sprache +Last Letzte +Last Column Letzte Spalte +Last Slide Letzte Folie +Last commit Letzter Commit +Layout Layout +Learn More Weitere Informationen +Learn\nMore Weitere Informationen +Ledger Paper (11x17 in) Ledger-Papier (11×17 Zoll) +Left Links +Left Brace Linke geschweifte Klammer +Left Bracket Linke eckige Klammer +Letter Paper (8.5x11 in) Letter-Papier (8,5×11 Zoll) +Liberation Serif Liberation Serif +Light Blue Hellblau +Light Green Hellgrün +Light/Dark appearance Helle/dunkle Darstellung +Lighten Aufhellen +Lightning Blitzschlag +Lightning Bolt Blitz +Line Linie +Line Color Linienfarbe +Line Spacing Zeilenabstand +Line Spacing Options… Optionen für Zeilenabstand… +Line delta Zeilenunterschied +Line spacing (lines): Zeilenabstand (Zeilen): +Line with Markers Linie mit Markierungen +Linear Linear +Lines Linien +Lines +/− Zeilen +/− +Lines added Hinzugefügte Zeilen +Lines deleted Gelöschte Zeilen +Link Verknüpfung +Link… Verknüpfung… +List Commands Befehlsliste +Lock Sperren +Long Dash Langer Strich +Long Dash Dot Langer Strich Punkt +Loop continuously until 'Esc' Endlos wiederholen bis 'Esc' +Loop until Stopped Wiederholen bis angehalten +Loops Schleifen +Loose Weit +Low Niedrig +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 das ArtCraft-Team und die DeckCraft-Mitwirkenden +Margins (pt) Ränder (pt) +Mark as decorative Als dekorativ markieren +Mark selected text as: Ausgewählten Text markieren als: +Math Mathematik +Matrix Matrix +Maximize content (else ensure fit) Inhalt maximieren (sonst einpassen) +Media Medien +Media Info Medieninformationen +Medium Mittel +Merge Cells Zellen verbinden +Merge Shapes Formen zusammenführen +Merge\nCells Zellen verbinden +Merge\nShapes Formen zusammenführen +Merged PRs Zusammengeführte PRs +Middle Mitte +Minus Sign Minuszeichen +Model Modell +Models Modelle +Moon Mond +More Colors… # Weitere Farben… # +Morph Morphen +Motion Bewegung +Motion Paths Bewegungspfade +Move Verschieben +Move Down Nach unten verschieben +Move Insertion Point Einfügemarke verschieben +Move Section Abschnitt verschieben +Move Section Down Abschnitt nach unten +Move Section Up Abschnitt nach oben +Move Slide Folie verschieben +Move Up Nach oben verschieben +Multiplication Sign Malzeichen +Multiply Multiplikation +Mute Stummschalten +Name Name +Name (A–Z) Name (A–Z) +Name: Name: +New Comment Neuer Kommentar +New Presentation Neue Präsentation +New Slide Neue Folie +New Slide (⇧⌘N) Neue Folie (⇧⌘N) +New presentation Neue Präsentation +New show name: Name der neuen Präsentation: +New\nComment Neuer Kommentar +New\nSlide Neue Folie +Next Weiter +Next Slide Nächste Folie +Next Window Nächstes Fenster +Next ▶ Weiter ▶ +No Color Keine Farbe +No Fill Keine Füllung +No Glow Kein Leuchten +No Outline Keine Kontur +No Reflection Keine Reflexion +No Shadow Kein Schatten +No Soft Edges Keine weichen Kanten +No accessibility issues found. People with disabilities should not have difficulty reading this document. Keine Barrierefreiheitsprobleme gefunden. Personen mit Behinderungen sollten keine Schwierigkeiten beim Lesen dieses Dokuments haben. +No comments on this slide. Keine Kommentare auf dieser Folie. +No contributor data was built into this copy. In diese Kopie wurden keine Mitwirkendendaten eingebaut. +No fill Keine Füllung +No line Keine Linie +No model credits were built into this copy. In diese Kopie wurden keine Angaben zu verwendeten Modellen eingebaut. +No notes. Keine Notizen. +No sound: {err} Kein Ton: {err} +None Keine +Normal Normal +Not Equal Ungleich +Not allowed Nicht erlaubt +Notes Notizen +Notes Master Notizenmaster +Notes Master (coming soon) Notizenmaster (in Kürze) +Notes Page Notizenseite +Notes Pages Notizenseiten +Notes\nMaster Notizenmaster +Notes\nPage Notizenseite +Nudge Verschieben +Number of columns: Anzahl der Spalten: +Number of rows: Anzahl der Zeilen: +Numbering Nummerierung +Object Color Objektfarbe +Objects Objekte +Octagon Achteck +On Click Beim Klicken +On Click of {name} Beim Klicken auf {name} +On Click of… (none) Beim Klicken auf… (keine) +On Mouse Click Bei Mausklick +On-screen Show (16:10) Bildschirmpräsentation (16:10) +Open Data Daten öffnen +Open Dialog Dialog öffnen +Open Recovered Presentations Wiederhergestellte Präsentationen öffnen +Open the sample deck Beispielpräsentation öffnen +Open… Öffnen… +Orange Orange +Orbit Umlaufbahn +Order Objects Objekte anordnen +Origami Origami +Out Von außen +Out Bounce Von außen mit Sprung +Outer Außen +Outline Gliederung +Outline (.txt) Gliederung (.txt) +Outline View Gliederungsansicht +Outline\nView Gliederungsansicht +Oval Oval +Oval ends Ovale Enden +Overhead Tageslichtprojektor +PDF document (.pdf) PDF-Dokument (.pdf) +PNG images (all slides) PNG-Bilder (alle Folien) +PNG images (current slide) PNG-Bilder (aktuelle Folie) +PRs Pull Requests +Page Curl Seitenrollung +Page Setup… Seite einrichten… +PageDown Bild ab +PageUp Bild auf +Pan Schwenken +Pane Bereich +Paragraph Absatz +Paragraph… Absatz… +Parallelogram Parallelogramm +Pareto Pareto +Partial Circle Teilkreis +Particles Partikel +Paste Einfügen +Paste (⌘V) Einfügen (⌘V) +Paste Formatting Formatierung einfügen +Paste and Match Formatting Mit gleicher Formatierung einfügen +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Fügen Sie eine Gliederung ein oder tippen Sie sie. Zeilen ohne Einzug werden Folientitel; Zeilen mit Tabulatoreinzug werden Aufzählungspunkte. +Pasted image.png Eingefügtes Bild.png +Path Pfad +Pattern fill Musterfüllung +Pause Anhalten +Peek In Hineinlugen +Peel Off Ablösen +Pencil Stift +Pentagon Fünfeck +Perspective Perspektive +Pick a graphic; type one item per line. Wählen Sie eine Grafik; geben Sie pro Zeile ein Element ein. +Pick a look for your slides. Ideas are generated on your device. Wählen Sie ein Aussehen für Ihre Folien. Ideen werden auf Ihrem Gerät erzeugt. +Picture Bild +Picture Format Bildformat +Picture Styles Bildformatvorlagen +Picture from File… Bild aus Datei… +Picture or texture fill Bild- oder Texturfüllung +Picture\nStyles Bildformatvorlagen +Pictures Bilder +Pie Kreis +Pin Anheften +Placeholder colour Platzhalterfarbe +Plan\nBuild\nLaunch Planen\nErstellen\nStarten +Plaque Tafel +Play Abspielen +Play Across Slides Über mehrere Folien abspielen +Play Full Screen Im Vollbild abspielen +Play Narrations Kommentare wiedergeben +Play from Current Slide Ab aktueller Folie abspielen +Play from Start Von Anfang abspielen +Play from Start (F5) Von Anfang abspielen (F5) +Play from\nCurrent Slide Ab aktueller Folie +Play from\nStart Von Anfang +Play/Pause Abspielen/Anhalten +Playback Wiedergabe +Plus Plus +Plus In Plus von innen +Plus Out Plus von außen +Plus Sign Pluszeichen +Portrait (9:16) Hochformat (9:16) +Português Português +Position Position +Position Objects Objekte positionieren +Position and Size Position und Größe +Post Senden +Poster Frame Titelbild +PowerPoint Presentation (.pptx) PowerPoint-Präsentation (.pptx) +Preferences Optionen +Preferences… Optionen… +Presentation Präsentation +Presentations Präsentationen +Presentations and slide shows, rebuilt from scratch in pure Rust. Präsentationen und Bildschirmpräsentationen, von Grund auf in reinem Rust neu gebaut. +Presented by a speaker (full screen) Präsentation durch einen Redner (Vollbild) +Presenter View Referentenansicht +Presenter View — DeckCraft Referentenansicht — DeckCraft +Presenter\nView Referentenansicht +Preset gradients Vorgegebene Verläufe +Prestige Prestige +Preview Vorschau +Previous Slide Vorherige Folie +Print layout: Drucklayout: +Properties Eigenschaften +Pulse Pulsieren +Punctuation Satzzeichen +Purple Violett +Push Schieben +Pyramid Pyramide +Quick Styles Schnellformatvorlagen +Quick\nStyles Schnellformatvorlagen +Radar Netz +Radial Radial +Random Zufällig +Random Bars Zufallsbalken +Reading View Leseansicht +Reading\nView Leseansicht +Real name Echter Name +Recent Zuletzt verwendet +Record Aufzeichnen +Recording narration needs audio capture (coming soon) Das Aufzeichnen von Kommentaren erfordert Audioaufnahme (in Kürze) +Recovered Presentations Wiederhergestellte Präsentationen +Recovered {} from the last session {} aus der letzten Sitzung wiederhergestellt +Rectangle Rechteck +Rectangle: Diagonal Corners Rounded Rechteck: diagonale Ecken abgerundet +Rectangle: Diagonal Corners Snipped Rechteck: diagonale Ecken abgeschnitten +Rectangle: Rounded Corners Rechteck: abgerundete Ecken +Rectangle: Single Corner Rounded Rechteck: eine abgerundete Ecke +Rectangle: Single Corner Snipped Rechteck: eine abgeschnittene Ecke +Rectangle: Top Corners One Rounded and One Snipped Rechteck: obere Ecken, eine abgerundet und eine abgeschnitten +Rectangle: Top Corners Rounded Rechteck: obere Ecken abgerundet +Rectangle: Top Corners Snipped Rechteck: obere Ecken abgeschnitten +Rectangles Rechtecke +Rectangular Rechteckig +Red Rot +Red Pen Roter Stift +Redo Wiederholen +Redo (⌘Y) Wiederholen (⌘Y) +Reflected Rounded Rectangle Abgerundetes Rechteck mit Reflexion +Reflection Reflexion +Regroup Erneut gruppieren +Regular Pentagon Regelmäßiges Fünfeck +Rehearse Timings Timings proben +Rehearse\nTimings Timings proben +Remove Entfernen +Remove All Animations Alle Animationen entfernen +Remove All Sections Alle Abschnitte entfernen +Remove Animation Animation entfernen +Remove Background Hintergrund entfernen +Remove Background (coming soon) Hintergrund entfernen (in Kürze) +Remove Section Abschnitt entfernen +Remove Section & Slides Abschnitt und Folien entfernen +Remove stop Verlaufspunkt entfernen +Remove\nBackground Hintergrund entfernen +Rename Umbenennen +Rename Layout Layout umbenennen +Rename Section Abschnitt umbenennen +Rename Section… Abschnitt umbenennen… +Rename Slide Folie umbenennen +Rename… Umbenennen… +Render Slide Folie rendern +Reopen Erneut öffnen +Reorder Animation Animation neu anordnen +Reorder Objects Objekte neu anordnen +Replace straight quotes with smart quotes Gerade Anführungszeichen durch typografische ersetzen +Reply Antworten +Reply… Antworten… +Reset Zurücksetzen +Reset Background Hintergrund zurücksetzen +Reset Crop Zuschnitt zurücksetzen +Reset Effects Effekte zurücksetzen +Reset Picture Bild zurücksetzen +Reset Slide Folie zurücksetzen +Reset Slide Background Folienhintergrund zurücksetzen +Resize shape to fit text Form an Text anpassen +Resolve Als gelöst markieren +Resolve Thread Unterhaltung als gelöst markieren +Return Zurückkehren +Reveal Aufdecken +Reverse the order Reihenfolge umkehren +Revert Zurücksetzen auf frühere Version +Review Überprüfen +Rewind after Playing Nach dem Abspielen zurückspulen +Ribbon Tab Menübandregisterkarte +Ribbon: Tilted Down Band: nach unten geneigt +Ribbon: Tilted Up Band: nach oben geneigt +Right Rechts +Right Brace Rechte geschweifte Klammer +Right Bracket Rechte eckige Klammer +Right Triangle Rechtwinkliges Dreieck +Right-to-Left Text Direction Textrichtung von rechts nach links +Ring Ring +Ripple Kräuseln +Rise Up Aufsteigen +Rotate Drehen +Rotate Left 90° Um 90° nach links drehen +Rotate Right 90° Um 90° nach rechts drehen +Rotate all text 270° Gesamten Text um 270° drehen +Rotate all text 90° Gesamten Text um 90° drehen +Rotate with shape Mit Form drehen +Rotation Drehung +Round Dot Runder Punkt +Rounded Diagonal Corner Abgerundete diagonale Ecke +Ruler Lineal +Saturation Sättigung +Saturation {}% Sättigung {} % +Save Speichern +Save (⌘S) Speichern (⌘S) +Save As… Speichern unter… +Save AutoRecover Information AutoWiederherstellen-Informationen speichern +Save as Template… Als Vorlage speichern… +Save to Data In Daten speichern +Saved Gespeichert +Saved {path} Gespeichert: {path} +Scatter Punkt +ScreenTip: Bildschirmtipp: +Screenshot Screenshot +Screenshot (not available yet) Screenshot (noch nicht verfügbar) +Scroll: Horizontal Schriftrolle: Horizontal +Scroll: Vertical Schriftrolle: Vertikal +Search commands (⇧⌘P) Befehle suchen (⇧⌘P) +Search commands… Befehle suchen… +Section Abschnitt +Seek Position suchen +Select Auswählen +Select All Alles auswählen +Select All Text Gesamten Text auswählen +Select Cells Zellen auswählen +Select Objects Objekte auswählen +Select Paragraph Absatz auswählen +Select Slides Folien auswählen +Select Text Text auswählen +Select Word Wort auswählen +Select a chart first. Wählen Sie zuerst ein Diagramm aus. +Select a shape to format it. Wählen Sie eine Form aus, um sie zu formatieren. +Select an object on the slide and add an animation from the Animations tab. Wählen Sie ein Objekt auf der Folie aus und fügen Sie auf der Registerkarte Animationen eine Animation hinzu. +Selection Auswahl +Selection Pane Auswahlbereich +Selection Pane… Auswahlbereich… +Selection\nPane Auswahlbereich +Send Backward Ebene nach hinten +Send to Back In den Hintergrund +Send\nBackward Ebene nach hinten +Sentence case. Satzanfang groß. +Set Text Text festlegen +Set Up Show… Bildschirmpräsentation einrichten… +Set Up Slide Show Bildschirmpräsentation einrichten +Set Up Slide Show… Bildschirmpräsentation einrichten… +Set Up\nSlide Show Bildschirmpräsentation einrichten +Set as Default Shape Als Standardform festlegen +Shading Schattierung +Shadow Schatten +Shape Form +Shape Effects Formeffekte +Shape Fill Formfüllung +Shape Format Formformat +Shape Gallery Formenkatalog +Shape Outline Formkontur +Shape Styles Formformatvorlagen +Shape {} Form {} +Shape\nStyles Formformatvorlagen +Shapes Formen +Shift+ Umschalt+ +Shift+F9 Umschalt+F9 +Show Anzeigen +Show All Alle anzeigen +Show Comments Kommentare anzeigen +Show Media Controls Mediensteuerelemente anzeigen +Show Slide Folie anzeigen +Show smart guides Intelligente Führungslinien anzeigen +Show type Präsentationstyp +Show without animation Ohne Animation anzeigen +Show without narration Ohne Kommentare anzeigen +Show/Hide Ein-/Ausblenden +Show\nComments Kommentare anzeigen +Shred Zerkleinern +Shrink & Turn Verkleinern und drehen +Shrink text on overflow Text bei Überlauf verkleinern +Simple Frame, White Einfacher Rahmen, weiß +Size Größe +Size & Properties Größe und Eigenschaften +Slide Master Folienmaster +Slide Number Foliennummer +Slide Show Bildschirmpräsentation +Slide Size Foliengröße +Slide Sorter Foliensortierung +Slide number Foliennummer +Slide timings recorded. Folien-Zeitaufzeichnungen gespeichert. +Slide {:02}:{:04.1} Total {:02}:{:02} Folie {:02}:{:04.1} Gesamt {:02}:{:02} +Slide {} of {} Folie {} von {} +Slide {}: {}{} Folie {}: {}{} +Slide {}: “{w}” Folie {}: „{w}“ +Slide\nMaster Folienmaster +Slide\nNumber Foliennummer +Slide\nSize Foliengröße +Slide\nSorter Foliensortierung +Slides (e.g. 1,3,5): Folien (z. B. 1,3,5): +Slides from Outline Folien aus Gliederung +Slides from Outline… Folien aus Gliederung… +Slides sized for: Foliengröße formatiert für: +SmartArt SmartArt +Smile Lächeln +Smiley Face Lächelndes Gesicht +Smoothly Sanft +Smoothly Left Sanft nach links +Smoothly Right Sanft nach rechts +Snap objects to grid Objekte am Raster ausrichten +Soft Edge Rectangle Rechteck mit weichen Kanten +Soft Edges Weiche Kanten +Solid Einfarbig +Solid fill Einfarbige Füllung +Solid line Durchgezogene Linie +Sort Sortieren +Source on GitHub Quellcode auf GitHub +Space Leertaste +Spacing after (pt): Abstand nach (pt): +Spacing before (pt): Abstand vor (pt): +Special — hanging (in): Spezial — hängend (Zoll): +Speech Sprachausgabe +Speech Bubble: Oval Sprechblase: Oval +Speech Bubble: Rectangle Sprechblase: Rechteck +Speech Bubble: Rectangle with Corners Rounded Sprechblase: Rechteck mit abgerundeten Ecken +Spelling Rechtschreibung +Spin Rotieren +Spinner Dauerdrehung +Split Teilen +Split Cells Zellen teilen +Split\nCells Zellen teilen +Square Quadrat +Square (1:1) Quadrat (1:1) +Square Dot Quadratischer Punkt +Stacked Gestapelt +Stacked Area Gestapelte Fläche +Stacked Bar Gestapelte Balken +Stacked Column Gestapelte Säulen +Stacked Line Gestapelte Linie +Standard (4:3) Standard (4:3) +Standard Colors Standardfarben +Star Stern +Star: 10 Points Stern: 10 Zacken +Star: 12 Points Stern: 12 Zacken +Star: 16 Points Stern: 16 Zacken +Star: 24 Points Stern: 24 Zacken +Star: 32 Points Stern: 32 Zacken +Star: 4 Points Stern: 4 Zacken +Star: 5 Points Stern: 5 Zacken +Star: 6 Points Stern: 6 Zacken +Star: 7 Points Stern: 7 Zacken +Star: 8 Points Stern: 8 Zacken +Stars and Banners Sterne und Banner +Start After Previous Nach vorheriger +Start Automatically Automatisch +Start On Click Beim Klicken +Start With Previous Mit vorheriger +Start a conversation Beginnen Sie eine Unterhaltung +Start time (s): Startzeit (s): +Start: Start: +Stealth end Pfeilspitze +Stock Kurs +Stop Beenden +Stop Editing Text Textbearbeitung beenden +Strikethrough Durchgestrichen +Strips Streifen +Style {i} Formatvorlage {i} +Subscript Tiefgestellt +Subtle Dezent +Sun Sonne +Sunburst Sunburst +Superscript Hochgestellt +Surface Oberfläche +Switch Umschalten +Swivel Schwenken +Symbol Symbol +System language Systemsprache +Tab Tab +Table Tabelle +Table Design Tabellenentwurf +Table Style Options Tabellenformatoptionen +Table Styles Tabellenformatvorlagen +Table… Tabelle… +Task Pane Aufgabenbereich +Teardrop Tropfen +Teeter Wackeln +Text Text +Text Box Textfeld +Text Box Margins Textfeldränder +Text Direction Textrichtung +Text Effects Texteffekte +Text Fill Textfüllung +Text Highlight Color Textmarkierungsfarbe +Text Options Textoptionen +Text Outline Textkontur +Text Shadow Textschatten +Text/Background - Dark 1 Text/Hintergrund - dunkel 1 +Text/Background - Dark 2 Text/Hintergrund - dunkel 2 +Text/Background - Light 1 Text/Hintergrund - hell 1 +Text/Background - Light 2 Text/Hintergrund - hell 2 +Text\nBox Textfeld +The spelling check is complete. No issues found. Die Rechtschreibprüfung ist abgeschlossen. Keine Fehler gefunden. +Theme Colors Designfarben +Theme Gallery Designkatalog +Themes Designs +Thesaurus Thesaurus +Thesaurus (coming soon) Thesaurus (in Kürze) +This Document Dieses Dokument +Thought Gedanke +Thought Bubble: Cloud Gedankenblase: Wolke +Through Black Über Schwarz +Tight Eng +Timing Timing +Top Oben +Total Row Ergebniszeile +Transition Übergang +Transition Gallery Übergangskatalog +Transitions Übergänge +Translate Übersetzen +Translation needs a language model (not bundled) Übersetzung erfordert ein Sprachmodell (nicht im Lieferumfang) +Transparency Transparenz +Trapezoid Trapez +Treemap Treemap +Triangle Dreieck +Trigger Auslöser +Trim Kürzen +Trim Media Medien kürzen +Turns Drehungen +Type Typ +Type Text Text eingeben +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Geben Sie eine Gleichung in linearer Form ein (z. B. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Aufdecken +Underline Unterstrichen +Undo Rückgängig +Undo (⌘Z) Rückgängig (⌘Z) +Ungroup Gruppierung aufheben +Up Nach oben +Use Timings Timings verwenden +Use timings, if present Timings verwenden, falls vorhanden +Username Benutzername +Version Version +Version {} Version {} +Vert In Vertikal von innen +Vert Out Vertikal von außen +Vertical Vertikal +Vertical alignment Vertikale Ausrichtung +Very Loose Sehr weit +Very Tight Sehr eng +Video Video +Video from File… Video aus Datei… +View Ansicht +Volume Lautstärke +Vortex Wirbel +Waterfall Wasserfall +Wave Welle +Web Page or File Webseite oder Datei +Wedge Keil +Weight Stärke +Wheel Rad +Widescreen (13.333x7.5 in) Breitbild (13,333×7,5 Zoll) +Widescreen (16:9) Breitbild (16:9) +Width Breite +Width (in): Breite (Zoll): +Width: Breite: +Width: Breite: +Wind Wind +Window Fenster +Wipe Wischen +With Previous Mit vorheriger +WordArt WordArt +WordArt style {} WordArt-Formatvorlage {} +Words Wörter +Wrap Text in Shape Text in Form umbrechen +Wrap text in shape Text in Form umbrechen +Yellow Gelb +Your changes will be lost if you don't save them. Ihre Änderungen gehen verloren, wenn Sie nicht speichern. +Your name (comments): Ihr Name (Kommentare): +Zoom Zoom +Zoom In Vergrößern +Zoom Out Verkleinern +Zoom… Zoom… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Revision übernehmen +Action Settings Aktionseinstellungen +Add Font Schriftart hinzufügen +Add Guide Führungslinie hinzufügen +Add Point Punkt hinzufügen +Add Shape Form hinzufügen +Add to Dictionary Zum Wörterbuch hinzufügen +Align Cell Text Zelltext ausrichten +Apply Design Idea Designidee anwenden +Arrow: Circular Pfeil: kreisförmig +Arrow: Circular Counter-clockwise Pfeil: kreisförmig gegen den Uhrzeigersinn +Arrow: Circular Two-headed Pfeil: kreisförmig mit zwei Spitzen +Arrow: Curved Down Pfeil: nach unten gebogen +Arrow: Curved Left Pfeil: nach links gebogen +Arrow: Curved Right Pfeil: nach rechts gebogen +Arrow: Curved Up Pfeil: nach oben gebogen +Arrow: Swoosh Pfeil: Schwung +Artistic Effects Künstlerische Effekte +AutoCorrect Options AutoKorrektur-Optionen +Bean Bohne +Borders Rahmenlinien +Bounce Left Sprung nach links +Bounce Right Sprung nach rechts +Browse for Themes… Nach Designs durchsuchen… +Callout: Bent Line Legende: gewinkelte Linie +Callout: Bent Line with Accent Bar Legende: gewinkelte Linie mit Akzentleiste +Callout: Bent Line with Border and Accent Bar Legende: gewinkelte Linie mit Rahmen und Akzentleiste +Callout: Bent Line with No Border Legende: gewinkelte Linie ohne Rahmen +Callout: Double Bent Line Legende: doppelt gewinkelte Linie +Callout: Double Bent Line with Accent Bar Legende: doppelt gewinkelte Linie mit Akzentleiste +Callout: Double Bent Line with Border and Accent Bar Legende: doppelt gewinkelte Linie mit Rahmen und Akzentleiste +Callout: Double Bent Line with No Border Legende: doppelt gewinkelte Linie ohne Rahmen +Callout: Left-Right Arrow Legende: Pfeil nach links und rechts +Callout: Line with Accent Bar Legende: Linie mit Akzentleiste +Callout: Line with Border and Accent Bar Legende: Linie mit Rahmen und Akzentleiste +Callout: Line with No Border Legende: Linie ohne Rahmen +Callout: Quad Arrow Legende: Vierfachpfeil +Callout: Up-Down Arrow Legende: Pfeil nach oben und unten +Cell Margins Zellenränder +Change Colors Farben ändern +Change Layout Layout ändern +Change Picture… Bild ändern… +Change Spelling Rechtschreibung ändern +Chart Marker: Cross Lines Diagrammmarkierung: Kreuzlinien +Chart Marker: Plus Lines Diagrammmarkierung: Pluslinien +Chart Marker: Star Lines Diagrammmarkierung: Sternlinien +Color At Farbe bei +Commit Composition Zusammensetzung übernehmen +Compare Vergleichen +Compare… Vergleichen… +Compose Text Text zusammensetzen +Compress Pictures Bilder komprimieren +Contract Zusammenziehen +Convert to Shapes In Formen konvertieren +Convert to SmartArt In SmartArt konvertieren +Convert to Text In Text konvertieren +Corner Tabs: Quarter Circles Ecklaschen: Viertelkreise +Corner Tabs: Squares Ecklaschen: Quadrate +Corner Tabs: Triangles Ecklaschen: Dreiecke +Crescent Moon Mondsichel +Curved Square Gekrümmtes Quadrat +Decaying Wave Abklingende Welle +Delete Guide Führungslinie löschen +Delete Point Punkt löschen +Demote Tieferstufen +Diagonal Down Right Diagonal nach unten rechts +Diagonal Up Right Diagonal nach oben rechts +Draw Table Tabelle zeichnen +dropped file abgelegte Datei +Edit Photo Album… Fotoalbum bearbeiten… +Edit Points Punkte bearbeiten +Edit SmartArt Text SmartArt-Text bearbeiten +End Review Überprüfung beenden +Find Suchen +Flowchart: Offline Storage Flussdiagramm: Externer Speicher +Fonts in Presentation Schriftarten in der Präsentation +Font… Schriftart… +Football Football +Gear: 6 Teeth Zahnrad: 6 Zähne +Gear: 9 Teeth Zahnrad: 9 Zähne +Grid and Guides Raster und Hilfslinien +Grid Options… Rasteroptionen… +Handout Placeholders Handzettelplatzhalter +Heartbeat Herzschlag +Hex D Sechseck unten +Hex L Sechseck links +Hex R Sechseck rechts +Hex U Sechseck oben +Horizontal Figure 8 Horizontale Acht +i. ii. iii. i. ii. iii. +Icon Gallery Symbolkatalog +Info Informationen +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Freihand in Form: verwandelt gezeichnete Linien, Rechtecke, Ovale und Dreiecke in Formen +Insert Picture in SmartArt Bild in SmartArt einfügen +Insert Picture in SmartArt… Bild in SmartArt einfügen… +Insert Synonym Synonym einfügen +Layout Placeholders Layoutplatzhalter +Line: Rising Linie: aufsteigend +Loop de Loop Looping +Move Guide Führungslinie verschieben +Move Handle Ziehpunkt verschieben +Move Point Punkt verschieben +Neutron Neutron +New Window Neues Fenster +Next Comment Nächster Kommentar +No comments. Keine Kommentare. +no presentation open Keine Präsentation geöffnet +no slides Keine Folien +no text insertion point Keine Texteinfügemarke +Notes Placeholders Notizenplatzhalter +nothing selected Nichts ausgewählt +nothing to redo Nichts zum Wiederholen +nothing to undo Nichts rückgängig zu machen +Open Öffnen +Particles In Partikel hinein +Particles Out Partikel heraus +Paste Special Inhalte einfügen +Paste Special… Inhalte einfügen… +Peanut Erdnuss +Peek Out Hinauslugen +Photo Album… Fotoalbum… +Pick a design for this slide. Ideas are generated on your device. Wählen Sie ein Design für diese Folie. Ideen werden auf Ihrem Gerät erzeugt. +Picture Style Gallery Bildformatvorlagenkatalog +Point Type Punkttyp +Points Punkte +Preserve Beibehalten +Preview Animations Animationen in der Vorschau anzeigen +Previous Comment Vorheriger Kommentar +Print Drucken +Print… Drucken… +Promote Höherstufen +Quarter Wedge Viertelkeil +Quick Access Toolbar Symbolleiste für den Schnellzugriff +Recolor Umfärben +Recolor Gallery Umfärbungskatalog +Remove Shape Form entfernen +Replace Ersetzen +Replace Fonts Schriftarten ersetzen +Replace… Ersetzen… +Rescan Installed Fonts Installierte Schriftarten neu einlesen +Reuse Slides… Folien wiederverwenden… +Revisions Revisionen +Ribbon: Curved and Tilted Down Band: gekrümmt und nach unten geneigt +Ribbon: Curved and Tilted Up Band: gekrümmt und nach oben geneigt +Ribbon: Left-Right Fold Band: links-rechts gefaltet +S Curve 1 S-Kurve 1 +S Curve 2 S-Kurve 2 +select text or a shape Text oder eine Form auswählen +select two or more objects Zwei oder mehr Objekte auswählen +Set Transparent Color Transparente Farbe festlegen +Set Zoom Zoom festlegen +Sine Wave Sinuswelle +Single L Einfach links +Single R Einfach rechts +Sink Down Absinken +size (pt) Größe (pt) +Size and Position… Größe und Position… +SmartArt Styles SmartArt-Formatvorlagen +Smooth Corners Ecken abrunden +Sound Sound +Spelling Dictionary Rechtschreibwörterbuch +Spiral Left Spirale nach links +Spiral Right Spirale nach rechts +Spring Feder +Stairs Down Treppe hinunter +Starter Templates Startvorlagen +Strips In Streifen hinein +Strips Out Streifen heraus +Swoosh Schwung +Table Eraser Tabellenradierer +Tabs… Tabstopps… +Text Pane Textbereich +Text Transform Text transformieren +Text Transparency Texttransparenz +tOGGLE cASE gROSS-/kLEINSCHREIBUNG uMKEHREN +Trapezoid: Uneven Sides Trapez: ungleiche Seiten +unknown interface language Unbekannte Sprache der Benutzeroberfläche +Unlock Entsperren +Variant Gallery Variantenkatalog +Variants Varianten +Vertical Figure 8 Vertikale Acht +Zigzag Zickzack + (not checked) (nicht geprüft) +4 Point Star Stern mit 4 Zacken +5 Point Star Stern mit 5 Zacken +6 Point Star Stern mit 6 Zacken +8 Point Star Stern mit 8 Zacken +{ch} Bullet {ch} Aufzählungszeichen +{f} (Body) {f} (Text) +{f} (Headings) {f} (Überschriften) +{name}: DeckCraft can't open this kind of file {name}: DeckCraft kann diese Art von Datei nicht öffnen +{n} Column{} {n} Spalte{} +{r} pt {r} pt +{r} pt glow Leuchten {r} pt +{w} pt {w} pt +{} ({} slides) {} ({} Folien) +{} Slide Master Folienmaster {} +{} contributors · {} commits Mitwirkende: {} · Commits: {} +{} presentations {} Präsentationen +{}x{} Table Tabelle {}×{} +“{}” is not available yet. „{}“ ist noch nicht verfügbar. +−Bin −Intervall +▶ Play All ▶ Alles abspielen +◀ Previous ◀ Zurück +✏ on ✏ aktiv diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv new file mode 100644 index 000000000..9f7e80966 --- /dev/null +++ b/crates/ui-egui/src/i18n/es.tsv @@ -0,0 +1,1408 @@ +# Spanish interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Fecha fija (vacío = actualización automática): + Footer text: Texto del pie de página: + Present Presentar + pt pt + — Edited — Editado +"Not Allowed" Symbol Símbolo «Prohibido» +% of all commits % de todas las confirmaciones ++ New Comment + Nuevo comentario ++ New Slide + Nueva diapositiva ++ Row + Fila ++ Series + Serie ++Bin +Intervalo +100% Stacked Bar Barra 100% apilada +100% Stacked Column Columna 100% apilada +35mm Slides Diapositivas de 35 mm +@ribbon:Home Inicio +@ribbon:Insert Insertar +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{}: solicitudes de cambios (PR): {}, confirmaciones: {}, líneas: +{} / −{} (Δ {}), recursos binarios: +{} / −{}, {} – {} +A3 Paper (297x420 mm) Papel A3 (297×420 mm) +A4 Paper (210x297 mm) Papel A4 (210×297 mm) +Aa Aa +Abc Abc +About Acerca de +About DeckCraft Acerca de DeckCraft +Accent 1 Énfasis 1 +Accent 2 Énfasis 2 +Accent 3 Énfasis 3 +Accent 4 Énfasis 4 +Accent 5 Énfasis 5 +Accent 6 Énfasis 6 +Accessibility Checker Comprobador de accesibilidad +Across A través +Action Acción +Action Button: Custom Botón de acción: personalizado +Action Button: Document Botón de acción: documento +Action Button: Get Information Botón de acción: obtener información +Action Button: Go Back Botón de acción: volver +Action Button: Go Back or Previous Botón de acción: atrás o anterior +Action Button: Go Forward or Next Botón de acción: adelante o siguiente +Action Button: Go Home Botón de acción: inicio +Action Button: Go to Beginning Botón de acción: al principio +Action Button: Go to End Botón de acción: al final +Action Button: Help Botón de acción: ayuda +Action Button: Sound Botón de acción: sonido +Action Button: Video Botón de acción: vídeo +Action Button: {k} Botón de acción: {k} +Action Buttons Botones de acción +Add Animation Agregar animación +Add Section Agregar sección +Add\nAnimation Agregar animación +Address: Dirección: +Adjust Shape Ajustar forma +After Previous Después de la anterior +After: Después: +Airplane Avión +Align Alinear +Align Bottom Alinear abajo +Align Center Alinear al centro +Align Left Alinear a la izquierda +Align Middle Alinear al medio +Align Right Alinear a la derecha +Align Text Alinear texto +Align Top Alinear arriba +Alt Text Texto alternativo +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Texto alternativo +An open-source, clean-room project. Not affiliated with Microsoft. Proyecto independiente de código abierto. No está afiliado a Microsoft. +Angle Ángulo +Animation Gallery Galería de animación +Animation Pane Panel de animación +Animation Styles Estilos de animación +Animation\nPane Panel de animación +Animations Animaciones +Animation Painter Copiador de animación +Apply Animation Aplicar animación +Play/Pause GIF Reproducir/pausar GIF +Animations on Slide Animaciones en la diapositiva +Appear Aparecer +Apply Aplicar +Apply To All Aplicar a todo +Apply to All Aplicar a todo +Apply\nTo All Aplicar a todo +Arc Arco +Arcs Arcos +Area Área +Arrange Organizar +Arrow Flecha +Arrow at end Flecha al final +Arrow at start Flecha al inicio +Arrow: Bent Flecha: doblada +Arrow: Bent-Up Flecha: doblada hacia arriba +Arrow: Chevron Flecha: galón +Arrow: Down Flecha: abajo +Arrow: Left Flecha: izquierda +Arrow: Left-Right Flecha: izquierda-derecha +Arrow: Left-Right-Up Flecha: izquierda-derecha-arriba +Arrow: Left-Up Flecha: izquierda-arriba +Arrow: Notched Right Flecha: derecha dentada +Arrow: Pentagon Flecha: pentagonal +Arrow: Quad Flecha: de cuatro puntas +Arrow: Right Flecha: derecha +Arrow: Striped Right Flecha: derecha a rayas +Arrow: U-Turn Flecha: en U +Arrow: Up Flecha: arriba +Arrow: Up-Down Flecha: arriba-abajo +Arrows Flechas +Arrows at both ends Flechas en ambos extremos +As One Object Como un objeto +Audio Audio +Audio from File… Audio desde archivo… +AutoCorrect as you type Autocorrección mientras se escribe +Autofit Ajuste automático +Automatic Automático +B4 (ISO) Paper (250x353 mm) Papel B4 (ISO) (250×353 mm) +B5 (ISO) Paper (176x250 mm) Papel B5 (ISO) (176×250 mm) +Background Fondo +Background Styles Estilos de fondo +Background\nStyles Estilos de fondo +Backspace Retroceso +Banded Columns Columnas con bandas +Banded Rows Filas con bandas +Banner Estandarte +Basic Cycle Ciclo básico +Basic List Lista básica +Basic Process Proceso básico +Basic Shapes Formas básicas +Before text (in): Antes del texto (pulgadas): +Bevel Bisel +Binary assets added Recursos binarios añadidos +Binary assets removed Recursos binarios eliminados +Black Left A través de negro a la izquierda +Black Pen Bolígrafo negro +Black Right A través de negro a la derecha +Blinds Persianas +Block Arc Arco de bloque +Block Arrows Flechas de bloque +Blue Azul +Blue Pen Bolígrafo azul +Bold Negrita +Bold Flash Destello audaz +Both Ambos +Bottom Abajo +Bounce Rebote +Box Caja +Box In Caja hacia dentro +Box Out Caja hacia fuera +Box and Whisker Caja y bigotes +Brightness Brillo +Brightness {:+}% Brillo {:+}% +Bring Forward Traer adelante +Bring to Front Traer al frente +Bring\nForward Traer adelante +Browsed at a kiosk (full screen) Examinar en un quiosco (pantalla completa) +Browsed by an individual (window) Examinar individualmente (ventana) +Bubble Burbuja +Bullets Viñetas +Burst Explosión +By Paragraph Por párrafo +Callout: Down Arrow Globo: flecha abajo +Callout: Left Arrow Globo: flecha izquierda +Callout: Line Globo: línea +Callout: Right Arrow Globo: flecha derecha +Callout: Up Arrow Globo: flecha arriba +Callouts Globos +Cameo Cameo +Camera capture is not available yet La captura de cámara aún no está disponible +Cancel Cancelar +Capitalize Each Word Poner mayúscula a cada palabra +Caps Mayúsculas +Center Centrar +Centered Centrado +Change Case Cambiar mayúsculas y minúsculas +Change Chart Type Cambiar tipo de gráfico +Change Picture Cambiar imagen +Change Shape Cambiar forma +Change\nChart Type Cambiar tipo de gráfico +Character Spacing Espaciado entre caracteres +Characters Caracteres +Chart Gráfico +Chart Data Datos del gráfico +Chart Design Diseño de gráfico +Chart Elements Elementos de gráfico +Chart… Gráfico… +Check Accessibility Comprobar accesibilidad +Check\nAccessibility Comprobar accesibilidad +Checkerboard Tablero de ajedrez +Chevron Galón +Choose a SmartArt Graphic Elegir un gráfico SmartArt +Chord Cuerda +Circle Círculo +Circle In Círculo hacia dentro +Circle Out Círculo hacia fuera +Clear All Formatting Borrar todo el formato +Click a symbol to insert it at the insertion point. Haga clic en un símbolo para insertarlo en el punto de inserción. +Click icon to add SmartArt graphic Haga clic en el icono para agregar un gráfico SmartArt +Click icon to add chart Haga clic en el icono para agregar un gráfico +Click icon to add media Haga clic en el icono para agregar multimedia +Click icon to add picture Haga clic en el icono para agregar una imagen +Click icon to add table Haga clic en el icono para agregar una tabla +Click to add first slide Haga clic para agregar la primera diapositiva +Click to add notes Haga clic para agregar notas +Click to add subtitle Haga clic para agregar subtítulo +Click to add text Haga clic para agregar texto +Click to add title Haga clic para agregar título +Click to edit Master text styles Haga clic para editar los estilos de texto del patrón +Click to edit Master title style Haga clic para editar el estilo de título del patrón +Clock Reloj +Clockwise En sentido horario +Close Cerrar +Close Master View Cerrar la vista Patrón +Close\nMaster View Cerrar la vista Patrón +Cloud Nube +Clustered Bar Barras agrupadas +Clustered Column Columnas agrupadas +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Contraer la cinta de opciones +Color Color +Color Pulse Pulso de color +Colors Colores +Columns Columnas +Comb Peine +Combo Combinado +Command Palette Paleta de comandos +Comment Comentario +Comments Comentarios +Commits Confirmaciones +Community Links Enlaces de la comunidad +Company Empresa +Complementary Color Color complementario +Connect Shapes Conectar formas +Connection Sites Puntos de conexión +Connector: Curved Conector: curvo +Connector: Elbow Conector: acodado +Connector: Elbow (one bend) Conector: acodado (un codo) +Content Contenido +Contrast Contraste +Contrast {:+}% Contraste {:+}% +Contributors Colaboradores +Conveyor Cinta transportadora +Copy Copiar +Corrections Correcciones +Couldn't save AutoRecover information: {e} No se pudo guardar la información de autorrecuperación: {e} +Counter Clockwise En sentido antihorario +Cover Cubrir +Create Crear +Crop Recortar +Crop 10% each side Recortar un 10% por lado +Crop 20% each side Recortar un 20% por lado +Crop to Shape Recortar a la forma +Cross Cruz +Crush Aplastar +Ctrl+ Ctrl+ +Cube Cubo +Currency Moneda +Curtains Cortinas +Custom Personalizado +Custom Path Ruta personalizada +Custom Show Presentación personalizada +Custom Show 1 Presentación personalizada 1 +Custom Shows Presentaciones personalizadas +Custom Slide Show Presentación personalizada +Custom\nShow Presentación personalizada +Cut Cortar +Cylinder Cilindro +Dark Blue Azul oscuro +Dark Mode Modo oscuro +Dark Red Rojo oscuro +Dark appearance Apariencia oscura +Dark\nMode Modo oscuro +Darken Oscurecer +Dash Guion +Dash Dot Guion y punto +Dashes Guiones +Database Base de datos +Date Fecha +Date & Time Fecha y hora +Date &\nTime Fecha y hora +Date and Time Fecha y hora +Date and time Fecha y hora +Decagon Decágono +Decision Decisión +DeckCraft DeckCraft +Decrease Font Size Reducir el tamaño de fuente +Decrease List Level Disminuir el nivel de lista +Delay: Retardo: +Delete Eliminar +Delete Columns Eliminar columnas +Delete Comment Eliminar comentario +Delete Layout Eliminar diseño +Delete Rows Eliminar filas +Delete Slide Eliminar diapositiva +Delete Table Eliminar tabla +Delete Text Eliminar texto +Desaturate Desaturar +Deselect Anular selección +Design Diseño +Design Ideas Ideas de diseño +Design\nIdeas Ideas de diseño +Deutsch Deutsch +Diagonal Stripe Franja diagonal +Diamond Rombo +Diamond In Rombo hacia dentro +Diamond Out Rombo hacia fuera +Direction Dirección +Disappear Desaparecer +Discard Recovered Presentations Descartar presentaciones recuperadas +Display name Nombre para mostrar +Dissolve Disolución +Dissolve In Disolución hacia dentro +Dissolve Out Disolución hacia fuera +Distribute Distribuir +Distribute Columns Distribuir columnas +Distribute Horizontally Distribuir horizontalmente +Distribute Rows Distribuir filas +Distribute Vertically Distribuir verticalmente +Division Sign Signo de división +Do not Autofit No ajustar automáticamente +Do you want to save the changes you made to {what}? ¿Desea guardar los cambios realizados en {what}? +Document Documento +Dodecagon Dodecágono +Don't Save No guardar +Don't show on title slide No mostrar en la diapositiva de título +Done Listo +Donut Dona +Doors Puertas +Double Brace Llave doble +Double Bracket Corchete doble +Double Wave Doble onda +Doughnut Anillo +Down Abajo +Drape Drapeado +Draw Dibujar +Drop Shadow Rectangle Rectángulo con sombra +Duplicate Duplicar +Duplicate Selected Slides Duplicar las diapositivas seleccionadas +Duplicate Slide Duplicar diapositiva +Duration: Duración: +Dynamic Content Contenido dinámico +Edit Editar +Edit Alt Text… Editar texto alternativo… +Edit Data Editar datos +Edit Shape Editar forma +Edit Text Editar texto +Edit the data: first row = series names, first column = categories. Edite los datos: la primera fila son los nombres de las series, la primera columna las categorías. +Edit\nData Editar datos +Edit\nShape Editar forma +Editing Edición +Effect Options Opciones de efecto +Effect\nOptions Opciones de efecto +Effects Efectos +Email Address Dirección de correo electrónico +Email address: Dirección de correo electrónico: +Emphasis Énfasis +End Final +End Show Finalizar presentación +End of slide show Fin de la presentación +End of slide show, click to exit. Fin de la presentación. Haga clic para salir. +End trim (s): Recorte final (s): +English (United Kingdom) Inglés (Reino Unido) +English (United States) Inglés (Estados Unidos) +Enter Entrar +Entrance Entrada +Equals Igual +Equation Ecuación +Equation Shapes Formas de ecuación +Eraser Borrador +Escape Escape +Español Español +Exciting Llamativas +Exit Salida +Expand Expandir +Explosion: 14 Points Explosión: 14 puntas +Explosion: 8 Points Explosión: 8 puntas +Export Exportar +Export the presentation as: Exportar la presentación como: +Exported {path} Exportado: {path} +Export… Exportar… +Fade Fundido +Fade in (s): Fundido de entrada (s): +Fade out (s): Fundido de salida (s): +Fall Over Caer +Ferris Wheel Noria +File Archivo +Fill Relleno +Fill & Line Relleno y línea +Fill Color Color de relleno +Filled Radar Radar relleno +Find… Buscar… +First Primero +First Column Primera columna +First Slide Primera diapositiva +First commit Primera confirmación +Fit Ajustar +Fit slide to current window Ajustar la diapositiva a la ventana actual +Fit to Window Ajustar a la ventana +Fit to\nWindow Ajustar a la ventana +Flash Destello +Flip Voltear +Flip Horizontal Voltear horizontalmente +Flip Vertical Voltear verticalmente +Float In Flotar hacia dentro +Float Out Flotar hacia fuera +Flowchart Diagrama de flujo +Flowchart: Alternate Process Diagrama de flujo: proceso alternativo +Flowchart: Card Diagrama de flujo: tarjeta +Flowchart: Collate Diagrama de flujo: recopilación +Flowchart: Connector Diagrama de flujo: conector +Flowchart: Data Diagrama de flujo: datos +Flowchart: Decision Diagrama de flujo: decisión +Flowchart: Delay Diagrama de flujo: retardo +Flowchart: Direct Access Storage Diagrama de flujo: almacenamiento de acceso directo +Flowchart: Display Diagrama de flujo: pantalla +Flowchart: Document Diagrama de flujo: documento +Flowchart: Extract Diagrama de flujo: extracción +Flowchart: Internal Storage Diagrama de flujo: almacenamiento interno +Flowchart: Magnetic Disk Diagrama de flujo: disco magnético +Flowchart: Manual Input Diagrama de flujo: entrada manual +Flowchart: Manual Operation Diagrama de flujo: operación manual +Flowchart: Merge Diagrama de flujo: combinación +Flowchart: Multidocument Diagrama de flujo: multidocumento +Flowchart: Off-page Connector Diagrama de flujo: conector fuera de página +Flowchart: Or Diagrama de flujo: o +Flowchart: Predefined Process Diagrama de flujo: proceso predefinido +Flowchart: Preparation Diagrama de flujo: preparación +Flowchart: Process Diagrama de flujo: proceso +Flowchart: Punched Tape Diagrama de flujo: cinta perforada +Flowchart: Sequential Access Storage Diagrama de flujo: almacenamiento de acceso secuencial +Flowchart: Sort Diagrama de flujo: ordenación +Flowchart: Stored Data Diagrama de flujo: datos almacenados +Flowchart: Summing Junction Diagrama de flujo: unión de suma +Flowchart: Terminator Diagrama de flujo: inicio/fin +Fly In Entrar volando +Fly Out Salir volando +Fly Through Volar a través +Folded Corner Esquina doblada +Follow the layout Según el diseño +Followed Hyperlink Hipervínculo visitado +Font Fuente +Font Color Color de fuente +Font Size Tamaño de fuente +Fonts Fuentes +Footer Pie de página +Foreground Primer plano +Format Formato +Format Background Formato de fondo +Format Background… Formato de fondo… +Format Painter Copiar formato +Format Painter (double-click to keep it on) Copiar formato (doble clic para mantenerlo activo) +Format Pane Panel de formato +Format Shape Formato de forma +Format Shape… Formato de forma… +Format\nBackground Formato de fondo +Format\nPane Panel de formato +Formatting State Estado de formato +Fracture Fractura +Frame Marco +Français Français +Freeform Forma libre +From Desde +From Beginning Desde el principio +From Bottom Desde abajo +From Bottom Left Desde abajo a la izquierda +From Bottom Right Desde abajo a la derecha +From Current Slide Desde la diapositiva actual +From Left Desde la izquierda +From Right Desde la derecha +From Top Desde arriba +From Top Left Desde arriba a la izquierda +From Top Right Desde arriba a la derecha +From bottom left Desde abajo a la izquierda +From bottom right Desde abajo a la derecha +From center Desde el centro +From top left Desde arriba a la izquierda +From top right Desde arriba a la derecha +From\nBeginning Desde el principio +From\nCurrent Slide Desde la diapositiva actual +Full Completa +Full Page Slides Diapositivas en página completa +Funnel Embudo +Gallery Galería +General General +Get Text Obtener texto +Glitter Destellos +Glow Resplandor +Go to Ir a +Go to Slide Ir a la diapositiva +Grab bag Surtido variado +Gradient fill Relleno con degradado +Gradient stops Puntos de degradado +Gradient… Degradado… +Grayscale Escala de grises +Greek Griego +Green Verde +Gridlines Líneas de cuadrícula +Group Agrupar +Group Objects Agrupar objetos +Grow & Turn Crecer y girar +Grow/Shrink Crecer/Reducir +Guides Guías +Half Mitad +Half Frame Medio marco +Handout Master Patrón de documentos +Handout Master (coming soon) Patrón de documentos (próximamente) +Handout\nMaster Patrón de documentos +Handouts (1 slide per page) Documentos (1 diapositiva por página) +Handouts (2 slides per page) Documentos (2 diapositivas por página) +Handouts (3 slides per page) Documentos (3 diapositivas por página) +Handouts (4 slides per page) Documentos (4 diapositivas por página) +Handouts (6 slides per page) Documentos (6 diapositivas por página) +Handouts (9 slides per page) Documentos (9 diapositivas por página) +Header Encabezado +Header & Footer Encabezado y pie de página +Header &\nFooter Encabezado y pie de página +Header Row Fila de encabezado +Header and Footer Encabezado y pie de página +Header and Footer… Encabezado y pie de página… +Heart Corazón +Height Alto +Height (in): Alto (pulgadas): +Height: Alto: +Help Ayuda +Heptagon Heptágono +Hexagon Hexágono +Hide All Ocultar todo +Hide Background Graphics Ocultar gráficos de fondo +Hide During Show Ocultar durante la presentación +Hide Slide Ocultar diapositiva +Hide background graphics Ocultar gráficos de fondo +Hide\nSlide Ocultar diapositiva +Hierarchy Jerarquía +High Alta +Highlighter Resaltador +Histogram Histograma +Home Inicio +Honeycomb Panal +Horizontal Horizontal +Horz In Horizontal hacia dentro +Horz Out Horizontal hacia fuera +How would you describe this object and its context to someone who is blind or has low vision? ¿Cómo describiría este objeto y su contexto a una persona ciega o con baja visión? +Hyperlink Hipervínculo +Icons Iconos +In Hacia dentro +In Bounce Hacia dentro con rebote +Include hidden slides Incluir diapositivas ocultas +Increase Font Size Aumentar el tamaño de fuente +Increase List Level Aumentar el nivel de lista +Ink to Math Tinta a matemáticas +Ink to Math (coming soon) Tinta a matemáticas (próximamente) +Ink to Shape Tinta a forma +Ink to Shape (coming soon) Tinta a forma (próximamente) +Ink to Text Tinta a texto +Ink to Text (coming soon) Tinta a texto (próximamente) +Ink to\nMath Tinta a matemáticas +Ink to\nShape Tinta a forma +Ink to\nText Tinta a texto +Inner Interior +Insert Insertar +Insert Above Insertar arriba +Insert Below Insertar abajo +Insert Hyperlink Insertar hipervínculo +Insert Layout Insertar diseño +Insert Left Insertar a la izquierda +Insert Placeholder Insertar marcador de posición +Insert Right Insertar a la derecha +Insert Table Insertar tabla +Insert Table… Insertar tabla… +Insert picture from file… Insertar imagen desde archivo… +Insert\nAbove Insertar arriba +Insert\nBelow Insertar abajo +Insert\nLayout Insertar diseño +Insert\nLeft Insertar a la izquierda +Insert\nPlaceholder Insertar marcador de posición +Insert\nRight Insertar a la derecha +Inspect Presentation Inspeccionar presentación +Inspect Shape Inspeccionar forma +Inspect Slide Inspeccionar diapositiva +Interface Language Idioma de la interfaz +Interface language: Idioma de la interfaz: +Interface size Tamaño de la interfaz +Isosceles Triangle Triángulo isósceles +Italiano Italiano +Italic Cursiva +JPEG image (current slide) Imagen JPEG (diapositiva actual) +Join our community on Discord Únase a nuestra comunidad en Discord +Join the ArtCraft community on Discord Únase a la comunidad de ArtCraft en Discord +Justify Justificar +L-Shape Forma de L +Language Idioma +Last Último +Last Column Última columna +Last Slide Última diapositiva +Last commit Última confirmación +Layout Diseño +Learn More Más información +Learn\nMore Más información +Ledger Paper (11x17 in) Papel Ledger (11×17 pulgadas) +Left Izquierda +Left Brace Llave izquierda +Left Bracket Corchete izquierdo +Letter Paper (8.5x11 in) Papel Carta (8,5×11 pulgadas) +Liberation Serif Liberation Serif +Light Blue Azul claro +Light Green Verde claro +Light/Dark appearance Apariencia clara/oscura +Lighten Aclarar +Lightning Relámpago +Lightning Bolt Rayo +Line Línea +Line Color Color de línea +Line Spacing Interlineado +Line Spacing Options… Opciones de interlineado… +Line delta Diferencia de líneas +Line spacing (lines): Interlineado (líneas): +Line with Markers Línea con marcadores +Linear Lineal +Lines Líneas +Lines +/− Líneas +/− +Lines added Líneas añadidas +Lines deleted Líneas eliminadas +Link Vínculo +Link… Vínculo… +List Commands Lista de comandos +Lock Bloquear +Long Dash Guion largo +Long Dash Dot Guion largo y punto +Loop continuously until 'Esc' Repetir continuamente hasta presionar «Esc» +Loop until Stopped Repetir hasta que se detenga +Loops Bucles +Loose Suelto +Low Baja +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 el equipo de ArtCraft y los colaboradores de DeckCraft +Margins (pt) Márgenes (pt) +Mark as decorative Marcar como decorativo +Mark selected text as: Marcar el texto seleccionado como: +Math Matemáticas +Matrix Matriz +Maximize content (else ensure fit) Maximizar el contenido (si no, ajustar) +Media Multimedia +Media Info Información multimedia +Medium Media +Merge Cells Combinar celdas +Merge Shapes Combinar formas +Merge\nCells Combinar celdas +Merge\nShapes Combinar formas +Merged PRs Solicitudes de cambios combinadas +Middle Medio +Minus Sign Signo menos +Model Modelo +Models Modelos +Moon Luna +More Colors… # Más colores… # +Morph Transformación +Motion Movimiento +Motion Paths Trayectorias +Move Mover +Move Down Bajar +Move Insertion Point Mover el punto de inserción +Move Section Mover sección +Move Section Down Bajar sección +Move Section Up Subir sección +Move Slide Mover diapositiva +Move Up Subir +Multiplication Sign Signo de multiplicación +Multiply Multiplicación +Mute Silenciar +Name Nombre +Name (A–Z) Nombre (A–Z) +Name: Nombre: +New Comment Nuevo comentario +New Presentation Nueva presentación +New Slide Nueva diapositiva +New Slide (⇧⌘N) Nueva diapositiva (⇧⌘N) +New presentation Nueva presentación +New show name: Nombre de la nueva presentación: +New\nComment Nuevo comentario +New\nSlide Nueva diapositiva +Next Siguiente +Next Slide Diapositiva siguiente +Next Window Ventana siguiente +Next ▶ Siguiente ▶ +No Color Sin color +No Fill Sin relleno +No Glow Sin resplandor +No Outline Sin contorno +No Reflection Sin reflejo +No Shadow Sin sombra +No Soft Edges Sin bordes suaves +No accessibility issues found. People with disabilities should not have difficulty reading this document. No se encontraron problemas de accesibilidad. Las personas con discapacidad no deberían tener dificultad para leer este documento. +No comments on this slide. No hay comentarios en esta diapositiva. +No contributor data was built into this copy. Esta copia no incluye datos de colaboradores. +No fill Sin relleno +No line Sin línea +No model credits were built into this copy. Esta copia no incluye datos de los modelos utilizados. +No notes. No hay notas. +No sound: {err} Sin sonido: {err} +None Ninguno +Normal Normal +Not Equal Distinto +Not allowed No permitido +Notes Notas +Notes Master Patrón de notas +Notes Master (coming soon) Patrón de notas (próximamente) +Notes Page Página de notas +Notes Pages Páginas de notas +Notes\nMaster Patrón de notas +Notes\nPage Página de notas +Nudge Desplazar +Number of columns: Número de columnas: +Number of rows: Número de filas: +Numbering Numeración +Object Color Color del objeto +Objects Objetos +Octagon Octágono +On Click Al hacer clic +On Click of {name} Al hacer clic en {name} +On Click of… (none) Al hacer clic en… (nada) +On Mouse Click Con un clic del ratón +On-screen Show (16:10) Presentación en pantalla (16:10) +Open Data Abrir datos +Open Dialog Abrir diálogo +Open Recovered Presentations Abrir presentaciones recuperadas +Open the sample deck Abrir la presentación de ejemplo +Open… Abrir… +Orange Naranja +Orbit Órbita +Order Objects Orden de los objetos +Origami Origami +Out Hacia fuera +Out Bounce Hacia fuera con rebote +Outer Exterior +Outline Esquema +Outline (.txt) Esquema (.txt) +Outline View Vista Esquema +Outline\nView Vista Esquema +Oval Óvalo +Oval ends Extremos ovales +Overhead Proyector +PDF document (.pdf) Documento PDF (.pdf) +PNG images (all slides) Imágenes PNG (todas las diapositivas) +PNG images (current slide) Imágenes PNG (diapositiva actual) +PRs Solicitudes de cambios +Page Curl Pliegue de página +Page Setup… Configurar página… +PageDown PageDown +PageUp PageUp +Pan Paneo +Pane Panel +Paragraph Párrafo +Paragraph… Párrafo… +Parallelogram Paralelogramo +Pareto Pareto +Partial Circle Círculo parcial +Particles Partículas +Paste Pegar +Paste (⌘V) Pegar (⌘V) +Paste Formatting Pegar formato +Paste and Match Formatting Pegar con el mismo formato +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Pegue o escriba un esquema. Las líneas sin sangría se convierten en títulos de diapositivas; las líneas con sangría de tabulación, en viñetas. +Pasted image.png Imagen pegada.png +Path Trayectoria +Pattern fill Relleno con trama +Pause Pausa +Peek In Asomarse +Peel Off Despegar +Pencil Lápiz +Pentagon Pentágono +Perspective Perspectiva +Pick a graphic; type one item per line. Elija un gráfico; escriba un elemento por línea. +Pick a look for your slides. Ideas are generated on your device. Elija un aspecto para sus diapositivas. Las ideas se generan en su dispositivo. +Picture Imagen +Picture Format Formato de imagen +Picture Styles Estilos de imagen +Picture from File… Imagen desde archivo… +Picture or texture fill Relleno con imagen o textura +Picture\nStyles Estilos de imagen +Pictures Imágenes +Pie Circular +Pin Anclar +Placeholder colour Color del marcador de posición +Plan\nBuild\nLaunch Planificar\nConstruir\nLanzar +Plaque Placa +Play Reproducir +Play Across Slides Reproducir en varias diapositivas +Play Full Screen Reproducir a pantalla completa +Play Narrations Reproducir narraciones +Play from Current Slide Reproducir desde la diapositiva actual +Play from Start Reproducir desde el principio +Play from Start (F5) Reproducir desde el principio (F5) +Play from\nCurrent Slide Reproducir desde la diapositiva actual +Play from\nStart Reproducir desde el principio +Play/Pause Reproducir/Pausar +Playback Reproducción +Plus Más +Plus In Más hacia dentro +Plus Out Más hacia fuera +Plus Sign Signo más +Portrait (9:16) Vertical (9:16) +Português Português +Position Posición +Position Objects Posición de los objetos +Position and Size Posición y tamaño +Post Publicar +Poster Frame Fotograma de póster +PowerPoint Presentation (.pptx) Presentación de PowerPoint (.pptx) +Preferences Opciones +Preferences… Opciones… +Presentation Presentación +Presentations Presentaciones +Presentations and slide shows, rebuilt from scratch in pure Rust. Presentaciones y proyecciones de diapositivas, reconstruidas desde cero en Rust puro. +Presented by a speaker (full screen) Presentada por un orador (pantalla completa) +Presenter View Vista Moderador +Presenter View — DeckCraft Vista Moderador — DeckCraft +Presenter\nView Vista Moderador +Preset gradients Degradados predefinidos +Prestige Prestigio +Preview Vista previa +Previous Slide Diapositiva anterior +Print layout: Diseño de impresión: +Properties Propiedades +Pulse Pulsación +Punctuation Puntuación +Purple Morado +Push Empujar +Pyramid Pirámide +Quick Styles Estilos rápidos +Quick\nStyles Estilos rápidos +Radar Radar +Radial Radial +Random Aleatorio +Random Bars Barras aleatorias +Reading View Vista de lectura +Reading\nView Vista de lectura +Real name Nombre real +Recent Reciente +Record Grabar +Recording narration needs audio capture (coming soon) La grabación de narraciones requiere captura de audio (próximamente) +Recovered Presentations Presentaciones recuperadas +Recovered {} from the last session Recuperado {} de la última sesión +Rectangle Rectángulo +Rectangle: Diagonal Corners Rounded Rectángulo: esquinas diagonales redondeadas +Rectangle: Diagonal Corners Snipped Rectángulo: esquinas diagonales recortadas +Rectangle: Rounded Corners Rectángulo: esquinas redondeadas +Rectangle: Single Corner Rounded Rectángulo: una esquina redondeada +Rectangle: Single Corner Snipped Rectángulo: una esquina recortada +Rectangle: Top Corners One Rounded and One Snipped Rectángulo: esquinas superiores, una redondeada y otra recortada +Rectangle: Top Corners Rounded Rectángulo: esquinas superiores redondeadas +Rectangle: Top Corners Snipped Rectángulo: esquinas superiores recortadas +Rectangles Rectángulos +Rectangular Rectangular +Red Rojo +Red Pen Bolígrafo rojo +Redo Rehacer +Redo (⌘Y) Rehacer (⌘Y) +Reflected Rounded Rectangle Rectángulo redondeado con reflejo +Reflection Reflejo +Regroup Reagrupar +Regular Pentagon Pentágono regular +Rehearse Timings Ensayar intervalos +Rehearse\nTimings Ensayar intervalos +Remove Quitar +Remove All Animations Quitar todas las animaciones +Remove All Sections Quitar todas las secciones +Remove Animation Quitar animación +Remove Background Quitar el fondo +Remove Background (coming soon) Quitar el fondo (próximamente) +Remove Section Quitar sección +Remove Section & Slides Quitar sección y diapositivas +Remove stop Quitar punto +Remove\nBackground Quitar el fondo +Rename Cambiar nombre +Rename Layout Cambiar nombre del diseño +Rename Section Cambiar nombre de la sección +Rename Section… Cambiar nombre de la sección… +Rename Slide Cambiar nombre de la diapositiva +Rename… Cambiar nombre… +Render Slide Representar diapositiva +Reopen Volver a abrir +Reorder Animation Reordenar animación +Reorder Objects Reordenar objetos +Replace straight quotes with smart quotes Reemplazar comillas rectas por tipográficas +Reply Responder +Reply… Responder… +Reset Restablecer +Reset Background Restablecer fondo +Reset Crop Restablecer recorte +Reset Effects Restablecer efectos +Reset Picture Restablecer imagen +Reset Slide Restablecer diapositiva +Reset Slide Background Restablecer fondo de diapositiva +Resize shape to fit text Cambiar el tamaño de la forma para ajustar el texto +Resolve Marcar como resuelto +Resolve Thread Resolver conversación +Return Volver +Reveal Revelar +Reverse the order Invertir el orden +Revert Revertir +Review Revisar +Rewind after Playing Rebobinar después de reproducir +Ribbon Tab Pestaña de la cinta de opciones +Ribbon: Tilted Down Cinta: inclinada hacia abajo +Ribbon: Tilted Up Cinta: inclinada hacia arriba +Right Derecha +Right Brace Llave derecha +Right Bracket Corchete derecho +Right Triangle Triángulo rectángulo +Right-to-Left Text Direction Dirección del texto de derecha a izquierda +Ring Anillo +Ripple Ondulación +Rise Up Elevarse +Rotate Girar +Rotate Left 90° Girar a la izquierda 90° +Rotate Right 90° Girar a la derecha 90° +Rotate all text 270° Girar todo el texto 270° +Rotate all text 90° Girar todo el texto 90° +Rotate with shape Girar con la forma +Rotation Rotación +Round Dot Punto redondo +Rounded Diagonal Corner Esquina diagonal redondeada +Ruler Regla +Saturation Saturación +Saturation {}% Saturación {}% +Save Guardar +Save (⌘S) Guardar (⌘S) +Save As… Guardar como… +Save AutoRecover Information Guardar información de autorrecuperación +Save as Template… Guardar como plantilla… +Save to Data Guardar en datos +Saved Guardado +Saved {path} Guardado: {path} +Scatter Dispersión +ScreenTip: Información en pantalla: +Screenshot Captura de pantalla +Screenshot (not available yet) Captura de pantalla (aún no disponible) +Scroll: Horizontal Pergamino: horizontal +Scroll: Vertical Pergamino: vertical +Search commands (⇧⌘P) Buscar comandos (⇧⌘P) +Search commands… Buscar comandos… +Section Sección +Seek Buscar posición +Select Seleccionar +Select All Seleccionar todo +Select All Text Seleccionar todo el texto +Select Cells Seleccionar celdas +Select Objects Seleccionar objetos +Select Paragraph Seleccionar párrafo +Select Slides Seleccionar diapositivas +Select Text Seleccionar texto +Select Word Seleccionar palabra +Select a chart first. Seleccione primero un gráfico. +Select a shape to format it. Seleccione una forma para darle formato. +Select an object on the slide and add an animation from the Animations tab. Seleccione un objeto en la diapositiva y agregue una animación desde la pestaña Animaciones. +Selection Selección +Selection Pane Panel de selección +Selection Pane… Panel de selección… +Selection\nPane Panel de selección +Send Backward Enviar atrás +Send to Back Enviar al fondo +Send\nBackward Enviar atrás +Sentence case. Tipo frase. +Set Text Establecer texto +Set Up Show… Configurar presentación… +Set Up Slide Show Configurar la presentación +Set Up Slide Show… Configurar la presentación… +Set Up\nSlide Show Configurar la presentación +Set as Default Shape Establecer como forma predeterminada +Shading Sombreado +Shadow Sombra +Shape Forma +Shape Effects Efectos de forma +Shape Fill Relleno de forma +Shape Format Formato de forma +Shape Gallery Galería de formas +Shape Outline Contorno de forma +Shape Styles Estilos de forma +Shape {} Forma {} +Shape\nStyles Estilos de forma +Shapes Formas +Shift+ Shift+ +Shift+F9 Shift+F9 +Show Mostrar +Show All Mostrar todo +Show Comments Mostrar comentarios +Show Media Controls Mostrar controles multimedia +Show Slide Mostrar diapositiva +Show smart guides Mostrar guías inteligentes +Show type Tipo de presentación +Show without animation Mostrar sin animación +Show without narration Mostrar sin narración +Show/Hide Mostrar/Ocultar +Show\nComments Mostrar comentarios +Shred Triturar +Shrink & Turn Reducir y girar +Shrink text on overflow Reducir el texto si desborda +Simple Frame, White Marco sencillo, blanco +Size Tamaño +Size & Properties Tamaño y propiedades +Slide Master Patrón de diapositivas +Slide Number Número de diapositiva +Slide Show Presentación +Slide Size Tamaño de diapositiva +Slide Sorter Clasificador de diapositivas +Slide number Número de diapositiva +Slide timings recorded. Intervalos de las diapositivas grabados. +Slide {:02}:{:04.1} Total {:02}:{:02} Diapositiva {:02}:{:04.1} Total {:02}:{:02} +Slide {} of {} Diapositiva {} de {} +Slide {}: {}{} Diapositiva {}: {}{} +Slide {}: “{w}” Diapositiva {}: «{w}» +Slide\nMaster Patrón de diapositivas +Slide\nNumber Número de diapositiva +Slide\nSize Tamaño de diapositiva +Slide\nSorter Clasificador de diapositivas +Slides (e.g. 1,3,5): Diapositivas (p. ej., 1,3,5): +Slides from Outline Diapositivas a partir del esquema +Slides from Outline… Diapositivas a partir del esquema… +Slides sized for: Tamaño de las diapositivas: +SmartArt SmartArt +Smile Sonrisa +Smiley Face Cara sonriente +Smoothly Suavemente +Smoothly Left Suavemente a la izquierda +Smoothly Right Suavemente a la derecha +Snap objects to grid Ajustar objetos a la cuadrícula +Soft Edge Rectangle Rectángulo con bordes suaves +Soft Edges Bordes suaves +Solid Sólido +Solid fill Relleno sólido +Solid line Línea sólida +Sort Ordenar +Source on GitHub Código fuente en GitHub +Space Espacio +Spacing after (pt): Espaciado posterior (pt): +Spacing before (pt): Espaciado anterior (pt): +Special — hanging (in): Especial — sangría francesa (pulgadas): +Speech Voz +Speech Bubble: Oval Globo: óvalo +Speech Bubble: Rectangle Globo: rectángulo +Speech Bubble: Rectangle with Corners Rounded Globo: rectángulo con esquinas redondeadas +Spelling Ortografía +Spin Giro +Spinner Giro circular +Split Dividir +Split Cells Dividir celdas +Split\nCells Dividir celdas +Square Cuadrado +Square (1:1) Cuadrado (1:1) +Square Dot Punto cuadrado +Stacked Apilado +Stacked Area Área apilada +Stacked Bar Barra apilada +Stacked Column Columna apilada +Stacked Line Línea apilada +Standard (4:3) Estándar (4:3) +Standard Colors Colores estándar +Star Estrella +Star: 10 Points Estrella: 10 puntas +Star: 12 Points Estrella: 12 puntas +Star: 16 Points Estrella: 16 puntas +Star: 24 Points Estrella: 24 puntas +Star: 32 Points Estrella: 32 puntas +Star: 4 Points Estrella: 4 puntas +Star: 5 Points Estrella: 5 puntas +Star: 6 Points Estrella: 6 puntas +Star: 7 Points Estrella: 7 puntas +Star: 8 Points Estrella: 8 puntas +Stars and Banners Estrellas y cintas +Start After Previous Después de la anterior +Start Automatically Automáticamente +Start On Click Al hacer clic +Start With Previous Con la anterior +Start a conversation Inicie una conversación +Start time (s): Hora de inicio (s): +Start: Inicio: +Stealth end Punta de flecha +Stock Bolsa +Stop Detener +Stop Editing Text Dejar de editar el texto +Strikethrough Tachado +Strips Franjas +Style {i} Estilo {i} +Subscript Subíndice +Subtle Sutiles +Sun Sol +Sunburst Ráfaga de sol +Superscript Superíndice +Surface Superficie +Switch Cambio +Swivel Giratorio +Symbol Símbolo +System language Idioma del sistema +Tab Tabulación +Table Tabla +Table Design Diseño de tabla +Table Style Options Opciones de estilo de tabla +Table Styles Estilos de tabla +Table… Tabla… +Task Pane Panel de tareas +Teardrop Lágrima +Teeter Titilar +Text Texto +Text Box Cuadro de texto +Text Box Margins Márgenes del cuadro de texto +Text Direction Dirección del texto +Text Effects Efectos de texto +Text Fill Relleno de texto +Text Highlight Color Color de resaltado de texto +Text Options Opciones de texto +Text Outline Contorno de texto +Text Shadow Sombra de texto +Text/Background - Dark 1 Texto/Fondo - Oscuro 1 +Text/Background - Dark 2 Texto/Fondo - Oscuro 2 +Text/Background - Light 1 Texto/Fondo - Claro 1 +Text/Background - Light 2 Texto/Fondo - Claro 2 +Text\nBox Cuadro de texto +The spelling check is complete. No issues found. La revisión ortográfica se completó. No se encontraron problemas. +Theme Colors Colores del tema +Theme Gallery Galería de temas +Themes Temas +Thesaurus Diccionario de sinónimos +Thesaurus (coming soon) Diccionario de sinónimos (próximamente) +This Document Este documento +Thought Pensamiento +Thought Bubble: Cloud Pensamiento: nube +Through Black A través de negro +Tight Apretado +Timing Intervalos +Top Arriba +Total Row Fila de totales +Transition Transición +Transition Gallery Galería de transiciones +Transitions Transiciones +Translate Traducir +Translation needs a language model (not bundled) La traducción requiere un modelo de lenguaje (no incluido) +Transparency Transparencia +Trapezoid Trapecio +Treemap Mapa de árbol +Triangle Triángulo +Trigger Desencadenador +Trim Recortar +Trim Media Recortar multimedia +Turns Giros +Type Tipo +Type Text Escribir texto +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Escriba una ecuación en forma lineal (p. ej., a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Descubrir +Underline Subrayado +Undo Deshacer +Undo (⌘Z) Deshacer (⌘Z) +Ungroup Desagrupar +Up Arriba +Use Timings Usar intervalos +Use timings, if present Usar intervalos, si existen +Username Nombre de usuario +Version Versión +Version {} Versión {} +Vert In Vertical hacia dentro +Vert Out Vertical hacia fuera +Vertical Vertical +Vertical alignment Alineación vertical +Very Loose Muy suelto +Very Tight Muy apretado +Video Vídeo +Video from File… Vídeo desde archivo… +View Vista +Volume Volumen +Vortex Vórtice +Waterfall Cascada +Wave Ola +Web Page or File Página web o archivo +Wedge Cuña +Weight Grosor +Wheel Rueda +Widescreen (13.333x7.5 in) Panorámico (13,333×7,5 pulgadas) +Widescreen (16:9) Panorámico (16:9) +Width Ancho +Width (in): Ancho (pulgadas): +Width: Ancho: +Width: Ancho: +Wind Viento +Window Ventana +Wipe Barrido +With Previous Con la anterior +WordArt WordArt +WordArt style {} Estilo de WordArt {} +Words Palabras +Wrap Text in Shape Ajustar texto en la forma +Wrap text in shape Ajustar texto en la forma +Yellow Amarillo +Your changes will be lost if you don't save them. Los cambios se perderán si no los guarda. +Your name (comments): Su nombre (comentarios): +Zoom Zoom +Zoom In Acercar +Zoom Out Alejar +Zoom… Zoom… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Aceptar revisión +Action Settings Configuración de acciones +Add Font Agregar fuente +Add Guide Agregar guía +Add Point Agregar punto +Add Shape Agregar forma +Add to Dictionary Agregar al diccionario +Align Cell Text Alinear texto de celda +Apply Design Idea Aplicar idea de diseño +Arrow: Circular Flecha: circular +Arrow: Circular Counter-clockwise Flecha: circular en sentido antihorario +Arrow: Circular Two-headed Flecha: circular de dos puntas +Arrow: Curved Down Flecha: curvada hacia abajo +Arrow: Curved Left Flecha: curvada hacia la izquierda +Arrow: Curved Right Flecha: curvada hacia la derecha +Arrow: Curved Up Flecha: curvada hacia arriba +Arrow: Swoosh Flecha: swoosh +Artistic Effects Efectos artísticos +AutoCorrect Options Opciones de autocorrección +Bean Frijol +Borders Bordes +Bounce Left Rebote a la izquierda +Bounce Right Rebote a la derecha +Browse for Themes… Buscar temas… +Callout: Bent Line Globo: línea doblada +Callout: Bent Line with Accent Bar Globo: línea doblada con barra de énfasis +Callout: Bent Line with Border and Accent Bar Globo: línea doblada con borde y barra de énfasis +Callout: Bent Line with No Border Globo: línea doblada sin borde +Callout: Double Bent Line Globo: línea doblemente doblada +Callout: Double Bent Line with Accent Bar Globo: línea doblemente doblada con barra de énfasis +Callout: Double Bent Line with Border and Accent Bar Globo: línea doblemente doblada con borde y barra de énfasis +Callout: Double Bent Line with No Border Globo: línea doblemente doblada sin borde +Callout: Left-Right Arrow Globo: flecha izquierda-derecha +Callout: Line with Accent Bar Globo: línea con barra de énfasis +Callout: Line with Border and Accent Bar Globo: línea con borde y barra de énfasis +Callout: Line with No Border Globo: línea sin borde +Callout: Quad Arrow Globo: flecha de cuatro puntas +Callout: Up-Down Arrow Globo: flecha arriba-abajo +Cell Margins Márgenes de celda +Change Colors Cambiar colores +Change Layout Cambiar diseño +Change Picture… Cambiar imagen… +Change Spelling Cambiar ortografía +Chart Marker: Cross Lines Marcador de gráfico: líneas en X +Chart Marker: Plus Lines Marcador de gráfico: líneas en cruz +Chart Marker: Star Lines Marcador de gráfico: líneas de estrella +Color At Color en +Commit Composition Confirmar composición +Compare Comparar +Compare… Comparar… +Compose Text Componer texto +Compress Pictures Comprimir imágenes +Contract Contraer +Convert to Shapes Convertir en formas +Convert to SmartArt Convertir a SmartArt +Convert to Text Convertir a texto +Corner Tabs: Quarter Circles Pestañas de esquina: cuartos de círculo +Corner Tabs: Squares Pestañas de esquina: cuadrados +Corner Tabs: Triangles Pestañas de esquina: triángulos +Crescent Moon Luna creciente +Curved Square Cuadrado curvado +Decaying Wave Onda amortiguada +Delete Guide Eliminar guía +Delete Point Eliminar punto +Demote Degradar +Diagonal Down Right Diagonal hacia abajo a la derecha +Diagonal Up Right Diagonal hacia arriba a la derecha +Draw Table Dibujar tabla +dropped file archivo arrastrado +Edit Photo Album… Editar álbum de fotos… +Edit Points Editar puntos +Edit SmartArt Text Editar texto de SmartArt +End Review Finalizar revisión +Find Buscar +Flowchart: Offline Storage Diagrama de flujo: almacenamiento sin conexión +Fonts in Presentation Fuentes de la presentación +Font… Fuente… +Football Balón +Gear: 6 Teeth Engranaje: 6 dientes +Gear: 9 Teeth Engranaje: 9 dientes +Grid and Guides Cuadrícula y guías +Grid Options… Opciones de cuadrícula… +Handout Placeholders Marcadores de posición de documentos +Heartbeat Latido +Hex D Hexágono abajo +Hex L Hexágono izquierda +Hex R Hexágono derecha +Hex U Hexágono arriba +Horizontal Figure 8 Ocho horizontal +i. ii. iii. i. ii. iii. +Icon Gallery Galería de iconos +Info Información +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Tinta a forma: convierte las líneas, rectángulos, óvalos y triángulos dibujados en formas +Insert Picture in SmartArt Insertar imagen en SmartArt +Insert Picture in SmartArt… Insertar imagen en SmartArt… +Insert Synonym Insertar sinónimo +Layout Placeholders Marcadores de posición del diseño +Line: Rising Línea: ascendente +Loop de Loop Rizo +Move Guide Mover guía +Move Handle Mover controlador +Move Point Mover punto +Neutron Neutrón +New Window Nueva ventana +Next Comment Comentario siguiente +No comments. No hay comentarios. +no presentation open No hay ninguna presentación abierta +no slides No hay diapositivas +no text insertion point No hay punto de inserción de texto +Notes Placeholders Marcadores de posición de notas +nothing selected No hay nada seleccionado +nothing to redo Nada que rehacer +nothing to undo Nada que deshacer +Open Abrir +Particles In Partículas de entrada +Particles Out Partículas de salida +Paste Special Pegado especial +Paste Special… Pegado especial… +Peanut Maní +Peek Out Asomarse hacia fuera +Photo Album… Álbum de fotos… +Pick a design for this slide. Ideas are generated on your device. Elija un diseño para esta diapositiva. Las ideas se generan en su dispositivo. +Picture Style Gallery Galería de estilos de imagen +Point Type Tipo de punto +Points Puntos +Preserve Conservar +Preview Animations Vista previa de animaciones +Previous Comment Comentario anterior +Print Imprimir +Print… Imprimir… +Promote Promover +Quarter Wedge Cuña de un cuarto +Quick Access Toolbar Barra de herramientas de acceso rápido +Recolor Recolorear +Recolor Gallery Galería de nuevos colores +Remove Shape Quitar forma +Replace Reemplazar +Replace Fonts Reemplazar fuentes +Replace… Reemplazar… +Rescan Installed Fonts Reexaminar fuentes instaladas +Reuse Slides… Reutilizar diapositivas… +Revisions Revisiones +Ribbon: Curved and Tilted Down Cinta: curvada e inclinada hacia abajo +Ribbon: Curved and Tilted Up Cinta: curvada e inclinada hacia arriba +Ribbon: Left-Right Fold Cinta: doblez izquierda-derecha +S Curve 1 Curva S 1 +S Curve 2 Curva S 2 +select text or a shape Seleccione texto o una forma +select two or more objects Seleccione dos o más objetos +Set Transparent Color Establecer color transparente +Set Zoom Establecer zoom +Sine Wave Onda sinusoidal +Single L Simple izquierda +Single R Simple derecha +Sink Down Hundirse +size (pt) tamaño (pt) +Size and Position… Tamaño y posición… +SmartArt Styles Estilos de SmartArt +Smooth Corners Suavizar esquinas +Sound Sonido +Spelling Dictionary Diccionario ortográfico +Spiral Left Espiral a la izquierda +Spiral Right Espiral a la derecha +Spring Muelle +Stairs Down Escaleras abajo +Starter Templates Plantillas iniciales +Strips In Franjas de entrada +Strips Out Franjas de salida +Swoosh Swoosh +Table Eraser Borrador de tabla +Tabs… Tabulaciones… +Text Pane Panel de texto +Text Transform Transformación de texto +Text Transparency Transparencia del texto +tOGGLE cASE cAMBIAR cASO +Trapezoid: Uneven Sides Trapecio: lados desiguales +unknown interface language Idioma de interfaz desconocido +Unlock Desbloquear +Variant Gallery Galería de variantes +Variants Variantes +Vertical Figure 8 Ocho vertical +Zigzag Zigzag + (not checked) (sin comprobar) +4 Point Star Estrella de 4 puntas +5 Point Star Estrella de 5 puntas +6 Point Star Estrella de 6 puntas +8 Point Star Estrella de 8 puntas +{ch} Bullet {ch} Viñeta +{f} (Body) {f} (Cuerpo) +{f} (Headings) {f} (Títulos) +{name}: DeckCraft can't open this kind of file {name}: DeckCraft no puede abrir este tipo de archivo +{n} Column{} {n} Columna{} +{r} pt {r} pt +{r} pt glow Resplandor de {r} pt +{w} pt {w} pt +{} ({} slides) {} ({} diapositivas) +{} Slide Master Patrón de diapositivas {} +{} contributors · {} commits Colaboradores: {} · Confirmaciones: {} +{} presentations {} presentaciones +{}x{} Table Tabla {}×{} +“{}” is not available yet. «{}» aún no está disponible. +−Bin −Intervalo +▶ Play All ▶ Reproducir todo +◀ Previous ◀ Anterior +✏ on ✏ activado diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv new file mode 100644 index 000000000..e4937b2d5 --- /dev/null +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -0,0 +1,1408 @@ +# French interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Date fixe (vide = mise à jour automatique) : + Footer text: Texte du pied de page : + Present Présenter + pt pt + — Edited — Modifié +"Not Allowed" Symbol Symbole « Non autorisé » +% of all commits % de tous les commits ++ New Comment + Nouveau commentaire ++ New Slide + Nouvelle diapositive ++ Row + Ligne ++ Series + Série ++Bin +Intervalle +100% Stacked Bar Barres 100% empilées +100% Stacked Column Histogramme 100% empilé +35mm Slides Diapositives 35 mm +@ribbon:Home Accueil +@ribbon:Insert Insertion +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{} : {} PRs, {} commits, +{} / −{} lignes (Δ {}), +{} / −{} ressources binaires, {} – {} +A3 Paper (297x420 mm) Papier A3 (297x420 mm) +A4 Paper (210x297 mm) Papier A4 (210x297 mm) +Aa Aa +Abc Abc +About À propos +About DeckCraft À propos de DeckCraft +Accent 1 Accent 1 +Accent 2 Accent 2 +Accent 3 Accent 3 +Accent 4 Accent 4 +Accent 5 Accent 5 +Accent 6 Accent 6 +Accessibility Checker Vérificateur d'accessibilité +Across En travers +Action Action +Action Button: Custom Bouton d'action : Personnalisé +Action Button: Document Bouton d'action : Document +Action Button: Get Information Bouton d'action : Informations +Action Button: Go Back Bouton d'action : Retour +Action Button: Go Back or Previous Bouton d'action : Précédent +Action Button: Go Forward or Next Bouton d'action : Suivant +Action Button: Go Home Bouton d'action : Accueil +Action Button: Go to Beginning Bouton d'action : Début +Action Button: Go to End Bouton d'action : Fin +Action Button: Help Bouton d'action : Aide +Action Button: Sound Bouton d'action : Son +Action Button: Video Bouton d'action : Vidéo +Action Button: {k} Bouton d'action : {k} +Action Buttons Boutons d'action +Add Animation Ajouter une animation +Add Section Ajouter une section +Add\nAnimation Ajouter\nune animation +Address: Adresse : +Adjust Shape Ajuster la forme +After Previous Après la précédente +After: Après : +Airplane Avion +Align Aligner +Align Bottom Aligner en bas +Align Center Aligner au centre +Align Left Aligner à gauche +Align Middle Aligner au milieu +Align Right Aligner à droite +Align Text Aligner le texte +Align Top Aligner en haut +Alt Text Texte de remplacement +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Texte de\nremplacement +An open-source, clean-room project. Not affiliated with Microsoft. Projet open source indépendant, conçu de toutes pièces. Sans affiliation avec Microsoft. +Angle Angle +Animation Gallery Galerie d'animations +Animation Pane Volet Animation +Animation Styles Styles d'animation +Animation\nPane Volet\nAnimation +Animations Animations +Animation Painter Reproduire l'animation +Apply Animation Appliquer une animation +Play/Pause GIF Lire/mettre en pause le GIF +Animations on Slide Animations de la diapositive +Appear Apparition +Apply Appliquer +Apply To All Appliquer à tous +Apply to All Appliquer à tous +Apply\nTo All Appliquer\nà tous +Arc Arc +Arcs Arcs +Area Aires +Arrange Organiser +Arrow Flèche +Arrow at end Flèche à la fin +Arrow at start Flèche au début +Arrow: Bent Flèche : Coudée +Arrow: Bent-Up Flèche : Coudée vers le haut +Arrow: Chevron Flèche : Chevron +Arrow: Down Flèche : Vers le bas +Arrow: Left Flèche : Vers la gauche +Arrow: Left-Right Flèche : Gauche-droite +Arrow: Left-Right-Up Flèche : Gauche-droite-haut +Arrow: Left-Up Flèche : Gauche-haut +Arrow: Notched Right Flèche : Droite encochée +Arrow: Pentagon Flèche : Pentagonale +Arrow: Quad Flèche : Quadruple +Arrow: Right Flèche : Vers la droite +Arrow: Striped Right Flèche : Droite striée +Arrow: U-Turn Flèche : Demi-tour +Arrow: Up Flèche : Vers le haut +Arrow: Up-Down Flèche : Haut-bas +Arrows Flèches +Arrows at both ends Flèches aux deux extrémités +As One Object Comme un objet unique +Audio Audio +Audio from File… Audio à partir d'un fichier… +AutoCorrect as you type Correction automatique pendant la saisie +Autofit Ajustement automatique +Automatic Automatique +B4 (ISO) Paper (250x353 mm) Papier B4 (ISO) (250x353 mm) +B5 (ISO) Paper (176x250 mm) Papier B5 (ISO) (176x250 mm) +Background Arrière-plan +Background Styles Styles d'arrière-plan +Background\nStyles Styles\nd'arrière-plan +Backspace Retour arrière +Banded Columns Colonnes à bandes +Banded Rows Lignes à bandes +Banner Bannière +Basic Cycle Cycle de base +Basic List Liste de base +Basic Process Processus de base +Basic Shapes Formes de base +Before text (in): Avant le texte (po) : +Bevel Biseau +Binary assets added Ressources binaires ajoutées +Binary assets removed Ressources binaires supprimées +Black Left Noir vers la gauche +Black Pen Stylo noir +Black Right Noir vers la droite +Blinds Stores +Block Arc Arc bloqué +Block Arrows Flèches pleines +Blue Bleu +Blue Pen Stylo bleu +Bold Gras +Bold Flash Flash gras +Both Les deux +Bottom Bas +Bounce Rebond +Box Boîte +Box In Boîte vers l'intérieur +Box Out Boîte vers l'extérieur +Box and Whisker Boîte à moustaches +Brightness Luminosité +Brightness {:+}% Luminosité {:+}% +Bring Forward Avancer +Bring to Front Premier plan +Bring\nForward Avancer +Browsed at a kiosk (full screen) Présenté à un kiosque (plein écran) +Browsed by an individual (window) Présenté par une personne (fenêtre) +Bubble Bulles +Bullets Puces +Burst Éclatement +By Paragraph Par paragraphe +Callout: Down Arrow Légende : Flèche vers le bas +Callout: Left Arrow Légende : Flèche vers la gauche +Callout: Line Légende : Ligne +Callout: Right Arrow Légende : Flèche vers la droite +Callout: Up Arrow Légende : Flèche vers le haut +Callouts Légendes +Cameo Cameo +Camera capture is not available yet La capture de la caméra n'est pas encore disponible +Cancel Annuler +Capitalize Each Word Capitaliser chaque mot +Caps Majuscules +Center Centrer +Centered Centré +Change Case Changer la casse +Change Chart Type Changer le type de graphique +Change Picture Changer l'image +Change Shape Changer la forme +Change\nChart Type Changer le type\nde graphique +Character Spacing Espacement des caractères +Characters Caractères +Chart Graphique +Chart Data Données du graphique +Chart Design Création de graphique +Chart Elements Éléments du graphique +Chart… Graphique… +Check Accessibility Vérifier l'accessibilité +Check\nAccessibility Vérifier\nl'accessibilité +Checkerboard Damier +Chevron Chevron +Choose a SmartArt Graphic Choisir un graphique SmartArt +Chord Corde +Circle Cercle +Circle In Cercle vers l'intérieur +Circle Out Cercle vers l'extérieur +Clear All Formatting Effacer toute la mise en forme +Click a symbol to insert it at the insertion point. Cliquez sur un symbole pour l'insérer au point d'insertion. +Click icon to add SmartArt graphic Cliquez sur une icône pour ajouter un graphique SmartArt +Click icon to add chart Cliquez sur une icône pour ajouter un graphique +Click icon to add media Cliquez sur une icône pour ajouter un média +Click icon to add picture Cliquez sur une icône pour ajouter une image +Click icon to add table Cliquez sur une icône pour ajouter un tableau +Click to add first slide Cliquez pour ajouter la première diapositive +Click to add notes Cliquez pour ajouter des notes +Click to add subtitle Cliquez pour ajouter un sous-titre +Click to add text Cliquez pour ajouter du texte +Click to add title Cliquez pour ajouter un titre +Click to edit Master text styles Cliquez pour modifier les styles de texte du masque +Click to edit Master title style Cliquez pour modifier le style de titre du masque +Clock Horloge +Clockwise Sens horaire +Close Fermer +Close Master View Fermer le mode Masque +Close\nMaster View Fermer le\nmode Masque +Cloud Nuage +Clustered Bar Barres groupées +Clustered Column Histogramme groupé +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Réduire le ruban +Color Couleur +Color Pulse Pulsation de couleur +Colors Couleurs +Columns Colonnes +Comb Peigne +Combo Combiné +Command Palette Palette de commandes +Comment Commentaire +Comments Commentaires +Commits Commits +Community Links Liens communautaires +Company Société +Complementary Color Couleur complémentaire +Connect Shapes Connecter les formes +Connection Sites Points de connexion +Connector: Curved Connecteur : Courbe +Connector: Elbow Connecteur : Coude +Connector: Elbow (one bend) Connecteur : Coude (un seul coude) +Content Contenu +Contrast Contraste +Contrast {:+}% Contraste {:+}% +Contributors Contributeurs +Conveyor Convoyeur +Copy Copier +Corrections Corrections +Couldn't save AutoRecover information: {e} Impossible d'enregistrer les informations de Récupération automatique : {e} +Counter Clockwise Sens antihoraire +Cover Couvrir +Create Créer +Crop Rogner +Crop 10% each side Rogner de 10 % de chaque côté +Crop 20% each side Rogner de 20 % de chaque côté +Crop to Shape Rogner à la forme +Cross Croix +Crush Écrasement +Ctrl+ Ctrl+ +Cube Cube +Currency Devise +Curtains Rideaux +Custom Personnalisé +Custom Path Trajectoire personnalisée +Custom Show Projection personnalisée +Custom Show 1 Projection personnalisée 1 +Custom Shows Projections personnalisées +Custom Slide Show Projection personnalisée de diapositives +Custom\nShow Projection\npersonnalisée +Cut Couper +Cylinder Cylindre +Dark Blue Bleu foncé +Dark Mode Mode sombre +Dark Red Rouge foncé +Dark appearance Apparence sombre +Dark\nMode Mode\nsombre +Darken Assombrir +Dash Tiret +Dash Dot Tiret-point +Dashes Tirets +Database Base de données +Date Date +Date & Time Date et heure +Date &\nTime Date et\nheure +Date and Time Date et heure +Date and time Date et heure +Decagon Décagone +Decision Décision +DeckCraft DeckCraft +Decrease Font Size Réduire la taille de police +Decrease List Level Diminuer le niveau de liste +Delay: Délai : +Delete Supprimer +Delete Columns Supprimer les colonnes +Delete Comment Supprimer le commentaire +Delete Layout Supprimer la disposition +Delete Rows Supprimer les lignes +Delete Slide Supprimer la diapositive +Delete Table Supprimer le tableau +Delete Text Supprimer le texte +Desaturate Désaturer +Deselect Désélectionner +Design Création +Design Ideas Idées de conception +Design\nIdeas Idées de\nconception +Deutsch Deutsch +Diagonal Stripe Rayure diagonale +Diamond Losange +Diamond In Losange vers l'intérieur +Diamond Out Losange vers l'extérieur +Direction Direction +Disappear Disparaître +Discard Recovered Presentations Abandonner les présentations récupérées +Display name Nom d'affichage +Dissolve Dissolution +Dissolve In Fondu entrant +Dissolve Out Fondu sortant +Distribute Répartir +Distribute Columns Répartir les colonnes +Distribute Horizontally Répartir horizontalement +Distribute Rows Répartir les lignes +Distribute Vertically Répartir verticalement +Division Sign Signe de division +Do not Autofit Ne pas ajuster +Do you want to save the changes you made to {what}? Voulez-vous enregistrer les modifications apportées à {what} ? +Document Document +Dodecagon Dodécagone +Don't Save Ne pas enregistrer +Don't show on title slide Ne pas afficher sur la diapositive de titre +Done Terminé +Donut Anneau +Doors Portes +Double Brace Accolade double +Double Bracket Crochet double +Double Wave Double vague +Doughnut Anneau +Down Bas +Drape Rideau +Draw Dessin +Drop Shadow Rectangle Rectangle avec ombre portée +Duplicate Dupliquer +Duplicate Selected Slides Dupliquer les diapositives sélectionnées +Duplicate Slide Dupliquer la diapositive +Duration: Durée : +Dynamic Content Contenu dynamique +Edit Modifier +Edit Alt Text… Modifier le texte de remplacement… +Edit Data Modifier les données +Edit Shape Modifier la forme +Edit Text Modifier le texte +Edit the data: first row = series names, first column = categories. Modifiez les données : première ligne = noms de séries, première colonne = catégories. +Edit\nData Modifier les données +Edit\nShape Modifier la forme +Editing Modification +Effect Options Options d'effet +Effect\nOptions Options d'effet +Effects Effets +Email Address Adresse de messagerie +Email address: Adresse de messagerie : +Emphasis Accentuation +End Fin +End Show Terminer le diaporama +End of slide show Fin du diaporama +End of slide show, click to exit. Fin du diaporama, cliquez pour quitter. +End trim (s): Fin de la découpe (s) : +English (United Kingdom) Anglais (Royaume-Uni) +English (United States) Anglais (États-Unis) +Enter Entrée +Entrance Entrée +Equals Égal +Equation Équation +Equation Shapes Formes d'équation +Eraser Gomme +Escape Échap +Español Español +Exciting Expressifs +Exit Sortie +Expand Développer +Explosion: 14 Points Explosion : 14 branches +Explosion: 8 Points Explosion : 8 branches +Export Exporter +Export the presentation as: Exporter la présentation sous : +Exported {path} Exporté : {path} +Export… Exporter… +Fade Fondu +Fade in (s): Fondu entrant (s) : +Fade out (s): Fondu sortant (s) : +Fall Over Tomber +Ferris Wheel Grande roue +File Fichier +Fill Remplissage +Fill & Line Remplissage et trait +Fill Color Couleur de remplissage +Filled Radar Radar rempli +Find… Rechercher… +First Premier +First Column Première colonne +First Slide Première diapositive +First commit Premier commit +Fit Ajuster +Fit slide to current window Ajuster la diapositive à la fenêtre active +Fit to Window Ajuster à la fenêtre +Fit to\nWindow Ajuster à la fenêtre +Flash Flash +Flip Retourner +Flip Horizontal Retourner horizontalement +Flip Vertical Retourner verticalement +Float In Apparition flottante +Float Out Disparition flottante +Flowchart Organigramme +Flowchart: Alternate Process Organigramme : Processus de remplacement +Flowchart: Card Organigramme : Carte +Flowchart: Collate Organigramme : Assemblage +Flowchart: Connector Organigramme : Connecteur +Flowchart: Data Organigramme : Données +Flowchart: Decision Organigramme : Décision +Flowchart: Delay Organigramme : Délai +Flowchart: Direct Access Storage Organigramme : Stockage à accès direct +Flowchart: Display Organigramme : Écran +Flowchart: Document Organigramme : Document +Flowchart: Extract Organigramme : Extraction +Flowchart: Internal Storage Organigramme : Stockage interne +Flowchart: Magnetic Disk Organigramme : Disque magnétique +Flowchart: Manual Input Organigramme : Entrée manuelle +Flowchart: Manual Operation Organigramme : Opération manuelle +Flowchart: Merge Organigramme : Fusion +Flowchart: Multidocument Organigramme : Multidocument +Flowchart: Off-page Connector Organigramme : Connecteur hors page +Flowchart: Or Organigramme : Ou +Flowchart: Predefined Process Organigramme : Processus prédéfini +Flowchart: Preparation Organigramme : Préparation +Flowchart: Process Organigramme : Processus +Flowchart: Punched Tape Organigramme : Bande perforée +Flowchart: Sequential Access Storage Organigramme : Stockage à accès séquentiel +Flowchart: Sort Organigramme : Tri +Flowchart: Stored Data Organigramme : Données stockées +Flowchart: Summing Junction Organigramme : Nœud de sommation +Flowchart: Terminator Organigramme : Début/Fin +Fly In Voler vers l'intérieur +Fly Out Voler vers l'extérieur +Fly Through Vol à travers +Folded Corner Coin plié +Follow the layout Selon la disposition +Followed Hyperlink Lien hypertexte visité +Font Police +Font Color Couleur de police +Font Size Taille de police +Fonts Polices +Footer Pied de page +Foreground Premier plan +Format Format +Format Background Mise en forme de l'arrière-plan +Format Background… Mise en forme de l'arrière-plan… +Format Painter Reproduire la mise en forme +Format Painter (double-click to keep it on) Reproduire la mise en forme (double-clic pour le maintenir actif) +Format Pane Volet Mise en forme +Format Shape Mise en forme de la forme +Format Shape… Mise en forme de la forme… +Format\nBackground Mise en forme de l'arrière-plan +Format\nPane Volet Mise en forme +Formatting State État de la mise en forme +Fracture Fracture +Frame Cadre +Français Français +Freeform Forme libre +From À partir de +From Beginning À partir du début +From Bottom À partir du bas +From Bottom Left À partir du bas à gauche +From Bottom Right À partir du bas à droite +From Current Slide À partir de la diapositive actuelle +From Left À partir de la gauche +From Right À partir de la droite +From Top À partir du haut +From Top Left À partir du haut à gauche +From Top Right À partir du haut à droite +From bottom left À partir du bas à gauche +From bottom right À partir du bas à droite +From center À partir du centre +From top left À partir du haut à gauche +From top right À partir du haut à droite +From\nBeginning À partir du début +From\nCurrent Slide À partir de la diapositive actuelle +Full Complète +Full Page Slides Diapositives pleine page +Funnel Entonnoir +Gallery Galerie +General Général +Get Text Obtenir le texte +Glitter Scintillement +Glow Lueur +Go to Atteindre +Go to Slide Atteindre la diapositive +Grab bag Fourre-tout +Gradient fill Remplissage dégradé +Gradient stops Points de dégradé +Gradient… Dégradé… +Grayscale Niveaux de gris +Greek Grec +Green Vert +Gridlines Quadrillage +Group Grouper +Group Objects Grouper les objets +Grow & Turn Agrandir et pivoter +Grow/Shrink Agrandir/Réduire +Guides Repères +Half Moitié +Half Frame Demi-cadre +Handout Master Masque des documents +Handout Master (coming soon) Masque des documents (bientôt disponible) +Handout\nMaster Masque des documents +Handouts (1 slide per page) Documents (1 diapositive par page) +Handouts (2 slides per page) Documents (2 diapositives par page) +Handouts (3 slides per page) Documents (3 diapositives par page) +Handouts (4 slides per page) Documents (4 diapositives par page) +Handouts (6 slides per page) Documents (6 diapositives par page) +Handouts (9 slides per page) Documents (9 diapositives par page) +Header En-tête +Header & Footer En-tête et pied de page +Header &\nFooter En-tête et pied de page +Header Row Ligne d'en-tête +Header and Footer En-tête et pied de page +Header and Footer… En-tête et pied de page… +Heart Cœur +Height Hauteur +Height (in): Hauteur (in) : +Height: Hauteur : +Help Aide +Heptagon Heptagone +Hexagon Hexagone +Hide All Tout masquer +Hide Background Graphics Masquer les graphiques d'arrière-plan +Hide During Show Masquer pendant le diaporama +Hide Slide Masquer la diapositive +Hide background graphics Masquer les graphiques d'arrière-plan +Hide\nSlide Masquer la diapositive +Hierarchy Hiérarchie +High Élevée +Highlighter Surligneur +Histogram Histogramme +Home Accueil +Honeycomb Nid d'abeilles +Horizontal Horizontal +Horz In Horizontalement vers l'intérieur +Horz Out Horizontalement vers l'extérieur +How would you describe this object and its context to someone who is blind or has low vision? Comment décririez-vous cet objet et son contexte à une personne aveugle ou malvoyante ? +Hyperlink Lien hypertexte +Icons Icônes +In Vers l'intérieur +In Bounce Vers l'intérieur avec rebond +Include hidden slides Inclure les diapositives masquées +Increase Font Size Augmenter la taille de police +Increase List Level Augmenter le niveau de liste +Ink to Math Entrée manuscrite en équation +Ink to Math (coming soon) Entrée manuscrite en équation (bientôt disponible) +Ink to Shape Entrée manuscrite en forme +Ink to Shape (coming soon) Entrée manuscrite en forme (bientôt disponible) +Ink to Text Entrée manuscrite en texte +Ink to Text (coming soon) Entrée manuscrite en texte (bientôt disponible) +Ink to\nMath Entrée manuscrite en équation +Ink to\nShape Entrée manuscrite en forme +Ink to\nText Entrée manuscrite en texte +Inner Intérieure +Insert Insérer +Insert Above Insérer au-dessus +Insert Below Insérer en dessous +Insert Hyperlink Insérer un lien hypertexte +Insert Layout Insérer une disposition +Insert Left Insérer à gauche +Insert Placeholder Insérer un espace réservé +Insert Right Insérer à droite +Insert Table Insérer un tableau +Insert Table… Insérer un tableau… +Insert picture from file… Insérer une image à partir d'un fichier… +Insert\nAbove Insérer au-dessus +Insert\nBelow Insérer en dessous +Insert\nLayout Insérer une disposition +Insert\nLeft Insérer à gauche +Insert\nPlaceholder Insérer un espace réservé +Insert\nRight Insérer à droite +Inspect Presentation Inspecter la présentation +Inspect Shape Inspecter la forme +Inspect Slide Inspecter la diapositive +Interface Language Langue de l'interface +Interface language: Langue de l'interface : +Interface size Taille de l'interface +Isosceles Triangle Triangle isocèle +Italiano Italiano +Italic Italique +JPEG image (current slide) Image JPEG (diapositive active) +Join our community on Discord Rejoignez notre communauté sur Discord +Join the ArtCraft community on Discord Rejoignez la communauté ArtCraft sur Discord +Justify Justifier +L-Shape Forme en L +Language Langue +Last Dernier +Last Column Dernière colonne +Last Slide Dernière diapositive +Last commit Dernier commit +Layout Disposition +Learn More En savoir plus +Learn\nMore En savoir plus +Ledger Paper (11x17 in) Papier Ledger (11x17 in) +Left Gauche +Left Brace Accolade gauche +Left Bracket Crochet gauche +Letter Paper (8.5x11 in) Papier Letter (8.5x11 in) +Liberation Serif Liberation Serif +Light Blue Bleu clair +Light Green Vert clair +Light/Dark appearance Apparence claire/sombre +Lighten Éclaircir +Lightning Éclair +Lightning Bolt Éclair +Line Trait +Line Color Couleur du trait +Line Spacing Interligne +Line Spacing Options… Options d'interligne… +Line delta Écart de lignes +Line spacing (lines): Interligne (lignes) : +Line with Markers Courbe avec marqueurs +Linear Linéaire +Lines Lignes +Lines +/− Lignes +/− +Lines added Lignes ajoutées +Lines deleted Lignes supprimées +Link Lien +Link… Lien… +List Commands Liste des commandes +Lock Verrouiller +Long Dash Tiret long +Long Dash Dot Tiret long point +Loop continuously until 'Esc' Répéter en boucle jusqu'à « Échap » +Loop until Stopped Boucler jusqu'à l'arrêt +Loops Boucles +Loose Desserré +Low Basse +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 l'équipe ArtCraft et les contributeurs de DeckCraft +Margins (pt) Marges (pt) +Mark as decorative Marquer comme décoratif +Mark selected text as: Marquer le texte sélectionné comme : +Math Mathématiques +Matrix Matrice +Maximize content (else ensure fit) Agrandir le contenu (sinon ajuster) +Media Média +Media Info Informations sur le média +Medium Moyenne +Merge Cells Fusionner les cellules +Merge Shapes Fusionner les formes +Merge\nCells Fusionner les cellules +Merge\nShapes Fusionner les formes +Merged PRs Demandes de tirage fusionnées +Middle Milieu +Minus Sign Signe moins +Model Modèle +Models Modèles +Moon Lune +More Colors… # Plus de couleurs… # +Morph Transformation +Motion Mouvement +Motion Paths Trajectoires +Move Déplacer +Move Down Descendre +Move Insertion Point Déplacer le point d'insertion +Move Section Déplacer la section +Move Section Down Déplacer la section vers le bas +Move Section Up Déplacer la section vers le haut +Move Slide Déplacer la diapositive +Move Up Monter +Multiplication Sign Signe de multiplication +Multiply Multiplication +Mute Muet +Name Nom +Name (A–Z) Nom (A–Z) +Name: Nom : +New Comment Nouveau commentaire +New Presentation Nouvelle présentation +New Slide Nouvelle diapositive +New Slide (⇧⌘N) Nouvelle diapositive (⇧⌘N) +New presentation Nouvelle présentation +New show name: Nom de la nouvelle projection : +New\nComment Nouveau commentaire +New\nSlide Nouvelle diapositive +Next Suivant +Next Slide Diapositive suivante +Next Window Fenêtre suivante +Next ▶ Suivant ▶ +No Color Aucune couleur +No Fill Aucun remplissage +No Glow Aucune lueur +No Outline Aucun contour +No Reflection Aucun reflet +No Shadow Aucune ombre +No Soft Edges Aucun contour progressif +No accessibility issues found. People with disabilities should not have difficulty reading this document. Aucun problème d'accessibilité détecté. Les personnes handicapées ne devraient pas avoir de difficulté à lire ce document. +No comments on this slide. Aucun commentaire sur cette diapositive. +No contributor data was built into this copy. Aucune donnée de contributeurs n'a été intégrée à cette copie. +No fill Aucun remplissage +No line Aucun trait +No model credits were built into this copy. Aucune mention des modèles utilisés n'a été intégrée à cette copie. +No notes. Aucune note. +No sound: {err} Aucun son : {err} +None Aucun +Normal Normal +Not Equal Différent de +Not allowed Non autorisé +Notes Notes +Notes Master Masque des notes +Notes Master (coming soon) Masque des notes (à venir) +Notes Page Page de notes +Notes Pages Pages de notes +Notes\nMaster Masque des notes +Notes\nPage Page de notes +Nudge Décaler +Number of columns: Nombre de colonnes : +Number of rows: Nombre de lignes : +Numbering Numérotation +Object Color Couleur de l'objet +Objects Objets +Octagon Octogone +On Click Par clic +On Click of {name} Par clic sur {name} +On Click of… (none) Par clic sur… (aucun) +On Mouse Click Au clic de souris +On-screen Show (16:10) À l'écran (16:10) +Open Data Ouvrir les données +Open Dialog Ouvrir la boîte de dialogue +Open Recovered Presentations Ouvrir les présentations récupérées +Open the sample deck Ouvrir l'exemple de présentation +Open… Ouvrir… +Orange Orange +Orbit Orbite +Order Objects Ordre des objets +Origami Origami +Out Vers l'extérieur +Out Bounce Vers l'extérieur avec rebond +Outer Externe +Outline Plan +Outline (.txt) Plan (.txt) +Outline View Mode Plan +Outline\nView Mode Plan +Oval Ovale +Oval ends Extrémités ovales +Overhead Rétroprojecteur +PDF document (.pdf) Document PDF (.pdf) +PNG images (all slides) Images PNG (toutes les diapositives) +PNG images (current slide) Images PNG (diapositive actuelle) +PRs Demandes de tirage +Page Curl Enroulement de page +Page Setup… Mise en page… +PageDown PageDown +PageUp PageUp +Pan Panoramique +Pane Volet +Paragraph Paragraphe +Paragraph… Paragraphe… +Parallelogram Parallélogramme +Pareto Pareto +Partial Circle Cercle partiel +Particles Particules +Paste Coller +Paste (⌘V) Coller (⌘V) +Paste Formatting Coller la mise en forme +Paste and Match Formatting Coller avec la même mise en forme +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Collez ou saisissez un plan. Les lignes sans retrait deviennent des titres de diapositives ; les lignes avec tabulation deviennent des puces. +Pasted image.png Image collée.png +Path Trajectoire +Pattern fill Remplissage avec motif +Pause Pause +Peek In Apparition en coulisse +Peel Off Décollage +Pencil Crayon +Pentagon Pentagone +Perspective Perspective +Pick a graphic; type one item per line. Choisissez un graphique ; saisissez un élément par ligne. +Pick a look for your slides. Ideas are generated on your device. Choisissez un style pour vos diapositives. Les idées sont générées sur votre appareil. +Picture Image +Picture Format Format de l'image +Picture Styles Styles d'image +Picture from File… Image à partir d'un fichier… +Picture or texture fill Remplissage avec image ou texture +Picture\nStyles Styles d'image +Pictures Images +Pie Secteurs +Pin Épingler +Placeholder colour Couleur de l'espace réservé +Plan\nBuild\nLaunch Planifier\nCréer\nLancer +Plaque Plaque +Play Lire +Play Across Slides Lire sur plusieurs diapositives +Play Full Screen Lire en plein écran +Play Narrations Lire les narrations +Play from Current Slide À partir de la diapositive actuelle +Play from Start À partir du début +Play from Start (F5) À partir du début (F5) +Play from\nCurrent Slide À partir de la diapositive actuelle +Play from\nStart À partir du début +Play/Pause Lire/Interrompre +Playback Lecture +Plus Plus +Plus In Plus vers l'intérieur +Plus Out Plus vers l'extérieur +Plus Sign Signe plus +Portrait (9:16) Portrait (9:16) +Português Português +Position Position +Position Objects Positionner les objets +Position and Size Position et taille +Post Publier +Poster Frame Image d'affiche +PowerPoint Presentation (.pptx) Présentation PowerPoint (.pptx) +Preferences Options +Preferences… Options… +Presentation Présentation +Presentations Présentations +Presentations and slide shows, rebuilt from scratch in pure Rust. Présentations et diaporamas, reconstruits de zéro en Rust pur. +Presented by a speaker (full screen) Présentée par un intervenant (plein écran) +Presenter View Mode Présentateur +Presenter View — DeckCraft Mode Présentateur — DeckCraft +Presenter\nView Mode Présentateur +Preset gradients Dégradés prédéfinis +Prestige Prestige +Preview Aperçu +Previous Slide Diapositive précédente +Print layout: Disposition d'impression : +Properties Propriétés +Pulse Pulsation +Punctuation Ponctuation +Purple Violet +Push Pousser +Pyramid Pyramide +Quick Styles Styles rapides +Quick\nStyles Styles rapides +Radar Radar +Radial Radial +Random Aléatoire +Random Bars Barres aléatoires +Reading View Mode Lecture +Reading\nView Mode Lecture +Real name Nom réel +Recent Récents +Record Enregistrer +Recording narration needs audio capture (coming soon) L'enregistrement de narrations nécessite une capture audio (à venir) +Recovered Presentations Présentations récupérées +Recovered {} from the last session {} récupéré(s) depuis la dernière session +Rectangle Rectangle +Rectangle: Diagonal Corners Rounded Rectangle : coins diagonaux arrondis +Rectangle: Diagonal Corners Snipped Rectangle : coins diagonaux découpés +Rectangle: Rounded Corners Rectangle : coins arrondis +Rectangle: Single Corner Rounded Rectangle : un coin arrondi +Rectangle: Single Corner Snipped Rectangle : un coin découpé +Rectangle: Top Corners One Rounded and One Snipped Rectangle : coins supérieurs, un arrondi et un découpé +Rectangle: Top Corners Rounded Rectangle : coins supérieurs arrondis +Rectangle: Top Corners Snipped Rectangle : coins supérieurs découpés +Rectangles Rectangles +Rectangular Rectangulaire +Red Rouge +Red Pen Stylo rouge +Redo Rétablir +Redo (⌘Y) Rétablir (⌘Y) +Reflected Rounded Rectangle Rectangle arrondi avec reflet +Reflection Reflet +Regroup Regrouper +Regular Pentagon Pentagone régulier +Rehearse Timings Répéter les minutages +Rehearse\nTimings Répéter les minutages +Remove Supprimer +Remove All Animations Supprimer toutes les animations +Remove All Sections Supprimer toutes les sections +Remove Animation Supprimer l'animation +Remove Background Supprimer l'arrière-plan +Remove Background (coming soon) Supprimer l'arrière-plan (à venir) +Remove Section Supprimer la section +Remove Section & Slides Supprimer la section et les diapositives +Remove stop Supprimer le point +Remove\nBackground Supprimer l'arrière-plan +Rename Renommer +Rename Layout Renommer la disposition +Rename Section Renommer la section +Rename Section… Renommer la section… +Rename Slide Renommer la diapositive +Rename… Renommer… +Render Slide Effectuer le rendu de la diapositive +Reopen Rouvrir +Reorder Animation Réorganiser l'animation +Reorder Objects Réorganiser les objets +Replace straight quotes with smart quotes Remplacer les guillemets droits par des guillemets typographiques +Reply Répondre +Reply… Répondre… +Reset Réinitialiser +Reset Background Réinitialiser l'arrière-plan +Reset Crop Réinitialiser le rognage +Reset Effects Réinitialiser les effets +Reset Picture Réinitialiser l'image +Reset Slide Réinitialiser la diapositive +Reset Slide Background Réinitialiser l'arrière-plan de la diapositive +Resize shape to fit text Redimensionner la forme pour ajuster le texte +Resolve Marquer comme résolu +Resolve Thread Résoudre la conversation +Return Retour +Reveal Révéler +Reverse the order Inverser l'ordre +Revert Restaurer la version précédente +Review Révision +Rewind after Playing Rembobiner après la lecture +Ribbon Tab Onglet du ruban +Ribbon: Tilted Down Ruban : incliné vers le bas +Ribbon: Tilted Up Ruban : incliné vers le haut +Right Droite +Right Brace Accolade droite +Right Bracket Crochet droit +Right Triangle Triangle rectangle +Right-to-Left Text Direction Sens du texte de droite à gauche +Ring Anneau +Ripple Ondulation +Rise Up Élévation +Rotate Faire pivoter +Rotate Left 90° Pivoter à gauche de 90° +Rotate Right 90° Pivoter à droite de 90° +Rotate all text 270° Faire pivoter tout le texte de 270° +Rotate all text 90° Faire pivoter tout le texte de 90° +Rotate with shape Pivoter avec la forme +Rotation Rotation +Round Dot Point rond +Rounded Diagonal Corner Coin diagonal arrondi +Ruler Règle +Saturation Saturation +Saturation {}% Saturation {} % +Save Enregistrer +Save (⌘S) Enregistrer (⌘S) +Save As… Enregistrer sous… +Save AutoRecover Information Enregistrer les informations de récupération automatique +Save as Template… Enregistrer comme modèle… +Save to Data Enregistrer dans les données +Saved Enregistré +Saved {path} Enregistré : {path} +Scatter Nuage de points +ScreenTip: Info-bulle : +Screenshot Capture d'écran +Screenshot (not available yet) Capture d'écran (pas encore disponible) +Scroll: Horizontal Parchemin : horizontal +Scroll: Vertical Parchemin : vertical +Search commands (⇧⌘P) Rechercher des commandes (⇧⌘P) +Search commands… Rechercher des commandes… +Section Section +Seek Rechercher une position +Select Sélectionner +Select All Tout sélectionner +Select All Text Sélectionner tout le texte +Select Cells Sélectionner des cellules +Select Objects Sélectionner des objets +Select Paragraph Sélectionner le paragraphe +Select Slides Sélectionner des diapositives +Select Text Sélectionner le texte +Select Word Sélectionner le mot +Select a chart first. Sélectionnez d'abord un graphique. +Select a shape to format it. Sélectionnez une forme pour la mettre en forme. +Select an object on the slide and add an animation from the Animations tab. Sélectionnez un objet sur la diapositive et ajoutez une animation depuis l'onglet Animations. +Selection Sélection +Selection Pane Volet Sélection +Selection Pane… Volet Sélection… +Selection\nPane Volet Sélection +Send Backward Reculer +Send to Back Mettre à l'arrière-plan +Send\nBackward Reculer +Sentence case. Type phrase. +Set Text Définir le texte +Set Up Show… Configurer la projection… +Set Up Slide Show Configurer la projection +Set Up Slide Show… Configurer la projection… +Set Up\nSlide Show Configurer la projection +Set as Default Shape Définir comme forme par défaut +Shading Tramage +Shadow Ombre +Shape Forme +Shape Effects Effets de forme +Shape Fill Remplissage de la forme +Shape Format Format de la forme +Shape Gallery Galerie de formes +Shape Outline Contour de la forme +Shape Styles Styles de formes +Shape {} Forme {} +Shape\nStyles Styles de formes +Shapes Formes +Shift+ Shift+ +Shift+F9 Shift+F9 +Show Afficher +Show All Tout afficher +Show Comments Afficher les commentaires +Show Media Controls Afficher les commandes multimédias +Show Slide Afficher la diapositive +Show smart guides Afficher les repères dynamiques +Show type Type de projection +Show without animation Afficher sans animation +Show without narration Afficher sans narration +Show/Hide Afficher/Masquer +Show\nComments Afficher les commentaires +Shred Déchiqueter +Shrink & Turn Réduction et rotation +Shrink text on overflow Réduire le texte en cas de débordement +Simple Frame, White Cadre simple, blanc +Size Taille +Size & Properties Taille et propriétés +Slide Master Masque des diapositives +Slide Number Numéro de diapositive +Slide Show Diaporama +Slide Size Taille des diapositives +Slide Sorter Trieuse de diapositives +Slide number Numéro de diapositive +Slide timings recorded. Minutages des diapositives enregistrés. +Slide {:02}:{:04.1} Total {:02}:{:02} Diapositive {:02}:{:04.1} Total {:02}:{:02} +Slide {} of {} Diapositive {} sur {} +Slide {}: {}{} Diapositive {}: {}{} +Slide {}: “{w}” Diapositive {}: « {w} » +Slide\nMaster Masque des diapositives +Slide\nNumber Numéro de diapositive +Slide\nSize Taille des diapositives +Slide\nSorter Trieuse de diapositives +Slides (e.g. 1,3,5): Diapositives (par ex. 1,3,5) : +Slides from Outline Diapositives à partir du plan +Slides from Outline… Diapositives à partir du plan… +Slides sized for: Taille des diapositives : +SmartArt SmartArt +Smile Sourire +Smiley Face Visage souriant +Smoothly En douceur +Smoothly Left En douceur à gauche +Smoothly Right En douceur à droite +Snap objects to grid Aligner les objets sur la grille +Soft Edge Rectangle Rectangle à contours progressifs +Soft Edges Contours progressifs +Solid Uni +Solid fill Remplissage uni +Solid line Trait continu +Sort Trier +Source on GitHub Code source sur GitHub +Space Espace +Spacing after (pt): Espacement après (pt) : +Spacing before (pt): Espacement avant (pt) : +Special — hanging (in): Spécial — suspendu (pouces) : +Speech Voix +Speech Bubble: Oval Bulle : ovale +Speech Bubble: Rectangle Bulle : rectangle +Speech Bubble: Rectangle with Corners Rounded Bulle : rectangle à coins arrondis +Spelling Orthographe +Spin Tourner +Spinner Rotation continue +Split Fractionner +Split Cells Fractionner les cellules +Split\nCells Fractionner les cellules +Square Carré +Square (1:1) Carré (1:1) +Square Dot Point carré +Stacked Empilé +Stacked Area Aires empilées +Stacked Bar Barres empilées +Stacked Column Histogramme empilé +Stacked Line Courbes empilées +Standard (4:3) Standard (4:3) +Standard Colors Couleurs standard +Star Étoile +Star: 10 Points Étoile : 10 branches +Star: 12 Points Étoile : 12 branches +Star: 16 Points Étoile : 16 branches +Star: 24 Points Étoile : 24 branches +Star: 32 Points Étoile : 32 branches +Star: 4 Points Étoile : 4 branches +Star: 5 Points Étoile : 5 branches +Star: 6 Points Étoile : 6 branches +Star: 7 Points Étoile : 7 branches +Star: 8 Points Étoile : 8 branches +Stars and Banners Étoiles et bannières +Start After Previous Après la précédente +Start Automatically Automatiquement +Start On Click Par clic +Start With Previous Avec la précédente +Start a conversation Démarrez une conversation +Start time (s): Heure de début (s) : +Start: Début : +Stealth end Pointe de flèche +Stock Bourse +Stop Arrêter +Stop Editing Text Arrêter la modification du texte +Strikethrough Barré +Strips Bandes +Style {i} Style {i} +Subscript Indice +Subtle Subtils +Sun Soleil +Sunburst Rayons de soleil +Superscript Exposant +Surface Surface +Switch Basculer +Swivel Pivoter +Symbol Symbole +System language Langue du système +Tab Tabulation +Table Tableau +Table Design Création de tableau +Table Style Options Options de style de tableau +Table Styles Styles de tableau +Table… Tableau… +Task Pane Volet des tâches +Teardrop Goutte +Teeter Bascule +Text Texte +Text Box Zone de texte +Text Box Margins Marges de la zone de texte +Text Direction Sens du texte +Text Effects Effets de texte +Text Fill Remplissage du texte +Text Highlight Color Couleur de surlignage du texte +Text Options Options de texte +Text Outline Contour du texte +Text Shadow Ombre du texte +Text/Background - Dark 1 Texte/Arrière-plan - Sombre 1 +Text/Background - Dark 2 Texte/Arrière-plan - Sombre 2 +Text/Background - Light 1 Texte/Arrière-plan - Clair 1 +Text/Background - Light 2 Texte/Arrière-plan - Clair 2 +Text\nBox Zone de texte +The spelling check is complete. No issues found. La vérification de l'orthographe est terminée. Aucun problème détecté. +Theme Colors Couleurs du thème +Theme Gallery Galerie de thèmes +Themes Thèmes +Thesaurus Dictionnaire des synonymes +Thesaurus (coming soon) Dictionnaire des synonymes (à venir) +This Document Ce document +Thought Pensée +Thought Bubble: Cloud Pensée : nuage +Through Black À travers le noir +Tight Serré +Timing Minutage +Top Haut +Total Row Ligne de totaux +Transition Transition +Transition Gallery Galerie de transitions +Transitions Transitions +Translate Traduire +Translation needs a language model (not bundled) La traduction nécessite un modèle de langage (non inclus) +Transparency Transparence +Trapezoid Trapèze +Treemap Treemap +Triangle Triangle +Trigger Déclencheur +Trim Découper +Trim Media Découper le média +Turns Tours +Type Type +Type Text Saisir du texte +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Saisissez une équation sous forme linéaire (par ex. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Découvrir +Underline Souligné +Undo Annuler +Undo (⌘Z) Annuler (⌘Z) +Ungroup Dissocier +Up Vers le haut +Use Timings Utiliser les minutages +Use timings, if present Utiliser les minutages, le cas échéant +Username Nom d'utilisateur +Version Version +Version {} Version {} +Vert In Verticalement vers l'intérieur +Vert Out Verticalement vers l'extérieur +Vertical Vertical +Vertical alignment Alignement vertical +Very Loose Très desserré +Very Tight Très serré +Video Vidéo +Video from File… Vidéo à partir d'un fichier… +View Affichage +Volume Volume +Vortex Vortex +Waterfall Cascade +Wave Onde +Web Page or File Page web ou fichier +Wedge Coin +Weight Épaisseur +Wheel Roue +Widescreen (13.333x7.5 in) Grand écran (13,333×7,5 pouces) +Widescreen (16:9) Grand écran (16:9) +Width Largeur +Width (in): Largeur (pouces) : +Width: Largeur : +Width: Largeur : +Wind Vent +Window Fenêtre +Wipe Balayage +With Previous Avec la précédente +WordArt WordArt +WordArt style {} Style WordArt {} +Words Mots +Wrap Text in Shape Renvoyer le texte à la ligne dans la forme +Wrap text in shape Renvoyer le texte à la ligne dans la forme +Yellow Jaune +Your changes will be lost if you don't save them. Vos modifications seront perdues si vous ne les enregistrez pas. +Your name (comments): Votre nom (commentaires) : +Zoom Zoom +Zoom In Zoom avant +Zoom Out Zoom arrière +Zoom… Zoom… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Accepter la révision +Action Settings Paramètres de l'action +Add Font Ajouter une police +Add Guide Ajouter un repère +Add Point Ajouter un point +Add Shape Ajouter une forme +Add to Dictionary Ajouter au dictionnaire +Align Cell Text Aligner le texte de la cellule +Apply Design Idea Appliquer l'idée de conception +Arrow: Circular Flèche : Circulaire +Arrow: Circular Counter-clockwise Flèche : Circulaire dans le sens antihoraire +Arrow: Circular Two-headed Flèche : Circulaire à deux pointes +Arrow: Curved Down Flèche : Courbée vers le bas +Arrow: Curved Left Flèche : Courbée vers la gauche +Arrow: Curved Right Flèche : Courbée vers la droite +Arrow: Curved Up Flèche : Courbée vers le haut +Arrow: Swoosh Flèche : Swoosh +Artistic Effects Effets artistiques +AutoCorrect Options Options de correction automatique +Bean Haricot +Borders Bordures +Bounce Left Rebond vers la gauche +Bounce Right Rebond vers la droite +Browse for Themes… Parcourir les thèmes… +Callout: Bent Line Légende : Ligne coudée +Callout: Bent Line with Accent Bar Légende : Ligne coudée avec barre d'accent +Callout: Bent Line with Border and Accent Bar Légende : Ligne coudée avec bordure et barre d'accent +Callout: Bent Line with No Border Légende : Ligne coudée sans bordure +Callout: Double Bent Line Légende : Ligne à double coude +Callout: Double Bent Line with Accent Bar Légende : Ligne à double coude avec barre d'accent +Callout: Double Bent Line with Border and Accent Bar Légende : Ligne à double coude avec bordure et barre d'accent +Callout: Double Bent Line with No Border Légende : Ligne à double coude sans bordure +Callout: Left-Right Arrow Légende : Flèche gauche-droite +Callout: Line with Accent Bar Légende : Ligne avec barre d'accent +Callout: Line with Border and Accent Bar Légende : Ligne avec bordure et barre d'accent +Callout: Line with No Border Légende : Ligne sans bordure +Callout: Quad Arrow Légende : Flèche quadruple +Callout: Up-Down Arrow Légende : Flèche haut-bas +Cell Margins Marges de cellule +Change Colors Modifier les couleurs +Change Layout Modifier la disposition +Change Picture… Modifier l'image… +Change Spelling Modifier l'orthographe +Chart Marker: Cross Lines Marqueur de graphique : Lignes croisées +Chart Marker: Plus Lines Marqueur de graphique : Lignes en croix +Chart Marker: Star Lines Marqueur de graphique : Lignes en étoile +Color At Couleur à l'emplacement +Commit Composition Valider la composition +Compare Comparer +Compare… Comparer… +Compose Text Composer le texte +Compress Pictures Compresser les images +Contract Contraction +Convert to Shapes Convertir en formes +Convert to SmartArt Convertir en SmartArt +Convert to Text Convertir en texte +Corner Tabs: Quarter Circles Languettes de coin : Quarts de cercle +Corner Tabs: Squares Languettes de coin : Carrés +Corner Tabs: Triangles Languettes de coin : Triangles +Crescent Moon Croissant de lune +Curved Square Carré courbé +Decaying Wave Onde amortie +Delete Guide Supprimer le repère +Delete Point Supprimer le point +Demote Rétrograder +Diagonal Down Right Diagonale vers le bas à droite +Diagonal Up Right Diagonale vers le haut à droite +Draw Table Dessiner un tableau +dropped file fichier déposé +Edit Photo Album… Modifier l'album photo… +Edit Points Modifier les points +Edit SmartArt Text Modifier le texte SmartArt +End Review Terminer la révision +Find Rechercher +Flowchart: Offline Storage Organigramme : Stockage hors ligne +Fonts in Presentation Polices dans la présentation +Font… Police… +Football Ballon de football américain +Gear: 6 Teeth Engrenage : 6 dents +Gear: 9 Teeth Engrenage : 9 dents +Grid and Guides Grille et repères +Grid Options… Options de la grille… +Handout Placeholders Espaces réservés des documents +Heartbeat Battement de cœur +Hex D Hexagone bas +Hex L Hexagone gauche +Hex R Hexagone droite +Hex U Hexagone haut +Horizontal Figure 8 Huit horizontal +i. ii. iii. i. ii. iii. +Icon Gallery Galerie d'icônes +Info Informations +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Encre vers forme : transforme les lignes, rectangles, ovales et triangles dessinés en formes +Insert Picture in SmartArt Insérer une image dans SmartArt +Insert Picture in SmartArt… Insérer une image dans SmartArt… +Insert Synonym Insérer un synonyme +Layout Placeholders Espaces réservés de la disposition +Line: Rising Ligne : Montante +Loop de Loop Looping +Move Guide Déplacer le repère +Move Handle Déplacer la poignée +Move Point Déplacer le point +Neutron Neutron +New Window Nouvelle fenêtre +Next Comment Commentaire suivant +No comments. Aucun commentaire. +no presentation open Aucune présentation ouverte +no slides Aucune diapositive +no text insertion point Aucun point d'insertion de texte +Notes Placeholders Espaces réservés des notes +nothing selected Rien n'est sélectionné +nothing to redo Rien à rétablir +nothing to undo Rien à annuler +Open Ouvrir +Particles In Particules entrantes +Particles Out Particules sortantes +Paste Special Collage spécial +Paste Special… Collage spécial… +Peanut Cacahuète +Peek Out Disparition en coulisse +Photo Album… Album photo… +Pick a design for this slide. Ideas are generated on your device. Choisissez un design pour cette diapositive. Les idées sont générées sur votre appareil. +Picture Style Gallery Galerie de styles d'image +Point Type Type de point +Points Points +Preserve Conserver +Preview Animations Aperçu des animations +Previous Comment Commentaire précédent +Print Imprimer +Print… Imprimer… +Promote Promouvoir +Quarter Wedge Quart de coin +Quick Access Toolbar Barre d'outils Accès rapide +Recolor Recolorier +Recolor Gallery Galerie de recoloriage +Remove Shape Supprimer une forme +Replace Remplacer +Replace Fonts Remplacer les polices +Replace… Remplacer… +Rescan Installed Fonts Réanalyser les polices installées +Reuse Slides… Réutiliser les diapositives… +Revisions Révisions +Ribbon: Curved and Tilted Down Ruban : courbé et incliné vers le bas +Ribbon: Curved and Tilted Up Ruban : courbé et incliné vers le haut +Ribbon: Left-Right Fold Ruban : pli gauche-droite +S Curve 1 Courbe en S 1 +S Curve 2 Courbe en S 2 +select text or a shape Sélectionnez du texte ou une forme +select two or more objects Sélectionnez deux objets ou plus +Set Transparent Color Définir la couleur transparente +Set Zoom Définir le zoom +Sine Wave Onde sinusoïdale +Single L Simple gauche +Single R Simple droite +Sink Down Enfoncement +size (pt) taille (pt) +Size and Position… Taille et position… +SmartArt Styles Styles SmartArt +Smooth Corners Coins adoucis +Sound Son +Spelling Dictionary Dictionnaire orthographique +Spiral Left Spirale vers la gauche +Spiral Right Spirale vers la droite +Spring Ressort +Stairs Down Escalier vers le bas +Starter Templates Modèles de démarrage +Strips In Bandes entrantes +Strips Out Bandes sortantes +Swoosh Swoosh +Table Eraser Gomme de tableau +Tabs… Tabulations… +Text Pane Volet Texte +Text Transform Transformation du texte +Text Transparency Transparence du texte +tOGGLE cASE tOGGLE cASE +Trapezoid: Uneven Sides Trapèze : Côtés inégaux +unknown interface language Langue d'interface inconnue +Unlock Déverrouiller +Variant Gallery Galerie de variantes +Variants Variantes +Vertical Figure 8 Huit vertical +Zigzag Zigzag + (not checked) (non vérifié) +4 Point Star Étoile à 4 branches +5 Point Star Étoile à 5 branches +6 Point Star Étoile à 6 branches +8 Point Star Étoile à 8 branches +{ch} Bullet {ch} Puce +{f} (Body) {f} (Corps) +{f} (Headings) {f} (Titres) +{name}: DeckCraft can't open this kind of file {name} : DeckCraft ne peut pas ouvrir ce type de fichier +{n} Column{} {n} Colonne{} +{r} pt {r} pt +{r} pt glow Lueur de {r} pt +{w} pt {w} pt +{} ({} slides) {} ({} diapositives) +{} Slide Master Masque des diapositives {} +{} contributors · {} commits Contributeurs : {} · Commits : {} +{} presentations {} présentations +{}x{} Table Tableau {}×{} +“{}” is not available yet. « {} » n'est pas encore disponible. +−Bin −Intervalle +▶ Play All ▶ Tout lire +◀ Previous ◀ Précédent +✏ on ✏ activé diff --git a/crates/ui-egui/src/i18n/pt.tsv b/crates/ui-egui/src/i18n/pt.tsv new file mode 100644 index 000000000..aff0cc618 --- /dev/null +++ b/crates/ui-egui/src/i18n/pt.tsv @@ -0,0 +1,1408 @@ +# Portuguese interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Data fixa (vazio = atualização automática): + Footer text: Texto do rodapé: + Present Apresentar + pt pt + — Edited — Editado +"Not Allowed" Symbol Símbolo «Proibido» +% of all commits % de todas as confirmações ++ New Comment + Novo comentário ++ New Slide + Novo slide ++ Row + Linha ++ Series + Série ++Bin +Intervalo +100% Stacked Bar Barra 100% empilhada +100% Stacked Column Coluna 100% empilhada +35mm Slides Slides de 35 mm +@ribbon:Home Página Inicial +@ribbon:Insert Inserir +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{}: solicitações de pull (PR): {}, confirmações: {}, linhas: +{} / −{} (Δ {}), recursos binários: +{} / −{}, {} – {} +A3 Paper (297x420 mm) Papel A3 (297×420 mm) +A4 Paper (210x297 mm) Papel A4 (210×297 mm) +Aa Aa +Abc Abc +About Sobre +About DeckCraft Sobre o DeckCraft +Accent 1 Realce 1 +Accent 2 Realce 2 +Accent 3 Realce 3 +Accent 4 Realce 4 +Accent 5 Realce 5 +Accent 6 Realce 6 +Accessibility Checker Verificador de Acessibilidade +Across Através +Action Ação +Action Button: Custom Botão de ação: personalizado +Action Button: Document Botão de ação: documento +Action Button: Get Information Botão de ação: obter informações +Action Button: Go Back Botão de ação: voltar +Action Button: Go Back or Previous Botão de ação: voltar ou anterior +Action Button: Go Forward or Next Botão de ação: avançar ou próximo +Action Button: Go Home Botão de ação: página inicial +Action Button: Go to Beginning Botão de ação: para o início +Action Button: Go to End Botão de ação: para o fim +Action Button: Help Botão de ação: ajuda +Action Button: Sound Botão de ação: som +Action Button: Video Botão de ação: vídeo +Action Button: {k} Botão de ação: {k} +Action Buttons Botões de ação +Add Animation Adicionar Animação +Add Section Adicionar Seção +Add\nAnimation Adicionar animação +Address: Endereço: +Adjust Shape Ajustar forma +After Previous Após a anterior +After: Depois: +Airplane Avião +Align Alinhar +Align Bottom Alinhar abaixo +Align Center Centralizar +Align Left Alinhar à esquerda +Align Middle Alinhar ao meio +Align Right Alinhar à direita +Align Text Alinhar texto +Align Top Alinhar acima +Alt Text Texto Alternativo +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Texto alternativo +An open-source, clean-room project. Not affiliated with Microsoft. Um projeto independente de código aberto. Não é afiliado à Microsoft. +Angle Ângulo +Animation Gallery Galeria de animações +Animation Pane Painel de Animação +Animation Styles Estilos de animação +Animation\nPane Painel de animação +Animations Animações +Animation Painter Pincel de Animação +Apply Animation Aplicar animação +Play/Pause GIF Reproduzir/pausar GIF +Animations on Slide Animações no slide +Appear Aparecer +Apply Aplicar +Apply To All Aplicar a Tudo +Apply to All Aplicar a tudo +Apply\nTo All Aplicar a tudo +Arc Arco +Arcs Arcos +Area Área +Arrange Organizar +Arrow Seta +Arrow at end Seta no final +Arrow at start Seta no início +Arrow: Bent Seta: dobrada +Arrow: Bent-Up Seta: dobrada para cima +Arrow: Chevron Seta: divisor +Arrow: Down Seta: para baixo +Arrow: Left Seta: para a esquerda +Arrow: Left-Right Seta: esquerda-direita +Arrow: Left-Right-Up Seta: esquerda-direita-cima +Arrow: Left-Up Seta: esquerda-cima +Arrow: Notched Right Seta: direita entalhada +Arrow: Pentagon Seta: pentagonal +Arrow: Quad Seta: de quatro pontas +Arrow: Right Seta: para a direita +Arrow: Striped Right Seta: direita listrada +Arrow: U-Turn Seta: em U +Arrow: Up Seta: para cima +Arrow: Up-Down Seta: cima-baixo +Arrows Setas +Arrows at both ends Setas nas duas extremidades +As One Object Como um objeto +Audio Áudio +Audio from File… Áudio do Arquivo… +AutoCorrect as you type AutoCorreção ao digitar +Autofit Ajuste automático +Automatic Automático +B4 (ISO) Paper (250x353 mm) Papel B4 (ISO) (250×353 mm) +B5 (ISO) Paper (176x250 mm) Papel B5 (ISO) (176×250 mm) +Background Tela de Fundo +Background Styles Estilos de Plano de Fundo +Background\nStyles Estilos de fundo +Backspace Backspace +Banded Columns Colunas com faixas +Banded Rows Linhas com faixas +Banner Faixa +Basic Cycle Ciclo Básico +Basic List Lista Básica +Basic Process Processo Básico +Basic Shapes Formas Básicas +Before text (in): Antes do texto (pol): +Bevel Bisel +Binary assets added Recursos binários adicionados +Binary assets removed Recursos binários removidos +Black Left Pelo preto à esquerda +Black Pen Caneta Preta +Black Right Pelo preto à direita +Blinds Persianas +Block Arc Arco de Bloco +Block Arrows Setas de Bloco +Blue Azul +Blue Pen Caneta Azul +Bold Negrito +Bold Flash Clarão forte +Both Ambos +Bottom Parte Inferior +Bounce Salto +Box Caixa +Box In Caixa para dentro +Box Out Caixa para fora +Box and Whisker Caixa e Bigodes +Brightness Brilho +Brightness {:+}% Brilho {:+}% +Bring Forward Avançar +Bring to Front Trazer para Frente +Bring\nForward Avançar +Browsed at a kiosk (full screen) Exibido em quiosque (tela inteira) +Browsed by an individual (window) Exibido por um indivíduo (janela) +Bubble Bolha +Bullets Marcadores +Burst Rajada +By Paragraph Por Parágrafo +Callout: Down Arrow Balão: seta para baixo +Callout: Left Arrow Balão: seta para a esquerda +Callout: Line Balão: linha +Callout: Right Arrow Balão: seta para a direita +Callout: Up Arrow Balão: seta para cima +Callouts Balões +Cameo Cameo +Camera capture is not available yet A captura de câmera ainda não está disponível +Cancel Cancelar +Capitalize Each Word Iniciar Cada Palavra Com Maiúscula +Caps Maiúsculas +Center Centralizar +Centered Centralizado +Change Case Alterar Maiúsculas e Minúsculas +Change Chart Type Alterar Tipo de Gráfico +Change Picture Alterar Imagem +Change Shape Alterar Forma +Change\nChart Type Alterar tipo de gráfico +Character Spacing Espaçamento entre Caracteres +Characters Caracteres +Chart Gráfico +Chart Data Dados do Gráfico +Chart Design Design de Gráfico +Chart Elements Elementos de Gráfico +Chart… Gráfico… +Check Accessibility Verificar Acessibilidade +Check\nAccessibility Verificar acessibilidade +Checkerboard Xadrez +Chevron Divisor +Choose a SmartArt Graphic Escolher um Gráfico SmartArt +Chord Corda +Circle Círculo +Circle In Círculo para dentro +Circle Out Círculo para fora +Clear All Formatting Limpar Toda a Formatação +Click a symbol to insert it at the insertion point. Clique em um símbolo para inseri-lo no ponto de inserção. +Click icon to add SmartArt graphic Clique no ícone para adicionar um gráfico SmartArt +Click icon to add chart Clique no ícone para adicionar um gráfico +Click icon to add media Clique no ícone para adicionar mídia +Click icon to add picture Clique no ícone para adicionar uma imagem +Click icon to add table Clique no ícone para adicionar uma tabela +Click to add first slide Clique para adicionar o primeiro slide +Click to add notes Clique para adicionar anotações +Click to add subtitle Clique para adicionar subtítulo +Click to add text Clique para adicionar texto +Click to add title Clique para adicionar título +Click to edit Master text styles Clique para editar os estilos de texto do slide mestre +Click to edit Master title style Clique para editar o estilo de título do slide mestre +Clock Relógio +Clockwise No sentido horário +Close Fechar +Close Master View Fechar Exibição Mestre +Close\nMaster View Fechar exibição mestre +Cloud Nuvem +Clustered Bar Barra Agrupada +Clustered Column Coluna Agrupada +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Recolher a Faixa de Opções +Color Cor +Color Pulse Pulso de Cor +Colors Cores +Columns Colunas +Comb Pente +Combo Combinado +Command Palette Paleta de Comandos +Comment Comentário +Comments Comentários +Commits Confirmações +Community Links Links da Comunidade +Company Empresa +Complementary Color Cor Complementar +Connect Shapes Conectar Formas +Connection Sites Pontos de Conexão +Connector: Curved Conector: curvo +Connector: Elbow Conector: em cotovelo +Connector: Elbow (one bend) Conector: em cotovelo (uma dobra) +Content Conteúdo +Contrast Contraste +Contrast {:+}% Contraste {:+}% +Contributors Colaboradores +Conveyor Esteira +Copy Copiar +Corrections Correções +Couldn't save AutoRecover information: {e} Não foi possível salvar as informações de AutoRecuperação: {e} +Counter Clockwise No sentido anti-horário +Cover Cobrir +Create Criar +Crop Cortar +Crop 10% each side Cortar 10% de cada lado +Crop 20% each side Cortar 20% de cada lado +Crop to Shape Cortar pela Forma +Cross Cruz +Crush Esmagar +Ctrl+ Ctrl+ +Cube Cubo +Currency Moeda +Curtains Cortinas +Custom Personalizado +Custom Path Caminho Personalizado +Custom Show Apresentação Personalizada +Custom Show 1 Apresentação Personalizada 1 +Custom Shows Apresentações Personalizadas +Custom Slide Show Apresentação de Slides Personalizada +Custom\nShow Apresentação personalizada +Cut Recortar +Cylinder Cilindro +Dark Blue Azul Escuro +Dark Mode Modo Escuro +Dark Red Vermelho Escuro +Dark appearance Aparência escura +Dark\nMode Modo escuro +Darken Escurecer +Dash Traço +Dash Dot Traço e Ponto +Dashes Traços +Database Banco de Dados +Date Data +Date & Time Data e Hora +Date &\nTime Data e hora +Date and Time Data e Hora +Date and time Data e hora +Decagon Decágono +Decision Decisão +DeckCraft DeckCraft +Decrease Font Size Diminuir o Tamanho da Fonte +Decrease List Level Diminuir o Nível da Lista +Delay: Atraso: +Delete Excluir +Delete Columns Excluir Colunas +Delete Comment Excluir Comentário +Delete Layout Excluir Layout +Delete Rows Excluir Linhas +Delete Slide Excluir Slide +Delete Table Excluir Tabela +Delete Text Excluir Texto +Desaturate Dessaturar +Deselect Desmarcar +Design Design +Design Ideas Ideias de Design +Design\nIdeas Ideias de design +Deutsch Deutsch +Diagonal Stripe Faixa diagonal +Diamond Losango +Diamond In Losango para dentro +Diamond Out Losango para fora +Direction Direção +Disappear Desaparecer +Discard Recovered Presentations Descartar Apresentações Recuperadas +Display name Nome de exibição +Dissolve Dissolver +Dissolve In Dissolver para dentro +Dissolve Out Dissolver para fora +Distribute Distribuir +Distribute Columns Distribuir Colunas +Distribute Horizontally Distribuir Horizontalmente +Distribute Rows Distribuir Linhas +Distribute Vertically Distribuir Verticalmente +Division Sign Sinal de divisão +Do not Autofit Não ajustar automaticamente +Do you want to save the changes you made to {what}? Deseja salvar as alterações feitas em {what}? +Document Documento +Dodecagon Dodecágono +Don't Save Não Salvar +Don't show on title slide Não mostrar no slide de título +Done Concluído +Donut Rosca +Doors Portas +Double Brace Chave dupla +Double Bracket Colchete duplo +Double Wave Onda dupla +Doughnut Rosca +Down Para Baixo +Drape Drapeado +Draw Desenhar +Drop Shadow Rectangle Retângulo com Sombra +Duplicate Duplicar +Duplicate Selected Slides Duplicar Slides Selecionados +Duplicate Slide Duplicar Slide +Duration: Duração: +Dynamic Content Conteúdo Dinâmico +Edit Editar +Edit Alt Text… Editar Texto Alternativo… +Edit Data Editar Dados +Edit Shape Editar Forma +Edit Text Editar Texto +Edit the data: first row = series names, first column = categories. Edite os dados: a primeira linha = nomes das séries, a primeira coluna = categorias. +Edit\nData Editar dados +Edit\nShape Editar forma +Editing Edição +Effect Options Opções de Efeito +Effect\nOptions Opções de efeito +Effects Efeitos +Email Address Endereço de Email +Email address: Endereço de email: +Emphasis Ênfase +End Fim +End Show Encerrar Apresentação +End of slide show Fim da apresentação de slides +End of slide show, click to exit. Fim da apresentação de slides. Clique para sair. +End trim (s): Corte no final (s): +English (United Kingdom) Inglês (Reino Unido) +English (United States) Inglês (Estados Unidos) +Enter Enter +Entrance Entrada +Equals Igual +Equation Equação +Equation Shapes Formas de Equação +Eraser Borracha +Escape Escape +Español Español +Exciting Chamativas +Exit Saída +Expand Expandir +Explosion: 14 Points Explosão: 14 pontas +Explosion: 8 Points Explosão: 8 pontas +Export Exportar +Export the presentation as: Exportar a apresentação como: +Exported {path} Exportado: {path} +Export… Exportar… +Fade Esmaecer +Fade in (s): Fade de entrada (s): +Fade out (s): Fade de saída (s): +Fall Over Cair +Ferris Wheel Roda-gigante +File Arquivo +Fill Preenchimento +Fill & Line Preenchimento e Linha +Fill Color Cor de Preenchimento +Filled Radar Radar Preenchido +Find… Localizar… +First Primeiro +First Column Primeira Coluna +First Slide Primeiro Slide +First commit Primeira confirmação +Fit Ajustar +Fit slide to current window Ajustar o slide à janela atual +Fit to Window Ajustar à Janela +Fit to\nWindow Ajustar à janela +Flash Clarão +Flip Virar +Flip Horizontal Virar Horizontalmente +Flip Vertical Virar Verticalmente +Float In Flutuar para dentro +Float Out Flutuar para fora +Flowchart Fluxograma +Flowchart: Alternate Process Fluxograma: Processo Alternativo +Flowchart: Card Fluxograma: Cartão +Flowchart: Collate Fluxograma: Compilação +Flowchart: Connector Fluxograma: Conector +Flowchart: Data Fluxograma: Dados +Flowchart: Decision Fluxograma: Decisão +Flowchart: Delay Fluxograma: Atraso +Flowchart: Direct Access Storage Fluxograma: Armazenamento de Acesso Direto +Flowchart: Display Fluxograma: Tela +Flowchart: Document Fluxograma: Documento +Flowchart: Extract Fluxograma: Extração +Flowchart: Internal Storage Fluxograma: Armazenamento Interno +Flowchart: Magnetic Disk Fluxograma: Disco Magnético +Flowchart: Manual Input Fluxograma: Entrada Manual +Flowchart: Manual Operation Fluxograma: Operação Manual +Flowchart: Merge Fluxograma: Mesclagem +Flowchart: Multidocument Fluxograma: Multidocumento +Flowchart: Off-page Connector Fluxograma: Conector Fora da Página +Flowchart: Or Fluxograma: Ou +Flowchart: Predefined Process Fluxograma: Processo Predefinido +Flowchart: Preparation Fluxograma: Preparação +Flowchart: Process Fluxograma: Processo +Flowchart: Punched Tape Fluxograma: Fita Perfurada +Flowchart: Sequential Access Storage Fluxograma: Armazenamento de Acesso Sequencial +Flowchart: Sort Fluxograma: Classificação +Flowchart: Stored Data Fluxograma: Dados Armazenados +Flowchart: Summing Junction Fluxograma: Junção de Soma +Flowchart: Terminator Fluxograma: Início/Fim +Fly In Entrar voando +Fly Out Sair voando +Fly Through Voar através +Folded Corner Canto Dobrado +Follow the layout Conforme o layout +Followed Hyperlink Hiperlink Visitado +Font Fonte +Font Color Cor da Fonte +Font Size Tamanho da Fonte +Fonts Fontes +Footer Rodapé +Foreground Primeiro Plano +Format Formato +Format Background Formatar Plano de Fundo +Format Background… Formatar Plano de Fundo… +Format Painter Pincel de Formatação +Format Painter (double-click to keep it on) Pincel de Formatação (clique duplo para mantê-lo ativo) +Format Pane Painel de Formato +Format Shape Formatar Forma +Format Shape… Formatar Forma… +Format\nBackground Formatar plano de fundo +Format\nPane Painel de formato +Formatting State Estado de Formatação +Fracture Fratura +Frame Moldura +Français Français +Freeform Forma Livre +From De +From Beginning Do Início +From Bottom De Baixo +From Bottom Left De Baixo à Esquerda +From Bottom Right De Baixo à Direita +From Current Slide Do Slide Atual +From Left Da Esquerda +From Right Da Direita +From Top De Cima +From Top Left De Cima à Esquerda +From Top Right De Cima à Direita +From bottom left De baixo à esquerda +From bottom right De baixo à direita +From center Do centro +From top left De cima à esquerda +From top right De cima à direita +From\nBeginning Do início +From\nCurrent Slide Do slide atual +Full Completo +Full Page Slides Slides em Página Inteira +Funnel Funil +Gallery Galeria +General Geral +Get Text Obter Texto +Glitter Cintilância +Glow Brilho +Go to Ir para +Go to Slide Ir para o Slide +Grab bag Sortido +Gradient fill Preenchimento com Gradiente +Gradient stops Pontos de gradiente +Gradient… Gradiente… +Grayscale Tons de Cinza +Greek Grego +Green Verde +Gridlines Linhas de Grade +Group Agrupar +Group Objects Agrupar Objetos +Grow & Turn Aumentar e Girar +Grow/Shrink Aumentar/Diminuir +Guides Guias +Half Metade +Half Frame Meia Moldura +Handout Master Slide Mestre da Apostila +Handout Master (coming soon) Slide Mestre da Apostila (em breve) +Handout\nMaster Slide Mestre da apostila +Handouts (1 slide per page) Apostilas (1 slide por página) +Handouts (2 slides per page) Apostilas (2 slides por página) +Handouts (3 slides per page) Apostilas (3 slides por página) +Handouts (4 slides per page) Apostilas (4 slides por página) +Handouts (6 slides per page) Apostilas (6 slides por página) +Handouts (9 slides per page) Apostilas (9 slides por página) +Header Cabeçalho +Header & Footer Cabeçalho e Rodapé +Header &\nFooter Cabeçalho e rodapé +Header Row Linha de Cabeçalho +Header and Footer Cabeçalho e Rodapé +Header and Footer… Cabeçalho e Rodapé… +Heart Coração +Height Altura +Height (in): Altura (pol): +Height: Altura: +Help Ajuda +Heptagon Heptágono +Hexagon Hexágono +Hide All Ocultar Tudo +Hide Background Graphics Ocultar Elementos Gráficos de Tela de Fundo +Hide During Show Ocultar Durante a Apresentação +Hide Slide Ocultar Slide +Hide background graphics Ocultar elementos gráficos de tela de fundo +Hide\nSlide Ocultar slide +Hierarchy Hierarquia +High Alta +Highlighter Marca-Textos +Histogram Histograma +Home Início +Honeycomb Favo de Mel +Horizontal Horizontal +Horz In Horizontal para dentro +Horz Out Horizontal para fora +How would you describe this object and its context to someone who is blind or has low vision? Como você descreveria este objeto e seu contexto para alguém cego ou com baixa visão? +Hyperlink Hiperlink +Icons Ícones +In Para dentro +In Bounce Para dentro com salto +Include hidden slides Incluir slides ocultos +Increase Font Size Aumentar o Tamanho da Fonte +Increase List Level Aumentar o Nível da Lista +Ink to Math Tinta para Matemática +Ink to Math (coming soon) Tinta para Matemática (em breve) +Ink to Shape Tinta para Forma +Ink to Shape (coming soon) Tinta para Forma (em breve) +Ink to Text Tinta para Texto +Ink to Text (coming soon) Tinta para Texto (em breve) +Ink to\nMath Tinta para matemática +Ink to\nShape Tinta para forma +Ink to\nText Tinta para texto +Inner Interna +Insert Inserir +Insert Above Inserir Acima +Insert Below Inserir Abaixo +Insert Hyperlink Inserir Hiperlink +Insert Layout Inserir Layout +Insert Left Inserir à Esquerda +Insert Placeholder Inserir Espaço Reservado +Insert Right Inserir à Direita +Insert Table Inserir Tabela +Insert Table… Inserir Tabela… +Insert picture from file… Inserir imagem do arquivo… +Insert\nAbove Inserir acima +Insert\nBelow Inserir abaixo +Insert\nLayout Inserir layout +Insert\nLeft Inserir à esquerda +Insert\nPlaceholder Inserir espaço reservado +Insert\nRight Inserir à direita +Inspect Presentation Inspecionar Apresentação +Inspect Shape Inspecionar Forma +Inspect Slide Inspecionar Slide +Interface Language Idioma da Interface +Interface language: Idioma da interface: +Interface size Tamanho da interface +Isosceles Triangle Triângulo Isósceles +Italiano Italiano +Italic Itálico +JPEG image (current slide) Imagem JPEG (slide atual) +Join our community on Discord Junte-se à nossa comunidade no Discord +Join the ArtCraft community on Discord Junte-se à comunidade ArtCraft no Discord +Justify Justificar +L-Shape Forma de L +Language Idioma +Last Último +Last Column Última Coluna +Last Slide Último Slide +Last commit Última confirmação +Layout Layout +Learn More Saiba Mais +Learn\nMore Saiba mais +Ledger Paper (11x17 in) Papel Ledger (11×17 pol) +Left Esquerda +Left Brace Chave Esquerda +Left Bracket Colchete Esquerdo +Letter Paper (8.5x11 in) Papel Carta (8,5×11 pol) +Liberation Serif Liberation Serif +Light Blue Azul Claro +Light Green Verde Claro +Light/Dark appearance Aparência clara/escura +Lighten Clarear +Lightning Relâmpago +Lightning Bolt Raio +Line Linha +Line Color Cor da Linha +Line Spacing Espaçamento de Linha +Line Spacing Options… Opções de Espaçamento de Linha… +Line delta Diferença de linhas +Line spacing (lines): Espaçamento de linha (linhas): +Line with Markers Linha com Marcadores +Linear Linear +Lines Linhas +Lines +/− Linhas +/− +Lines added Linhas adicionadas +Lines deleted Linhas removidas +Link Link +Link… Link… +List Commands Lista de Comandos +Lock Bloquear +Long Dash Traço longo +Long Dash Dot Traço longo e ponto +Loop continuously until 'Esc' Repetir continuamente até 'Esc' +Loop until Stopped Repetir até Parar +Loops Laços +Loose Frouxo +Low Baixa +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 a equipe ArtCraft e os colaboradores do DeckCraft +Margins (pt) Margens (pt) +Mark as decorative Marcar como decorativo +Mark selected text as: Marcar o texto selecionado como: +Math Matemática +Matrix Matriz +Maximize content (else ensure fit) Maximizar o conteúdo (senão ajustar) +Media Mídia +Media Info Informações de Mídia +Medium Média +Merge Cells Mesclar Células +Merge Shapes Combinar Formas +Merge\nCells Mesclar células +Merge\nShapes Combinar formas +Merged PRs Solicitações de pull mescladas +Middle Meio +Minus Sign Sinal de menos +Model Modelo +Models Modelos +Moon Lua +More Colors… # Mais Cores… # +Morph Transformação +Motion Movimento +Motion Paths Trajetórias de Movimento +Move Mover +Move Down Mover para Baixo +Move Insertion Point Mover Ponto de Inserção +Move Section Mover Seção +Move Section Down Mover Seção para Baixo +Move Section Up Mover Seção para Cima +Move Slide Mover Slide +Move Up Mover para Cima +Multiplication Sign Sinal de multiplicação +Multiply Multiplicação +Mute Silenciar +Name Nome +Name (A–Z) Nome (A–Z) +Name: Nome: +New Comment Novo Comentário +New Presentation Nova Apresentação +New Slide Novo Slide +New Slide (⇧⌘N) Novo Slide (⇧⌘N) +New presentation Nova apresentação +New show name: Nome da nova apresentação: +New\nComment Novo comentário +New\nSlide Novo slide +Next Próximo +Next Slide Próximo Slide +Next Window Próxima Janela +Next ▶ Próximo ▶ +No Color Sem Cor +No Fill Sem Preenchimento +No Glow Sem Brilho +No Outline Sem Contorno +No Reflection Sem Reflexo +No Shadow Sem Sombra +No Soft Edges Sem Bordas Suaves +No accessibility issues found. People with disabilities should not have difficulty reading this document. Nenhum problema de acessibilidade encontrado. Pessoas com deficiência não devem ter dificuldade para ler este documento. +No comments on this slide. Não há comentários neste slide. +No contributor data was built into this copy. Nenhum dado de colaboradores foi incluído nesta cópia. +No fill Sem preenchimento +No line Sem linha +No model credits were built into this copy. Nenhum dado dos modelos utilizados foi incluído nesta cópia. +No notes. Não há anotações. +No sound: {err} Sem som: {err} +None Nenhum +Normal Normal +Not Equal Diferente de +Not allowed Não permitido +Notes Anotações +Notes Master Slide Mestre das Anotações +Notes Master (coming soon) Slide Mestre das Anotações (em breve) +Notes Page Página de Anotações +Notes Pages Páginas de Anotações +Notes\nMaster Slide Mestre das anotações +Notes\nPage Página de anotações +Nudge Deslocar +Number of columns: Número de colunas: +Number of rows: Número de linhas: +Numbering Numeração +Object Color Cor do Objeto +Objects Objetos +Octagon Octógono +On Click Ao Clicar +On Click of {name} Ao clicar em {name} +On Click of… (none) Ao clicar em… (nenhum) +On Mouse Click Ao Clicar com o Mouse +On-screen Show (16:10) Exibição na Tela (16:10) +Open Data Abrir Dados +Open Dialog Abrir Caixa de Diálogo +Open Recovered Presentations Abrir Apresentações Recuperadas +Open the sample deck Abrir a apresentação de exemplo +Open… Abrir… +Orange Laranja +Orbit Órbita +Order Objects Ordenar Objetos +Origami Origami +Out Para fora +Out Bounce Para fora com salto +Outer Externa +Outline Estrutura de Tópicos +Outline (.txt) Estrutura de Tópicos (.txt) +Outline View Exibição de Estrutura de Tópicos +Outline\nView Estrutura de tópicos +Oval Oval +Oval ends Pontas ovais +Overhead Projetor +PDF document (.pdf) Documento PDF (.pdf) +PNG images (all slides) Imagens PNG (todos os slides) +PNG images (current slide) Imagens PNG (slide atual) +PRs Solicitações de pull +Page Curl Dobra de página +Page Setup… Configurar Página… +PageDown PageDown +PageUp PageUp +Pan Panorâmica +Pane Painel +Paragraph Parágrafo +Paragraph… Parágrafo… +Parallelogram Paralelogramo +Pareto Pareto +Partial Circle Círculo Parcial +Particles Partículas +Paste Colar +Paste (⌘V) Colar (⌘V) +Paste Formatting Colar Formatação +Paste and Match Formatting Colar Combinando a Formatação +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Cole ou digite uma estrutura de tópicos. Linhas sem recuo tornam-se títulos de slides; linhas com recuo de tabulação tornam-se marcadores. +Pasted image.png Imagem colada.png +Path Caminho +Pattern fill Preenchimento com Padrão +Pause Pausar +Peek In Espiar +Peel Off Descascar +Pencil Lápis +Pentagon Pentágono +Perspective Perspectiva +Pick a graphic; type one item per line. Escolha um gráfico; digite um item por linha. +Pick a look for your slides. Ideas are generated on your device. Escolha uma aparência para seus slides. As ideias são geradas no seu dispositivo. +Picture Imagem +Picture Format Formato da Imagem +Picture Styles Estilos de Imagem +Picture from File… Imagem do Arquivo… +Picture or texture fill Preenchimento com Imagem ou Textura +Picture\nStyles Estilos de imagem +Pictures Imagens +Pie Pizza +Pin Fixar +Placeholder colour Cor do espaço reservado +Plan\nBuild\nLaunch Planejar\nConstruir\nLançar +Plaque Placa +Play Reproduzir +Play Across Slides Reproduzir em Vários Slides +Play Full Screen Reproduzir em Tela Inteira +Play Narrations Reproduzir Narrações +Play from Current Slide Reproduzir do Slide Atual +Play from Start Reproduzir do Início +Play from Start (F5) Reproduzir do Início (F5) +Play from\nCurrent Slide Reproduzir do slide atual +Play from\nStart Reproduzir do início +Play/Pause Reproduzir/Pausar +Playback Reprodução +Plus Mais +Plus In Mais para dentro +Plus Out Mais para fora +Plus Sign Sinal de adição +Portrait (9:16) Retrato (9:16) +Português Português +Position Posição +Position Objects Posicionar Objetos +Position and Size Posição e Tamanho +Post Publicar +Poster Frame Imagem de Capa +PowerPoint Presentation (.pptx) Apresentação do PowerPoint (.pptx) +Preferences Preferências +Preferences… Preferências… +Presentation Apresentação +Presentations Apresentações +Presentations and slide shows, rebuilt from scratch in pure Rust. Apresentações e exibições de slides, reconstruídas do zero em Rust puro. +Presented by a speaker (full screen) Apresentada por um orador (tela inteira) +Presenter View Modo do Apresentador +Presenter View — DeckCraft Modo do Apresentador — DeckCraft +Presenter\nView Modo do Apresentador +Preset gradients Gradientes predefinidos +Prestige Prestígio +Preview Visualização +Previous Slide Slide Anterior +Print layout: Layout de impressão: +Properties Propriedades +Pulse Pulso +Punctuation Pontuação +Purple Roxo +Push Empurrar +Pyramid Pirâmide +Quick Styles Estilos Rápidos +Quick\nStyles Estilos rápidos +Radar Radar +Radial Radial +Random Aleatório +Random Bars Barras Aleatórias +Reading View Modo de Leitura +Reading\nView Modo de leitura +Real name Nome real +Recent Recente +Record Gravar +Recording narration needs audio capture (coming soon) A gravação de narração requer captura de áudio (em breve) +Recovered Presentations Apresentações Recuperadas +Recovered {} from the last session Recuperado {} da última sessão +Rectangle Retângulo +Rectangle: Diagonal Corners Rounded Retângulo: cantos diagonais arredondados +Rectangle: Diagonal Corners Snipped Retângulo: cantos diagonais chanfrados +Rectangle: Rounded Corners Retângulo: cantos arredondados +Rectangle: Single Corner Rounded Retângulo: um canto arredondado +Rectangle: Single Corner Snipped Retângulo: um canto chanfrado +Rectangle: Top Corners One Rounded and One Snipped Retângulo: cantos superiores, um arredondado e outro chanfrado +Rectangle: Top Corners Rounded Retângulo: cantos superiores arredondados +Rectangle: Top Corners Snipped Retângulo: cantos superiores chanfrados +Rectangles Retângulos +Rectangular Retangular +Red Vermelho +Red Pen Caneta Vermelha +Redo Refazer +Redo (⌘Y) Refazer (⌘Y) +Reflected Rounded Rectangle Retângulo Arredondado com Reflexo +Reflection Reflexo +Regroup Reagrupar +Regular Pentagon Pentágono Regular +Rehearse Timings Ensaio de Intervalos +Rehearse\nTimings Ensaio de intervalos +Remove Remover +Remove All Animations Remover Todas as Animações +Remove All Sections Remover Todas as Seções +Remove Animation Remover Animação +Remove Background Remover Tela de Fundo +Remove Background (coming soon) Remover Tela de Fundo (em breve) +Remove Section Remover Seção +Remove Section & Slides Remover Seção e Slides +Remove stop Remover ponto +Remove\nBackground Remover tela de fundo +Rename Renomear +Rename Layout Renomear Layout +Rename Section Renomear Seção +Rename Section… Renomear Seção… +Rename Slide Renomear Slide +Rename… Renomear… +Render Slide Renderizar Slide +Reopen Reabrir +Reorder Animation Reordenar Animação +Reorder Objects Reordenar Objetos +Replace straight quotes with smart quotes Substituir aspas retas por aspas tipográficas +Reply Responder +Reply… Responder… +Reset Redefinir +Reset Background Redefinir Tela de Fundo +Reset Crop Redefinir Corte +Reset Effects Redefinir Efeitos +Reset Picture Redefinir Imagem +Reset Slide Redefinir Slide +Reset Slide Background Redefinir Tela de Fundo do Slide +Resize shape to fit text Redimensionar a forma para ajustar o texto +Resolve Marcar como resolvido +Resolve Thread Resolver Discussão +Return Retornar +Reveal Revelar +Reverse the order Inverter a ordem +Revert Reverter +Review Revisão +Rewind after Playing Rebobinar após a Reprodução +Ribbon Tab Guia da Faixa de Opções +Ribbon: Tilted Down Faixa: inclinada para baixo +Ribbon: Tilted Up Faixa: inclinada para cima +Right Direita +Right Brace Chave Direita +Right Bracket Colchete Direito +Right Triangle Triângulo Retângulo +Right-to-Left Text Direction Direção do Texto da Direita para a Esquerda +Ring Anel +Ripple Ondulação +Rise Up Erguer-se +Rotate Girar +Rotate Left 90° Girar 90° para a Esquerda +Rotate Right 90° Girar 90° para a Direita +Rotate all text 270° Girar todo o texto 270° +Rotate all text 90° Girar todo o texto 90° +Rotate with shape Girar com a forma +Rotation Rotação +Round Dot Ponto Redondo +Rounded Diagonal Corner Canto Diagonal Arredondado +Ruler Régua +Saturation Saturação +Saturation {}% Saturação {}% +Save Salvar +Save (⌘S) Salvar (⌘S) +Save As… Salvar Como… +Save AutoRecover Information Salvar Informações de AutoRecuperação +Save as Template… Salvar como Modelo… +Save to Data Salvar em Dados +Saved Salvo +Saved {path} Salvo: {path} +Scatter Dispersão +ScreenTip: Dica de Tela: +Screenshot Captura de Tela +Screenshot (not available yet) Captura de Tela (ainda não disponível) +Scroll: Horizontal Pergaminho: Horizontal +Scroll: Vertical Pergaminho: Vertical +Search commands (⇧⌘P) Pesquisar Comandos (⇧⌘P) +Search commands… Pesquisar Comandos… +Section Seção +Seek Buscar Posição +Select Selecionar +Select All Selecionar Tudo +Select All Text Selecionar Todo o Texto +Select Cells Selecionar Células +Select Objects Selecionar Objetos +Select Paragraph Selecionar Parágrafo +Select Slides Selecionar Slides +Select Text Selecionar Texto +Select Word Selecionar Palavra +Select a chart first. Selecione primeiro um gráfico. +Select a shape to format it. Selecione uma forma para formatá-la. +Select an object on the slide and add an animation from the Animations tab. Selecione um objeto no slide e adicione uma animação na guia Animações. +Selection Seleção +Selection Pane Painel de Seleção +Selection Pane… Painel de Seleção… +Selection\nPane Painel de seleção +Send Backward Enviar para Trás +Send to Back Enviar para o Fundo +Send\nBackward Enviar para trás +Sentence case. Tipo frase. +Set Text Definir Texto +Set Up Show… Configurar Apresentação… +Set Up Slide Show Configurar Apresentação de Slides +Set Up Slide Show… Configurar Apresentação de Slides… +Set Up\nSlide Show Configurar apresentação de slides +Set as Default Shape Definir como Forma Padrão +Shading Sombreamento +Shadow Sombra +Shape Forma +Shape Effects Efeitos da Forma +Shape Fill Preenchimento da Forma +Shape Format Formato da Forma +Shape Gallery Galeria de Formas +Shape Outline Contorno da Forma +Shape Styles Estilos da Forma +Shape {} Forma {} +Shape\nStyles Estilos da forma +Shapes Formas +Shift+ Shift+ +Shift+F9 Shift+F9 +Show Mostrar +Show All Mostrar Tudo +Show Comments Mostrar Comentários +Show Media Controls Mostrar Controles de Mídia +Show Slide Mostrar Slide +Show smart guides Mostrar guias inteligentes +Show type Tipo de apresentação +Show without animation Mostrar sem animação +Show without narration Mostrar sem narração +Show/Hide Mostrar/Ocultar +Show\nComments Mostrar comentários +Shred Fragmentar +Shrink & Turn Diminuir e Girar +Shrink text on overflow Reduzir o texto se exceder +Simple Frame, White Moldura Simples, Branca +Size Tamanho +Size & Properties Tamanho e Propriedades +Slide Master Slide Mestre +Slide Number Número do Slide +Slide Show Apresentação de Slides +Slide Size Tamanho do Slide +Slide Sorter Classificador de Slides +Slide number Número do slide +Slide timings recorded. Intervalos dos slides gravados. +Slide {:02}:{:04.1} Total {:02}:{:02} Slide {:02}:{:04.1} Total {:02}:{:02} +Slide {} of {} Slide {} de {} +Slide {}: {}{} Slide {}: {}{} +Slide {}: “{w}” Slide {}: «{w}» +Slide\nMaster Slide mestre +Slide\nNumber Número do slide +Slide\nSize Tamanho do slide +Slide\nSorter Classificador de slides +Slides (e.g. 1,3,5): Slides (por exemplo, 1,3,5): +Slides from Outline Slides a Partir da Estrutura de Tópicos +Slides from Outline… Slides a Partir da Estrutura de Tópicos… +Slides sized for: Dimensionar slides para: +SmartArt SmartArt +Smile Sorriso +Smiley Face Carinha Sorridente +Smoothly Suavemente +Smoothly Left Suavemente à esquerda +Smoothly Right Suavemente à direita +Snap objects to grid Encaixar objetos na grade +Soft Edge Rectangle Retângulo com Bordas Suaves +Soft Edges Bordas Suaves +Solid Sólido +Solid fill Preenchimento sólido +Solid line Linha sólida +Sort Classificar +Source on GitHub Código-fonte no GitHub +Space Espaço +Spacing after (pt): Espaçamento depois (pt): +Spacing before (pt): Espaçamento antes (pt): +Special — hanging (in): Especial — deslocamento (pol): +Speech Fala +Speech Bubble: Oval Balão de Fala: Oval +Speech Bubble: Rectangle Balão de Fala: Retângulo +Speech Bubble: Rectangle with Corners Rounded Balão de Fala: Retângulo com Cantos Arredondados +Spelling Ortografia +Spin Girar +Spinner Giro Contínuo +Split Dividir +Split Cells Dividir Células +Split\nCells Dividir células +Square Quadrado +Square (1:1) Quadrado (1:1) +Square Dot Ponto Quadrado +Stacked Empilhado +Stacked Area Área Empilhada +Stacked Bar Barra Empilhada +Stacked Column Coluna Empilhada +Stacked Line Linha Empilhada +Standard (4:3) Padrão (4:3) +Standard Colors Cores Padrão +Star Estrela +Star: 10 Points Estrela: 10 pontas +Star: 12 Points Estrela: 12 pontas +Star: 16 Points Estrela: 16 pontas +Star: 24 Points Estrela: 24 pontas +Star: 32 Points Estrela: 32 pontas +Star: 4 Points Estrela: 4 pontas +Star: 5 Points Estrela: 5 pontas +Star: 6 Points Estrela: 6 pontas +Star: 7 Points Estrela: 7 pontas +Star: 8 Points Estrela: 8 pontas +Stars and Banners Estrelas e Faixas +Start After Previous Após a Anterior +Start Automatically Automaticamente +Start On Click Ao Clicar +Start With Previous Com a Anterior +Start a conversation Inicie uma conversa +Start time (s): Horário de início (s): +Start: Início: +Stealth end Ponta de seta +Stock Ações +Stop Parar +Stop Editing Text Parar de Editar Texto +Strikethrough Tachado +Strips Faixas +Style {i} Estilo {i} +Subscript Subscrito +Subtle Sutis +Sun Sol +Sunburst Raios de Sol +Superscript Sobrescrito +Surface Superfície +Switch Alternar +Swivel Pivotante +Symbol Símbolo +System language Idioma do sistema +Tab Tabulação +Table Tabela +Table Design Design de Tabela +Table Style Options Opções de Estilo de Tabela +Table Styles Estilos de Tabela +Table… Tabela… +Task Pane Painel de Tarefas +Teardrop Gota +Teeter Balançar +Text Texto +Text Box Caixa de Texto +Text Box Margins Margens da Caixa de Texto +Text Direction Direção do Texto +Text Effects Efeitos de Texto +Text Fill Preenchimento do Texto +Text Highlight Color Cor de Realce do Texto +Text Options Opções de Texto +Text Outline Contorno do Texto +Text Shadow Sombra do Texto +Text/Background - Dark 1 Texto/Tela de Fundo - Escuro 1 +Text/Background - Dark 2 Texto/Tela de Fundo - Escuro 2 +Text/Background - Light 1 Texto/Tela de Fundo - Claro 1 +Text/Background - Light 2 Texto/Tela de Fundo - Claro 2 +Text\nBox Caixa de texto +The spelling check is complete. No issues found. A verificação ortográfica está concluída. Nenhum problema encontrado. +Theme Colors Cores do Tema +Theme Gallery Galeria de Temas +Themes Temas +Thesaurus Dicionário de Sinônimos +Thesaurus (coming soon) Dicionário de Sinônimos (em breve) +This Document Este Documento +Thought Pensamento +Thought Bubble: Cloud Nuvem de Pensamento +Through Black Através do Preto +Tight Justo +Timing Intervalos +Top Parte Superior +Total Row Linha de Totais +Transition Transição +Transition Gallery Galeria de Transições +Transitions Transições +Translate Traduzir +Translation needs a language model (not bundled) A tradução precisa de um modelo de linguagem (não incluído) +Transparency Transparência +Trapezoid Trapézio +Treemap Treemap +Triangle Triângulo +Trigger Gatilho +Trim Cortar +Trim Media Cortar Mídia +Turns Voltas +Type Tipo +Type Text Digitar Texto +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Digite uma equação em forma linear (por exemplo, a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Descobrir +Underline Sublinhado +Undo Desfazer +Undo (⌘Z) Desfazer (⌘Z) +Ungroup Desagrupar +Up Para Cima +Use Timings Usar Intervalos +Use timings, if present Usar intervalos, se houver +Username Nome de usuário +Version Versão +Version {} Versão {} +Vert In Vertical para dentro +Vert Out Vertical para fora +Vertical Vertical +Vertical alignment Alinhamento vertical +Very Loose Muito frouxo +Very Tight Muito justo +Video Vídeo +Video from File… Vídeo do Arquivo… +View Exibição +Volume Volume +Vortex Vórtice +Waterfall Cascata +Wave Onda +Web Page or File Página da Web ou Arquivo +Wedge Cunha +Weight Espessura +Wheel Roda +Widescreen (13.333x7.5 in) Panorâmico (13,333×7,5 pol) +Widescreen (16:9) Panorâmico (16:9) +Width Largura +Width (in): Largura (pol): +Width: Largura: +Width: Largura: +Wind Vento +Window Janela +Wipe Varredura +With Previous Com a Anterior +WordArt WordArt +WordArt style {} Estilo de WordArt {} +Words Palavras +Wrap Text in Shape Ajustar Texto na Forma +Wrap text in shape Ajustar texto na forma +Yellow Amarelo +Your changes will be lost if you don't save them. Suas alterações serão perdidas se você não salvá-las. +Your name (comments): Seu nome (comentários): +Zoom Zoom +Zoom In Ampliar +Zoom Out Reduzir +Zoom… Zoom… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Aceitar Revisão +Action Settings Configurações de Ação +Add Font Adicionar Fonte +Add Guide Adicionar Guia +Add Point Adicionar Ponto +Add Shape Adicionar Forma +Add to Dictionary Adicionar ao Dicionário +Align Cell Text Alinhar Texto da Célula +Apply Design Idea Aplicar Ideia de Design +Arrow: Circular Seta: circular +Arrow: Circular Counter-clockwise Seta: circular no sentido anti-horário +Arrow: Circular Two-headed Seta: circular de duas pontas +Arrow: Curved Down Seta: curva para baixo +Arrow: Curved Left Seta: curva para a esquerda +Arrow: Curved Right Seta: curva para a direita +Arrow: Curved Up Seta: curva para cima +Arrow: Swoosh Seta: swoosh +Artistic Effects Efeitos Artísticos +AutoCorrect Options Opções de AutoCorreção +Bean Feijão +Borders Bordas +Bounce Left Salto para a esquerda +Bounce Right Salto para a direita +Browse for Themes… Procurar Temas… +Callout: Bent Line Balão: linha dobrada +Callout: Bent Line with Accent Bar Balão: linha dobrada com barra de realce +Callout: Bent Line with Border and Accent Bar Balão: linha dobrada com contorno e barra de realce +Callout: Bent Line with No Border Balão: linha dobrada sem contorno +Callout: Double Bent Line Balão: linha com duas dobras +Callout: Double Bent Line with Accent Bar Balão: linha com duas dobras e barra de realce +Callout: Double Bent Line with Border and Accent Bar Balão: linha com duas dobras com contorno e barra de realce +Callout: Double Bent Line with No Border Balão: linha com duas dobras sem contorno +Callout: Left-Right Arrow Balão: seta esquerda-direita +Callout: Line with Accent Bar Balão: linha com barra de realce +Callout: Line with Border and Accent Bar Balão: linha com contorno e barra de realce +Callout: Line with No Border Balão: linha sem contorno +Callout: Quad Arrow Balão: seta de quatro pontas +Callout: Up-Down Arrow Balão: seta cima-baixo +Cell Margins Margens de Célula +Change Colors Alterar Cores +Change Layout Alterar Layout +Change Picture… Alterar imagem… +Change Spelling Alterar Ortografia +Chart Marker: Cross Lines Marcador de Gráfico: linhas em X +Chart Marker: Plus Lines Marcador de Gráfico: linhas em cruz +Chart Marker: Star Lines Marcador de Gráfico: linhas em estrela +Color At Cor em +Commit Composition Confirmar Composição +Compare Comparar +Compare… Comparar… +Compose Text Compor Texto +Compress Pictures Compactar Imagens +Contract Contrair +Convert to Shapes Converter em Formas +Convert to SmartArt Converter em SmartArt +Convert to Text Converter em Texto +Corner Tabs: Quarter Circles Abas de Canto: Quartos de Círculo +Corner Tabs: Squares Abas de Canto: Quadrados +Corner Tabs: Triangles Abas de Canto: Triângulos +Crescent Moon Lua Crescente +Curved Square Quadrado Curvo +Decaying Wave Onda Decrescente +Delete Guide Excluir Guia +Delete Point Excluir Ponto +Demote Rebaixar +Diagonal Down Right Diagonal para baixo à direita +Diagonal Up Right Diagonal para cima à direita +Draw Table Desenhar Tabela +dropped file arquivo arrastado +Edit Photo Album… Editar Álbum de Fotos… +Edit Points Editar pontos +Edit SmartArt Text Editar Texto do SmartArt +End Review Encerrar Revisão +Find Localizar +Flowchart: Offline Storage Fluxograma: Armazenamento Offline +Fonts in Presentation Fontes na Apresentação +Font… Fonte… +Football Bola de Futebol Americano +Gear: 6 Teeth Engrenagem: 6 dentes +Gear: 9 Teeth Engrenagem: 9 dentes +Grid and Guides Grade e guias +Grid Options… Opções de Grade… +Handout Placeholders Espaços Reservados da Apostila +Heartbeat Batimento Cardíaco +Hex D Hexágono para baixo +Hex L Hexágono à esquerda +Hex R Hexágono à direita +Hex U Hexágono para cima +Horizontal Figure 8 Oito Horizontal +i. ii. iii. i. ii. iii. +Icon Gallery Galeria de Ícones +Info Informações +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Tinta para forma: transforma linhas, retângulos, ovais e triângulos desenhados em formas +Insert Picture in SmartArt Inserir Imagem no SmartArt +Insert Picture in SmartArt… Inserir Imagem no SmartArt… +Insert Synonym Inserir Sinônimo +Layout Placeholders Espaços Reservados do Layout +Line: Rising Linha: ascendente +Loop de Loop Looping +Move Guide Mover Guia +Move Handle Mover Alça +Move Point Mover Ponto +Neutron Nêutron +New Window Nova Janela +Next Comment Próximo Comentário +No comments. Sem comentários. +no presentation open Nenhuma apresentação aberta +no slides Nenhum slide +no text insertion point Nenhum ponto de inserção de texto +Notes Placeholders Espaços Reservados das Anotações +nothing selected Nada selecionado +nothing to redo Nada para refazer +nothing to undo Nada para desfazer +Open Abrir +Particles In Partículas de entrada +Particles Out Partículas de saída +Paste Special Colar Especial +Paste Special… Colar Especial… +Peanut Amendoim +Peek Out Espiar para fora +Photo Album… Álbum de Fotos… +Pick a design for this slide. Ideas are generated on your device. Escolha um design para este slide. As ideias são geradas no seu dispositivo. +Picture Style Gallery Galeria de Estilos de Imagem +Point Type Tipo de Ponto +Points Pontos +Preserve Preservar +Preview Animations Visualizar Animações +Previous Comment Comentário Anterior +Print Imprimir +Print… Imprimir… +Promote Promover +Quarter Wedge Quarto de Cunha +Quick Access Toolbar Barra de Ferramentas de Acesso Rápido +Recolor Recolorir +Recolor Gallery Galeria de Recoloração +Remove Shape Remover Forma +Replace Substituir +Replace Fonts Substituir Fontes +Replace… Substituir… +Rescan Installed Fonts Reexaminar Fontes Instaladas +Reuse Slides… Reutilizar Slides… +Revisions Revisões +Ribbon: Curved and Tilted Down Faixa: curva e inclinada para baixo +Ribbon: Curved and Tilted Up Faixa: curva e inclinada para cima +Ribbon: Left-Right Fold Faixa: dobra esquerda-direita +S Curve 1 Curva em S 1 +S Curve 2 Curva em S 2 +select text or a shape Selecione texto ou uma forma +select two or more objects Selecione dois ou mais objetos +Set Transparent Color Definir Cor Transparente +Set Zoom Definir Zoom +Sine Wave Onda Senoidal +Single L Simples à esquerda +Single R Simples à direita +Sink Down Afundar +size (pt) tamanho (pt) +Size and Position… Tamanho e posição… +SmartArt Styles Estilos de SmartArt +Smooth Corners Cantos Suaves +Sound Som +Spelling Dictionary Dicionário Ortográfico +Spiral Left Espiral para a esquerda +Spiral Right Espiral para a direita +Spring Mola +Stairs Down Escada para baixo +Starter Templates Modelos Iniciais +Strips In Faixas de entrada +Strips Out Faixas de saída +Swoosh Swoosh +Table Eraser Borracha de Tabela +Tabs… Tabulações… +Text Pane Painel de Texto +Text Transform Transformação do Texto +Text Transparency Transparência do Texto +tOGGLE cASE tOGGLE cASE +Trapezoid: Uneven Sides Trapézio: lados desiguais +unknown interface language Idioma de interface desconhecido +Unlock Desbloquear +Variant Gallery Galeria de Variações +Variants Variações +Vertical Figure 8 Oito Vertical +Zigzag Zigue-zague + (not checked) (não verificado) +4 Point Star Estrela de 4 Pontas +5 Point Star Estrela de 5 Pontas +6 Point Star Estrela de 6 Pontas +8 Point Star Estrela de 8 Pontas +{ch} Bullet {ch} Marcador +{f} (Body) {f} (Corpo) +{f} (Headings) {f} (Títulos) +{name}: DeckCraft can't open this kind of file {name}: o DeckCraft não pode abrir este tipo de arquivo +{n} Column{} {n} Coluna{} +{r} pt {r} pt +{r} pt glow Brilho de {r} pt +{w} pt {w} pt +{} ({} slides) {} ({} slides) +{} Slide Master Slide Mestre {} +{} contributors · {} commits Colaboradores: {} · Confirmações: {} +{} presentations {} apresentações +{}x{} Table Tabela {}×{} +“{}” is not available yet. «{}» ainda não está disponível. +−Bin −Intervalo +▶ Play All ▶ Reproduzir Tudo +◀ Previous ◀ Anterior +✏ on ✏ ativado diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv new file mode 100644 index 000000000..6ecfb71a8 --- /dev/null +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -0,0 +1,1408 @@ +# Russian interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Фиксированная дата (пустое поле = обновлять автоматически): + Footer text: Текст нижнего колонтитула: + Present Показать + pt пт + — Edited — Изменено +"Not Allowed" Symbol Знак «Не разрешено» +% of all commits % всех коммитов ++ New Comment + Новый комментарий ++ New Slide + Новый слайд ++ Row + Строка ++ Series + Ряд данных ++Bin +Интервал +100% Stacked Bar Нормированная линейчатая с накоплением +100% Stacked Column Нормированная гистограмма с накоплением +35mm Slides Слайды 35 мм +@ribbon:Home Главная +@ribbon:Insert Вставка +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{}: запросы на слияние: {}, коммитов: {}, строк: +{} / −{} (Δ {}), двоичных файлов: +{} / −{}, {} – {} +A3 Paper (297x420 mm) Бумага A3 (297x420 мм) +A4 Paper (210x297 mm) Бумага A4 (210x297 мм) +Aa Aa +Abc Abc +About О программе +About DeckCraft О DeckCraft +Accent 1 Акцент 1 +Accent 2 Акцент 2 +Accent 3 Акцент 3 +Accent 4 Акцент 4 +Accent 5 Акцент 5 +Accent 6 Акцент 6 +Accessibility Checker Проверка читаемости +Across Поперек +Action Действие +Action Button: Custom Кнопка действия: Настраиваемая +Action Button: Document Кнопка действия: Документ +Action Button: Get Information Кнопка действия: Сведения +Action Button: Go Back Кнопка действия: Назад +Action Button: Go Back or Previous Кнопка действия: Назад или предыдущий +Action Button: Go Forward or Next Кнопка действия: Вперед или следующий +Action Button: Go Home Кнопка действия: Домой +Action Button: Go to Beginning Кнопка действия: В начало +Action Button: Go to End Кнопка действия: В конец +Action Button: Help Кнопка действия: Справка +Action Button: Sound Кнопка действия: Звук +Action Button: Video Кнопка действия: Видео +Action Button: {k} Кнопка действия: {k} +Action Buttons Кнопки действий +Add Animation Добавить анимацию +Add Section Добавить раздел +Add\nAnimation Добавить анимацию +Address: Адрес: +Adjust Shape Изменить фигуру +After Previous После предыдущего +After: После: +Airplane Самолет +Align Выровнять +Align Bottom Выровнять по нижнему краю +Align Center Выровнять по центру +Align Left Выровнять по левому краю +Align Middle Выровнять по середине +Align Right Выровнять по правому краю +Align Text Выровнять текст +Align Top Выровнять по верхнему краю +Alt Text Замещающий текст +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Замещающий текст +An open-source, clean-room project. Not affiliated with Microsoft. Независимый проект с открытым исходным кодом. Не связан с Microsoft. +Angle Угол +Animation Gallery Галерея анимации +Animation Pane Область анимации +Animation Styles Стили анимации +Animation\nPane Область анимации +Animations Анимация +Animation Painter Формат по образцу анимации +Apply Animation Применить анимацию +Play/Pause GIF Воспроизвести/приостановить GIF +Animations on Slide Анимация на слайде +Appear Появление +Apply Применить +Apply To All Применить ко всем +Apply to All Применить ко всем +Apply\nTo All Применить ко всем +Arc Дуга +Arcs Дуги +Area С областями +Arrange Упорядочить +Arrow Стрелка +Arrow at end Стрелка в конце +Arrow at start Стрелка в начале +Arrow: Bent Стрелка: Изогнутая +Arrow: Bent-Up Стрелка: Изогнутая вверх +Arrow: Chevron Стрелка: Шеврон +Arrow: Down Стрелка: Вниз +Arrow: Left Стрелка: Влево +Arrow: Left-Right Стрелка: Влево-вправо +Arrow: Left-Right-Up Стрелка: Влево-вправо-вверх +Arrow: Left-Up Стрелка: Влево-вверх +Arrow: Notched Right Стрелка: Вправо с выемкой +Arrow: Pentagon Стрелка: Пятиугольник +Arrow: Quad Стрелка: Четырехсторонняя +Arrow: Right Стрелка: Вправо +Arrow: Striped Right Стрелка: Полосатая вправо +Arrow: U-Turn Стрелка: Разворот +Arrow: Up Стрелка: Вверх +Arrow: Up-Down Стрелка: Вверх-вниз +Arrows Стрелки +Arrows at both ends Стрелки на обоих концах +As One Object Как один объект +Audio Звук +Audio from File… Звук из файла… +AutoCorrect as you type Автозамена при вводе +Autofit Автоподбор +Automatic Автоматически +B4 (ISO) Paper (250x353 mm) Бумага B4 (ISO) (250x353 мм) +B5 (ISO) Paper (176x250 mm) Бумага B5 (ISO) (176x250 мм) +Background Фон +Background Styles Стили фона +Background\nStyles Стили фона +Backspace Backspace +Banded Columns Чередующиеся столбцы +Banded Rows Чередующиеся строки +Banner Лента +Basic Cycle Простой цикл +Basic List Простой список +Basic Process Простой процесс +Basic Shapes Основные фигуры +Before text (in): Перед текстом (дюймы): +Bevel Фаска +Binary assets added Добавленные двоичные файлы +Binary assets removed Удаленные двоичные файлы +Black Left Через черное влево +Black Pen Черное перо +Black Right Через черное вправо +Blinds Жалюзи +Block Arc Блочная дуга +Block Arrows Блочные стрелки +Blue Синий +Blue Pen Синее перо +Bold Полужирный +Bold Flash Полужирная вспышка +Both Оба +Bottom Низ +Bounce Отскок +Box Коробка +Box In Коробка внутрь +Box Out Коробка наружу +Box and Whisker Ящик с усами +Brightness Яркость +Brightness {:+}% Яркость {:+}% +Bring Forward Переместить вперед +Bring to Front На передний план +Bring\nForward Переместить вперед +Browsed at a kiosk (full screen) Просмотр в киоске (полный экран) +Browsed by an individual (window) Индивидуальный просмотр (в окне) +Bubble Пузырьковая +Bullets Маркеры +Burst Взрыв +By Paragraph По абзацам +Callout: Down Arrow Выноска: Стрелка вниз +Callout: Left Arrow Выноска: Стрелка влево +Callout: Line Выноска: Линия +Callout: Right Arrow Выноска: Стрелка вправо +Callout: Up Arrow Выноска: Стрелка вверх +Callouts Выноски +Cameo Камео +Camera capture is not available yet Захват с камеры пока недоступен +Cancel Отмена +Capitalize Each Word Каждое Слово С Прописной +Caps Прописные +Center По центру +Centered По центру +Change Case Изменить регистр +Change Chart Type Изменить тип диаграммы +Change Picture Изменить рисунок +Change Shape Изменить фигуру +Change\nChart Type Изменить тип диаграммы +Character Spacing Межзнаковый интервал +Characters Символы +Chart Диаграмма +Chart Data Данные диаграммы +Chart Design Конструктор диаграмм +Chart Elements Элементы диаграммы +Chart… Диаграмма… +Check Accessibility Проверить читаемость +Check\nAccessibility Проверить доступность +Checkerboard Шахматная доска +Chevron Шеврон +Choose a SmartArt Graphic Выберите графический элемент SmartArt +Chord Хорда +Circle Круг +Circle In Круг внутрь +Circle Out Круг наружу +Clear All Formatting Очистить все форматирование +Click a symbol to insert it at the insertion point. Нажмите символ, чтобы вставить его в позицию курсора. +Click icon to add SmartArt graphic Щелкните значок, чтобы добавить графический элемент SmartArt +Click icon to add chart Щелкните значок, чтобы добавить диаграмму +Click icon to add media Щелкните значок, чтобы добавить медиафайл +Click icon to add picture Щелкните значок, чтобы добавить рисунок +Click icon to add table Щелкните значок, чтобы добавить таблицу +Click to add first slide Щелкните, чтобы добавить первый слайд +Click to add notes Щелкните, чтобы добавить заметки +Click to add subtitle Щелкните, чтобы добавить подзаголовок +Click to add text Щелкните, чтобы добавить текст +Click to add title Щелкните, чтобы добавить заголовок +Click to edit Master text styles Щелкните, чтобы изменить стили текста образца +Click to edit Master title style Щелкните, чтобы изменить стиль заголовка образца +Clock Часы +Clockwise По часовой стрелке +Close Закрыть +Close Master View Закрыть режим образца +Close\nMaster View Закрыть режим образца +Cloud Облако +Clustered Bar Линейчатая с группировкой +Clustered Column Гистограмма с группировкой +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Свернуть ленту +Color Цвет +Color Pulse Пульсация цвета +Colors Цвета +Columns Столбцы +Comb Гребенка +Combo Комбинированная +Command Palette Палитра команд +Comment Комментарий +Comments Комментарии +Commits Коммиты +Community Links Ссылки сообщества +Company Компания +Complementary Color Дополнительный цвет +Connect Shapes Соединить фигуры +Connection Sites Точки соединения +Connector: Curved Соединитель: Кривая +Connector: Elbow Соединитель: Ломаная +Connector: Elbow (one bend) Соединитель: Ломаная (один излом) +Content Содержимое +Contrast Контраст +Contrast {:+}% Контраст {:+}% +Contributors Участники +Conveyor Конвейер +Copy Копировать +Corrections Коррекция +Couldn't save AutoRecover information: {e} Не удалось сохранить данные автовосстановления: {e} +Counter Clockwise Против часовой стрелки +Cover Покрытие +Create Создать +Crop Обрезать +Crop 10% each side Обрезать по 10% с каждой стороны +Crop 20% each side Обрезать по 20% с каждой стороны +Crop to Shape Обрезать по фигуре +Cross Крест +Crush Смятие +Ctrl+ Ctrl+ +Cube Куб +Currency Денежный +Curtains Шторы +Custom Настраиваемый +Custom Path Настраиваемый путь +Custom Show Настраиваемый показ +Custom Show 1 Настраиваемый показ 1 +Custom Shows Настраиваемые показы +Custom Slide Show Настраиваемый показ слайдов +Custom\nShow Настраиваемый показ +Cut Вырезать +Cylinder Цилиндр +Dark Blue Темно-синий +Dark Mode Темный режим +Dark Red Темно-красный +Dark appearance Темное оформление +Dark\nMode Темный режим +Darken Затемнение +Dash Штрих +Dash Dot Штрих-точка +Dashes Штрихи +Database База данных +Date Дата +Date & Time Дата и время +Date &\nTime Дата и время +Date and Time Дата и время +Date and time Дата и время +Decagon Десятиугольник +Decision Решение +DeckCraft DeckCraft +Decrease Font Size Уменьшить размер шрифта +Decrease List Level Уменьшить уровень списка +Delay: Задержка: +Delete Удалить +Delete Columns Удалить столбцы +Delete Comment Удалить комментарий +Delete Layout Удалить макет +Delete Rows Удалить строки +Delete Slide Удалить слайд +Delete Table Удалить таблицу +Delete Text Удалить текст +Desaturate Обесцвечивание +Deselect Снять выделение +Design Дизайн +Design Ideas Идеи для дизайна +Design\nIdeas Идеи для дизайна +Deutsch Deutsch +Diagonal Stripe Диагональная полоса +Diamond Ромб +Diamond In Ромб внутрь +Diamond Out Ромб наружу +Direction Направление +Disappear Исчезновение +Discard Recovered Presentations Отменить восстановленные презентации +Display name Отображаемое имя +Dissolve Растворение +Dissolve In Растворение внутрь +Dissolve Out Растворение наружу +Distribute Распределить +Distribute Columns Распределить столбцы +Distribute Horizontally Распределить по горизонтали +Distribute Rows Распределить строки +Distribute Vertically Распределить по вертикали +Division Sign Знак деления +Do not Autofit Не подгонять +Do you want to save the changes you made to {what}? Сохранить изменения, внесенные в {what}? +Document Документ +Dodecagon Двенадцатиугольник +Don't Save Не сохранять +Don't show on title slide Не показывать на титульном слайде +Done Готово +Donut Кольцо +Doors Двери +Double Brace Двойная фигурная скобка +Double Bracket Двойная квадратная скобка +Double Wave Двойная волна +Doughnut Кольцевая +Down Вниз +Drape Занавес +Draw Рисование +Drop Shadow Rectangle Прямоугольник с тенью +Duplicate Дублировать +Duplicate Selected Slides Дублировать выбранные слайды +Duplicate Slide Дублировать слайд +Duration: Длительность: +Dynamic Content Динамическое содержимое +Edit Правка +Edit Alt Text… Изменить альтернативный текст… +Edit Data Изменить данные +Edit Shape Изменить фигуру +Edit Text Изменить текст +Edit the data: first row = series names, first column = categories. Измените данные: первая строка — имена рядов, первый столбец — категории. +Edit\nData Изменить данные +Edit\nShape Изменить фигуру +Editing Редактирование +Effect Options Параметры эффекта +Effect\nOptions Параметры эффекта +Effects Эффекты +Email Address Адрес электронной почты +Email address: Адрес электронной почты: +Emphasis Выделение +End Конец +End Show Завершить показ +End of slide show Конец показа слайдов +End of slide show, click to exit. Конец показа слайдов. Щелкните, чтобы выйти. +End trim (s): Обрезка в конце (с): +English (United Kingdom) Английский (Великобритания) +English (United States) Английский (США) +Enter Enter +Entrance Появление +Equals Равно +Equation Уравнение +Equation Shapes Фигуры уравнений +Eraser Ластик +Escape Escape +Español Español +Exciting Выразительные +Exit Исчезновение +Expand Развернуть +Explosion: 14 Points Взрыв: 14 лучей +Explosion: 8 Points Взрыв: 8 лучей +Export Экспорт +Export the presentation as: Экспортировать презентацию как: +Exported {path} Экспортировано: {path} +Export… Экспортировать… +Fade Затухание +Fade in (s): Появление (с): +Fade out (s): Исчезновение (с): +Fall Over Падение +Ferris Wheel Чертово колесо +File Файл +Fill Заливка +Fill & Line Заливка и линия +Fill Color Цвет заливки +Filled Radar Заполненная лепестковая +Find… Найти… +First Первый +First Column Первый столбец +First Slide Первый слайд +First commit Первый коммит +Fit Вписать +Fit slide to current window Вписать слайд в текущее окно +Fit to Window Вписать в окно +Fit to\nWindow Вписать в окно +Flash Вспышка +Flip Отразить +Flip Horizontal Отразить горизонтально +Flip Vertical Отразить вертикально +Float In Плавное появление +Float Out Плавное исчезновение +Flowchart Блок-схема +Flowchart: Alternate Process Блок-схема: Альтернативный процесс +Flowchart: Card Блок-схема: Карточка +Flowchart: Collate Блок-схема: Сопоставление +Flowchart: Connector Блок-схема: Соединитель +Flowchart: Data Блок-схема: Данные +Flowchart: Decision Блок-схема: Решение +Flowchart: Delay Блок-схема: Задержка +Flowchart: Direct Access Storage Блок-схема: Хранилище прямого доступа +Flowchart: Display Блок-схема: Дисплей +Flowchart: Document Блок-схема: Документ +Flowchart: Extract Блок-схема: Извлечение +Flowchart: Internal Storage Блок-схема: Внутреннее хранилище +Flowchart: Magnetic Disk Блок-схема: Магнитный диск +Flowchart: Manual Input Блок-схема: Ручной ввод +Flowchart: Manual Operation Блок-схема: Ручная операция +Flowchart: Merge Блок-схема: Объединение +Flowchart: Multidocument Блок-схема: Несколько документов +Flowchart: Off-page Connector Блок-схема: Соединитель между страницами +Flowchart: Or Блок-схема: Или +Flowchart: Predefined Process Блок-схема: Заранее определенный процесс +Flowchart: Preparation Блок-схема: Подготовка +Flowchart: Process Блок-схема: Процесс +Flowchart: Punched Tape Блок-схема: Перфолента +Flowchart: Sequential Access Storage Блок-схема: Хранилище последовательного доступа +Flowchart: Sort Блок-схема: Сортировка +Flowchart: Stored Data Блок-схема: Сохраненные данные +Flowchart: Summing Junction Блок-схема: Узел суммирования +Flowchart: Terminator Блок-схема: Начало/конец +Fly In Вылет +Fly Out Улет +Fly Through Пролет +Folded Corner Согнутый угол +Follow the layout Как в макете +Followed Hyperlink Посещенная гиперссылка +Font Шрифт +Font Color Цвет шрифта +Font Size Размер шрифта +Fonts Шрифты +Footer Нижний колонтитул +Foreground Передний план +Format Формат +Format Background Формат фона +Format Background… Формат фона… +Format Painter Формат по образцу +Format Painter (double-click to keep it on) Формат по образцу (двойной щелчок для постоянного режима) +Format Pane Область форматирования +Format Shape Формат фигуры +Format Shape… Формат фигуры… +Format\nBackground Формат фона +Format\nPane Область форматирования +Formatting State Состояние форматирования +Fracture Разлом +Frame Рамка +Français Français +Freeform Произвольная фигура +From Из +From Beginning С начала +From Bottom Снизу +From Bottom Left Снизу слева +From Bottom Right Снизу справа +From Current Slide С текущего слайда +From Left Слева +From Right Справа +From Top Сверху +From Top Left Сверху слева +From Top Right Сверху справа +From bottom left Снизу слева +From bottom right Снизу справа +From center Из центра +From top left Сверху слева +From top right Сверху справа +From\nBeginning С начала +From\nCurrent Slide С текущего слайда +Full Полная +Full Page Slides Слайды на всю страницу +Funnel Воронка +Gallery Галерея +General Общие +Get Text Получить текст +Glitter Блеск +Glow Свечение +Go to Перейти +Go to Slide Перейти к слайду +Grab bag Случайная подборка +Gradient fill Градиентная заливка +Gradient stops Точки градиента +Gradient… Градиент… +Grayscale Оттенки серого +Greek Греческий +Green Зеленый +Gridlines Линии сетки +Group Группировать +Group Objects Группировать объекты +Grow & Turn Увеличение и поворот +Grow/Shrink Увеличение/уменьшение +Guides Направляющие +Half Половина +Half Frame Половина рамки +Handout Master Образец выдачи +Handout Master (coming soon) Образец выдачи (скоро) +Handout\nMaster Образец выдачи +Handouts (1 slide per page) Выдача (1 слайд на страницу) +Handouts (2 slides per page) Выдача (2 слайда на страницу) +Handouts (3 slides per page) Выдача (3 слайда на страницу) +Handouts (4 slides per page) Выдача (4 слайда на страницу) +Handouts (6 slides per page) Выдача (6 слайдов на страницу) +Handouts (9 slides per page) Выдача (9 слайдов на страницу) +Header Верхний колонтитул +Header & Footer Колонтитулы +Header &\nFooter Колонтитулы +Header Row Строка заголовка +Header and Footer Колонтитулы +Header and Footer… Колонтитулы… +Heart Сердце +Height Высота +Height (in): Высота (дюймы): +Height: Высота: +Help Справка +Heptagon Семиугольник +Hexagon Шестиугольник +Hide All Скрыть все +Hide Background Graphics Скрыть графику фона +Hide During Show Скрыть во время показа +Hide Slide Скрыть слайд +Hide background graphics Скрыть графику фона +Hide\nSlide Скрыть слайд +Hierarchy Иерархия +High Высокий +Highlighter Маркер +Histogram Гистограмма +Home Главная +Honeycomb Соты +Horizontal Горизонтально +Horz In Горизонтально внутрь +Horz Out Горизонтально наружу +How would you describe this object and its context to someone who is blind or has low vision? Как бы вы описали этот объект и его контекст человеку с нарушением зрения? +Hyperlink Гиперссылка +Icons Значки +In Внутрь +In Bounce Внутрь с отскоком +Include hidden slides Включить скрытые слайды +Increase Font Size Увеличить размер шрифта +Increase List Level Повысить уровень списка +Ink to Math Рукописный ввод в уравнение +Ink to Math (coming soon) Рукописный ввод в уравнение (скоро) +Ink to Shape Рукописный ввод в фигуру +Ink to Shape (coming soon) Рукописный ввод в фигуру (скоро) +Ink to Text Рукописный ввод в текст +Ink to Text (coming soon) Рукописный ввод в текст (скоро) +Ink to\nMath Рукописный ввод в уравнение +Ink to\nShape Рукописный ввод в фигуру +Ink to\nText Рукописный ввод в текст +Inner Внутренняя +Insert Вставить +Insert Above Вставить выше +Insert Below Вставить ниже +Insert Hyperlink Вставить гиперссылку +Insert Layout Вставить макет +Insert Left Вставить слева +Insert Placeholder Вставить заполнитель +Insert Right Вставить справа +Insert Table Вставить таблицу +Insert Table… Вставить таблицу… +Insert picture from file… Вставить рисунок из файла… +Insert\nAbove Вставить выше +Insert\nBelow Вставить ниже +Insert\nLayout Вставить макет +Insert\nLeft Вставить слева +Insert\nPlaceholder Вставить заполнитель +Insert\nRight Вставить справа +Inspect Presentation Сведения о презентации +Inspect Shape Сведения о фигуре +Inspect Slide Сведения о слайде +Interface Language Язык интерфейса +Interface language: Язык интерфейса: +Interface size Размер интерфейса +Isosceles Triangle Равнобедренный треугольник +Italiano Italiano +Italic Курсив +JPEG image (current slide) Изображение JPEG (текущий слайд) +Join our community on Discord Присоединяйтесь к нашему сообществу в Discord +Join the ArtCraft community on Discord Присоединяйтесь к сообществу ArtCraft в Discord +Justify По ширине +L-Shape Г-образная фигура +Language Язык +Last Последний +Last Column Последний столбец +Last Slide Последний слайд +Last commit Последний коммит +Layout Макет +Learn More Подробнее +Learn\nMore Подробнее +Ledger Paper (11x17 in) Бумага Ledger (11×17 дюймов) +Left Слева +Left Brace Левая фигурная скобка +Left Bracket Левая квадратная скобка +Letter Paper (8.5x11 in) Бумага Letter (8,5×11 дюймов) +Liberation Serif Liberation Serif +Light Blue Светло-синий +Light Green Светло-зеленый +Light/Dark appearance Светлое/темное оформление +Lighten Осветление +Lightning Молния +Lightning Bolt Молния +Line Линия +Line Color Цвет линии +Line Spacing Междустрочный интервал +Line Spacing Options… Параметры междустрочного интервала… +Line delta Разница строк +Line spacing (lines): Междустрочный интервал (строки): +Line with Markers Линейная с маркерами +Linear Линейный +Lines Линии +Lines +/− Строки +/− +Lines added Добавленные строки +Lines deleted Удаленные строки +Link Ссылка +Link… Ссылка… +List Commands Список команд +Lock Заблокировать +Long Dash Длинный штрих +Long Dash Dot Длинный штрих и точка +Loop continuously until 'Esc' Повторять непрерывно до нажатия «Esc» +Loop until Stopped Повторять до остановки +Loops Петли +Loose Разреженный +Low Низкий +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 команда ArtCraft и участники DeckCraft +Margins (pt) Поля (пт) +Mark as decorative Пометить как декоративный +Mark selected text as: Пометить выделенный текст как: +Math Математика +Matrix Матрица +Maximize content (else ensure fit) Увеличить содержимое (иначе вписать) +Media Медиа +Media Info Сведения о мультимедиа +Medium Средний +Merge Cells Объединить ячейки +Merge Shapes Объединить фигуры +Merge\nCells Объединить ячейки +Merge\nShapes Объединить фигуры +Merged PRs Принятые запросы на слияние +Middle Посередине +Minus Sign Знак минуса +Model Модель +Models Модели +Moon Луна +More Colors… # Другие цвета… # +Morph Преобразование +Motion Движение +Motion Paths Траектории движения +Move Перемещение +Move Down Переместить вниз +Move Insertion Point Переместить точку ввода +Move Section Переместить раздел +Move Section Down Переместить раздел вниз +Move Section Up Переместить раздел вверх +Move Slide Переместить слайд +Move Up Переместить вверх +Multiplication Sign Знак умножения +Multiply Умножение +Mute Без звука +Name Имя +Name (A–Z) Имя (А–Я) +Name: Название: +New Comment Новый комментарий +New Presentation Новая презентация +New Slide Новый слайд +New Slide (⇧⌘N) Новый слайд (⇧⌘N) +New presentation Новая презентация +New show name: Название нового показа: +New\nComment Новый комментарий +New\nSlide Новый слайд +Next Далее +Next Slide Следующий слайд +Next Window Следующее окно +Next ▶ Далее ▶ +No Color Нет цвета +No Fill Нет заливки +No Glow Нет свечения +No Outline Нет контура +No Reflection Нет отражения +No Shadow Нет тени +No Soft Edges Нет размытия краев +No accessibility issues found. People with disabilities should not have difficulty reading this document. Проблем с читаемостью не найдено. У людей с ограниченными возможностями не должно возникнуть трудностей при чтении этой презентации. +No comments on this slide. На этом слайде нет комментариев. +No contributor data was built into this copy. В эту копию не встроены данные об участниках. +No fill Нет заливки +No line Нет линии +No model credits were built into this copy. В эту копию не встроены данные об использованных моделях. +No notes. Нет заметок. +No sound: {err} Нет звука: {err} +None Нет +Normal Обычный +Not Equal Не равно +Not allowed Не разрешено +Notes Заметки +Notes Master Образец заметок +Notes Master (coming soon) Образец заметок (скоро) +Notes Page Страница заметок +Notes Pages Страницы заметок +Notes\nMaster Образец заметок +Notes\nPage Страница заметок +Nudge Сдвинуть +Number of columns: Количество столбцов: +Number of rows: Количество строк: +Numbering Нумерация +Object Color Цвет объекта +Objects Объекты +Octagon Восьмиугольник +On Click По щелчку +On Click of {name} По щелчку на {name} +On Click of… (none) По щелчку на… (нет) +On Mouse Click По щелчку мыши +On-screen Show (16:10) Экранный показ (16:10) +Open Data Открыть данные +Open Dialog Открыть диалог +Open Recovered Presentations Открыть восстановленные презентации +Open the sample deck Открыть образец презентации +Open… Открыть… +Orange Оранжевый +Orbit Орбита +Order Objects Порядок объектов +Origami Оригами +Out Наружу +Out Bounce Наружу с отскоком +Outer Внешняя +Outline Структура +Outline (.txt) Структура (.txt) +Outline View Режим структуры +Outline\nView Режим структуры +Oval Овал +Oval ends Овальные концы +Overhead Диапроектор +PDF document (.pdf) Документ PDF (.pdf) +PNG images (all slides) Изображения PNG (все слайды) +PNG images (current slide) Изображения PNG (текущий слайд) +PRs Запросы на слияние +Page Curl Сворачивание страницы +Page Setup… Параметры страницы… +PageDown PageDown +PageUp PageUp +Pan Панорамирование +Pane Область +Paragraph Абзац +Paragraph… Абзац… +Parallelogram Параллелограмм +Pareto Парето +Partial Circle Часть круга +Particles Частицы +Paste Вставить +Paste (⌘V) Вставить (⌘V) +Paste Formatting Вставить форматирование +Paste and Match Formatting Вставить с совпадающим форматированием +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Вставьте или введите структуру. Строки без отступа станут заголовками слайдов; строки с отступом табуляции — пунктами списка. +Pasted image.png Вставленное изображение.png +Path Путь +Pattern fill Узорная заливка +Pause Пауза +Peek In Подглядывание +Peel Off Отслоение +Pencil Карандаш +Pentagon Пятиугольник +Perspective Перспектива +Pick a graphic; type one item per line. Выберите графику; введите по одному элементу в строке. +Pick a look for your slides. Ideas are generated on your device. Выберите оформление слайдов. Идеи создаются на вашем устройстве. +Picture Рисунок +Picture Format Формат рисунка +Picture Styles Стили рисунка +Picture from File… Рисунок из файла… +Picture or texture fill Заливка рисунком или текстурой +Picture\nStyles Стили рисунка +Pictures Рисунки +Pie Круговая +Pin Закрепить +Placeholder colour Цвет заполнителя +Plan\nBuild\nLaunch План\nРазработка\nЗапуск +Plaque Табличка +Play Воспроизвести +Play Across Slides Воспроизводить на нескольких слайдах +Play Full Screen Воспроизводить на весь экран +Play Narrations Воспроизводить звуковое сопровождение +Play from Current Slide Воспроизвести с текущего слайда +Play from Start Воспроизвести с начала +Play from Start (F5) Воспроизвести с начала (F5) +Play from\nCurrent Slide Воспроизвести с текущего слайда +Play from\nStart Воспроизвести с начала +Play/Pause Воспроизвести/приостановить +Playback Воспроизведение +Plus Плюс +Plus In Плюс внутрь +Plus Out Плюс наружу +Plus Sign Знак плюса +Portrait (9:16) Портретный (9:16) +Português Português +Position Положение +Position Objects Положение объектов +Position and Size Положение и размер +Post Отправить +Poster Frame Кадр афиши +PowerPoint Presentation (.pptx) Презентация PowerPoint (.pptx) +Preferences Параметры +Preferences… Параметры… +Presentation Презентация +Presentations Презентации +Presentations and slide shows, rebuilt from scratch in pure Rust. Презентации и показы слайдов, созданные с нуля на чистом Rust. +Presented by a speaker (full screen) Докладчиком (полноэкранный режим) +Presenter View Режим докладчика +Presenter View — DeckCraft Режим докладчика — DeckCraft +Presenter\nView Режим докладчика +Preset gradients Готовые градиенты +Prestige Престиж +Preview Предварительный просмотр +Previous Slide Предыдущий слайд +Print layout: Макет печати: +Properties Свойства +Pulse Пульсация +Punctuation Пунктуация +Purple Фиолетовый +Push Вытеснение +Pyramid Пирамида +Quick Styles Экспресс-стили +Quick\nStyles Экспресс-стили +Radar Лепестковая +Radial Радиальный +Random Случайный +Random Bars Случайные полосы +Reading View Режим чтения +Reading\nView Режим чтения +Real name Настоящее имя +Recent Недавние +Record Запись +Recording narration needs audio capture (coming soon) Для записи звукового сопровождения нужен захват аудио (скоро) +Recovered Presentations Восстановленные презентации +Recovered {} from the last session Восстановлено {} с прошлой сессии +Rectangle Прямоугольник +Rectangle: Diagonal Corners Rounded Прямоугольник: скругленные диагональные углы +Rectangle: Diagonal Corners Snipped Прямоугольник: срезанные диагональные углы +Rectangle: Rounded Corners Прямоугольник: скругленные углы +Rectangle: Single Corner Rounded Прямоугольник: один скругленный угол +Rectangle: Single Corner Snipped Прямоугольник: один срезанный угол +Rectangle: Top Corners One Rounded and One Snipped Прямоугольник: один верхний угол скругленный, другой срезанный +Rectangle: Top Corners Rounded Прямоугольник: скругленные верхние углы +Rectangle: Top Corners Snipped Прямоугольник: срезанные верхние углы +Rectangles Прямоугольники +Rectangular Прямоугольный +Red Красный +Red Pen Красное перо +Redo Вернуть +Redo (⌘Y) Вернуть (⌘Y) +Reflected Rounded Rectangle Скругленный прямоугольник с отражением +Reflection Отражение +Regroup Перегруппировать +Regular Pentagon Правильный пятиугольник +Rehearse Timings Репетиция хронометража +Rehearse\nTimings Репетиция хронометража +Remove Удалить +Remove All Animations Удалить все анимации +Remove All Sections Удалить все разделы +Remove Animation Удалить анимацию +Remove Background Удалить фон +Remove Background (coming soon) Удаление фона (скоро) +Remove Section Удалить раздел +Remove Section & Slides Удалить раздел и слайды +Remove stop Удалить точку +Remove\nBackground Удалить фон +Rename Переименовать +Rename Layout Переименовать макет +Rename Section Переименовать раздел +Rename Section… Переименовать раздел… +Rename Slide Переименовать слайд +Rename… Переименовать… +Render Slide Отрисовать слайд +Reopen Открыть снова +Reorder Animation Изменить порядок анимации +Reorder Objects Изменить порядок объектов +Replace straight quotes with smart quotes Заменять прямые кавычки типографскими +Reply Ответить +Reply… Ответить… +Reset Сбросить +Reset Background Сбросить фон +Reset Crop Сбросить обрезку +Reset Effects Сбросить эффекты +Reset Picture Сбросить рисунок +Reset Slide Сбросить слайд +Reset Slide Background Сбросить фон слайда +Resize shape to fit text Изменить размер фигуры по тексту +Resolve Пометить решенным +Resolve Thread Завершить обсуждение +Return Вернуться +Reveal Раскрытие +Reverse the order Обратный порядок +Revert Вернуть прежнюю версию +Review Рецензирование +Rewind after Playing Перемотать после воспроизведения +Ribbon Tab Вкладка ленты +Ribbon: Tilted Down Лента: наклон вниз +Ribbon: Tilted Up Лента: наклон вверх +Right Справа +Right Brace Правая фигурная скобка +Right Bracket Правая квадратная скобка +Right Triangle Прямоугольный треугольник +Right-to-Left Text Direction Направление текста справа налево +Ring Кольцо +Ripple Рябь +Rise Up Подъем +Rotate Повернуть +Rotate Left 90° Повернуть влево на 90° +Rotate Right 90° Повернуть вправо на 90° +Rotate all text 270° Повернуть весь текст на 270° +Rotate all text 90° Повернуть весь текст на 90° +Rotate with shape Поворачивать вместе с фигурой +Rotation Поворот +Round Dot Круглая точка +Rounded Diagonal Corner Скругленный диагональный угол +Ruler Линейка +Saturation Насыщенность +Saturation {}% Насыщенность {}% +Save Сохранить +Save (⌘S) Сохранить (⌘S) +Save As… Сохранить как… +Save AutoRecover Information Сохранить данные автовосстановления +Save as Template… Сохранить как шаблон… +Save to Data Сохранить в данные +Saved Сохранено +Saved {path} Сохранено: {path} +Scatter Точечная +ScreenTip: Всплывающая подсказка: +Screenshot Снимок экрана +Screenshot (not available yet) Снимок экрана (пока недоступно) +Scroll: Horizontal Свиток: горизонтальный +Scroll: Vertical Свиток: вертикальный +Search commands (⇧⌘P) Поиск команд (⇧⌘P) +Search commands… Поиск команд… +Section Раздел +Seek Перейти к позиции +Select Выделение +Select All Выделить все +Select All Text Выделить весь текст +Select Cells Выбрать ячейки +Select Objects Выбрать объекты +Select Paragraph Выбрать абзац +Select Slides Выбрать слайды +Select Text Выбрать текст +Select Word Выбрать слово +Select a chart first. Сначала выберите диаграмму. +Select a shape to format it. Выберите фигуру для форматирования. +Select an object on the slide and add an animation from the Animations tab. Выберите объект на слайде и добавьте анимацию на вкладке «Анимация». +Selection Выделение +Selection Pane Область выделения +Selection Pane… Область выделения… +Selection\nPane Область выделения +Send Backward Переместить назад +Send to Back На задний план +Send\nBackward Переместить назад +Sentence case. Как в предложениях. +Set Text Задать текст +Set Up Show… Настроить показ… +Set Up Slide Show Настроить показ слайдов +Set Up Slide Show… Настроить показ слайдов… +Set Up\nSlide Show Настроить показ слайдов +Set as Default Shape Сделать стандартной фигурой +Shading Затенение +Shadow Тень +Shape Фигура +Shape Effects Эффекты фигуры +Shape Fill Заливка фигуры +Shape Format Формат фигуры +Shape Gallery Галерея фигур +Shape Outline Контур фигуры +Shape Styles Стили фигур +Shape {} Фигура {} +Shape\nStyles Стили фигур +Shapes Фигуры +Shift+ Shift+ +Shift+F9 Shift+F9 +Show Показать +Show All Показать все +Show Comments Показать комментарии +Show Media Controls Показать элементы управления медиа +Show Slide Показать слайд +Show smart guides Показывать смарт-направляющие +Show type Тип показа +Show without animation Показ без анимации +Show without narration Показ без звукового сопровождения +Show/Hide Показать/скрыть +Show\nComments Показать комментарии +Shred Измельчение +Shrink & Turn Уменьшение и поворот +Shrink text on overflow Сжимать текст при переполнении +Simple Frame, White Простая рамка, белая +Size Размер +Size & Properties Размер и свойства +Slide Master Образец слайдов +Slide Number Номер слайда +Slide Show Показ слайдов +Slide Size Размер слайда +Slide Sorter Сортировщик слайдов +Slide number Номер слайда +Slide timings recorded. Хронометраж слайдов записан. +Slide {:02}:{:04.1} Total {:02}:{:02} Слайд {:02}:{:04.1} Всего {:02}:{:02} +Slide {} of {} Слайд {} из {} +Slide {}: {}{} Слайд {}: {}{} +Slide {}: “{w}” Слайд {}: «{w}» +Slide\nMaster Образец слайдов +Slide\nNumber Номер слайда +Slide\nSize Размер слайда +Slide\nSorter Сортировщик слайдов +Slides (e.g. 1,3,5): Слайды (например, 1,3,5): +Slides from Outline Слайды из структуры +Slides from Outline… Слайды из структуры… +Slides sized for: Размер слайдов: +SmartArt SmartArt +Smile Улыбка +Smiley Face Улыбающееся лицо +Smoothly Плавно +Smoothly Left Плавно влево +Smoothly Right Плавно вправо +Snap objects to grid Привязывать объекты к сетке +Soft Edge Rectangle Прямоугольник с размытыми краями +Soft Edges Размытые края +Solid Сплошной +Solid fill Сплошная заливка +Solid line Сплошная линия +Sort Сортировка +Source on GitHub Исходный код на GitHub +Space Space +Spacing after (pt): Интервал после (пт): +Spacing before (pt): Интервал перед (пт): +Special — hanging (in): Специальное — выступ (дюймы): +Speech Речь +Speech Bubble: Oval Выноска: овальная +Speech Bubble: Rectangle Выноска: прямоугольная +Speech Bubble: Rectangle with Corners Rounded Выноска: прямоугольная со скругленными углами +Spelling Орфография +Spin Вращение +Spinner Круговое вращение +Split Разделение +Split Cells Разделить ячейки +Split\nCells Разделить ячейки +Square Квадрат +Square (1:1) Квадрат (1:1) +Square Dot Квадратная точка +Stacked С накоплением +Stacked Area С областями с накоплением +Stacked Bar Линейчатая с накоплением +Stacked Column Гистограмма с накоплением +Stacked Line График с накоплением +Standard (4:3) Стандартный (4:3) +Standard Colors Стандартные цвета +Star Звезда +Star: 10 Points Звезда: 10 лучей +Star: 12 Points Звезда: 12 лучей +Star: 16 Points Звезда: 16 лучей +Star: 24 Points Звезда: 24 луча +Star: 32 Points Звезда: 32 луча +Star: 4 Points Звезда: 4 луча +Star: 5 Points Звезда: 5 лучей +Star: 6 Points Звезда: 6 лучей +Star: 7 Points Звезда: 7 лучей +Star: 8 Points Звезда: 8 лучей +Stars and Banners Звезды и ленты +Start After Previous После предыдущего +Start Automatically Автоматически +Start On Click По щелчку +Start With Previous Вместе с предыдущим +Start a conversation Начните обсуждение +Start time (s): Время начала (с): +Start: Начало: +Stealth end Остроконечный конец +Stock Биржевая +Stop Остановить +Stop Editing Text Завершить редактирование текста +Strikethrough Зачеркнутый +Strips Полосы +Style {i} Стиль {i} +Subscript Подстрочный знак +Subtle Сдержанные +Sun Солнце +Sunburst Солнечные лучи +Superscript Надстрочный знак +Surface Поверхностная +Switch Переключение +Swivel Поворот +Symbol Символ +System language Системный язык +Tab Tab +Table Таблица +Table Design Конструктор таблиц +Table Style Options Параметры стиля таблицы +Table Styles Стили таблицы +Table… Таблица… +Task Pane Область задач +Teardrop Капля +Teeter Качание +Text Текст +Text Box Надпись +Text Box Margins Поля текстового блока +Text Direction Направление текста +Text Effects Текстовые эффекты +Text Fill Заливка текста +Text Highlight Color Цвет выделения текста +Text Options Параметры текста +Text Outline Контур текста +Text Shadow Тень текста +Text/Background - Dark 1 Текст/фон — темный 1 +Text/Background - Dark 2 Текст/фон — темный 2 +Text/Background - Light 1 Текст/фон — светлый 1 +Text/Background - Light 2 Текст/фон — светлый 2 +Text\nBox Надпись +The spelling check is complete. No issues found. Проверка орфографии завершена. Ошибок не найдено. +Theme Colors Цвета темы +Theme Gallery Галерея тем +Themes Темы +Thesaurus Тезаурус +Thesaurus (coming soon) Тезаурус (скоро) +This Document Этот документ +Thought Мысль +Thought Bubble: Cloud Мысль: облако +Through Black Через черный +Tight Плотный +Timing Время показа +Top Верх +Total Row Строка итогов +Transition Переход +Transition Gallery Галерея переходов +Transitions Переходы +Translate Перевести +Translation needs a language model (not bundled) Для перевода нужна языковая модель (не входит в комплект) +Transparency Прозрачность +Trapezoid Трапеция +Treemap Древовидная +Triangle Треугольник +Trigger Триггер +Trim Обрезать +Trim Media Обрезать медиа +Turns Повороты +Type Тип +Type Text Ввести текст +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Введите уравнение в линейном виде (например, a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Открывание +Underline Подчеркнутый +Undo Отменить +Undo (⌘Z) Отменить (⌘Z) +Ungroup Разгруппировать +Up Вверх +Use Timings Использовать время показа +Use timings, if present Использовать время показа, если задано +Username Имя пользователя +Version Версия +Version {} Версия {} +Vert In Вертикально внутрь +Vert Out Вертикально наружу +Vertical Вертикально +Vertical alignment Вертикальное выравнивание +Very Loose Очень разреженный +Very Tight Очень плотный +Video Видео +Video from File… Видео из файла… +View Вид +Volume Громкость +Vortex Вихрь +Waterfall Каскадная +Wave Волна +Web Page or File Веб-страница или файл +Wedge Клин +Weight Толщина +Wheel Колесо +Widescreen (13.333x7.5 in) Широкоэкранный (13,333×7,5 дюймов) +Widescreen (16:9) Широкоэкранный (16:9) +Width Ширина +Width (in): Ширина (дюймы): +Width: Ширина: +Width: Ширина: +Wind Ветер +Window Окно +Wipe Стирание +With Previous Вместе с предыдущим +WordArt WordArt +WordArt style {} Стиль WordArt {} +Words Слова +Wrap Text in Shape Переносить текст в фигуре +Wrap text in shape Переносить текст в фигуре +Yellow Желтый +Your changes will be lost if you don't save them. Если не сохранить, изменения будут потеряны. +Your name (comments): Ваше имя (комментарии): +Zoom Масштаб +Zoom In Увеличить +Zoom Out Уменьшить +Zoom… Масштаб… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Принять исправление +Action Settings Настройка действия +Add Font Добавить шрифт +Add Guide Добавить направляющую +Add Point Добавить точку +Add Shape Добавить фигуру +Add to Dictionary Добавить в словарь +Align Cell Text Выровнять текст ячейки +Apply Design Idea Применить идею дизайна +Arrow: Circular Стрелка: Круговая +Arrow: Circular Counter-clockwise Стрелка: Круговая против часовой стрелки +Arrow: Circular Two-headed Стрелка: Круговая двусторонняя +Arrow: Curved Down Стрелка: Дуговая вниз +Arrow: Curved Left Стрелка: Дуговая влево +Arrow: Curved Right Стрелка: Дуговая вправо +Arrow: Curved Up Стрелка: Дуговая вверх +Arrow: Swoosh Стрелка: Взмах +Artistic Effects Художественные эффекты +AutoCorrect Options Параметры автозамены +Bean Фасолина +Borders Границы +Bounce Left Отскок влево +Bounce Right Отскок вправо +Browse for Themes… Обзор тем… +Callout: Bent Line Выноска: Ломаная линия +Callout: Bent Line with Accent Bar Выноска: Ломаная линия с акцентной полосой +Callout: Bent Line with Border and Accent Bar Выноска: Ломаная линия с контуром и акцентной полосой +Callout: Bent Line with No Border Выноска: Ломаная линия без контура +Callout: Double Bent Line Выноска: Двойная ломаная линия +Callout: Double Bent Line with Accent Bar Выноска: Двойная ломаная линия с акцентной полосой +Callout: Double Bent Line with Border and Accent Bar Выноска: Двойная ломаная линия с контуром и акцентной полосой +Callout: Double Bent Line with No Border Выноска: Двойная ломаная линия без контура +Callout: Left-Right Arrow Выноска: Стрелка влево-вправо +Callout: Line with Accent Bar Выноска: Линия с акцентной полосой +Callout: Line with Border and Accent Bar Выноска: Линия с контуром и акцентной полосой +Callout: Line with No Border Выноска: Линия без контура +Callout: Quad Arrow Выноска: Четырехсторонняя стрелка +Callout: Up-Down Arrow Выноска: Стрелка вверх-вниз +Cell Margins Поля ячейки +Change Colors Изменить цвета +Change Layout Изменить макет +Change Picture… Изменить рисунок… +Change Spelling Изменить написание +Chart Marker: Cross Lines Маркер диаграммы: Крест из линий +Chart Marker: Plus Lines Маркер диаграммы: Плюс из линий +Chart Marker: Star Lines Маркер диаграммы: Звезда из линий +Color At Цвет в точке +Commit Composition Подтвердить ввод +Compare Сравнить +Compare… Сравнить… +Compose Text Составить текст +Compress Pictures Сжать рисунки +Contract Сжатие +Convert to Shapes Преобразовать в фигуры +Convert to SmartArt Преобразовать в SmartArt +Convert to Text Преобразовать в текст +Corner Tabs: Quarter Circles Фотоуголки: Четверть круга +Corner Tabs: Squares Фотоуголки: Квадраты +Corner Tabs: Triangles Фотоуголки: Треугольники +Crescent Moon Полумесяц +Curved Square Изогнутый квадрат +Decaying Wave Затухающая волна +Delete Guide Удалить направляющую +Delete Point Удалить точку +Demote Понизить уровень +Diagonal Down Right Вниз по диагонали вправо +Diagonal Up Right Вверх по диагонали вправо +Draw Table Нарисовать таблицу +dropped file перетащенный файл +Edit Photo Album… Изменить фотоальбом… +Edit Points Изменить точки +Edit SmartArt Text Изменить текст SmartArt +End Review Завершить проверку +Find Найти +Flowchart: Offline Storage Блок-схема: Автономное хранилище +Fonts in Presentation Шрифты в презентации +Font… Шрифт… +Football Регбийный мяч +Gear: 6 Teeth Шестерня: 6 зубьев +Gear: 9 Teeth Шестерня: 9 зубьев +Grid and Guides Сетка и направляющие +Grid Options… Параметры сетки… +Handout Placeholders Заполнители выдачи +Heartbeat Сердцебиение +Hex D Шестиугольник снизу +Hex L Шестиугольник слева +Hex R Шестиугольник справа +Hex U Шестиугольник сверху +Horizontal Figure 8 Горизонтальная восьмерка +i. ii. iii. i. ii. iii. +Icon Gallery Галерея значков +Info Сведения +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Рукописный ввод в фигуру: превращает нарисованные линии, прямоугольники, овалы и треугольники в фигуры +Insert Picture in SmartArt Вставить рисунок в SmartArt +Insert Picture in SmartArt… Вставить рисунок в SmartArt… +Insert Synonym Вставить синоним +Layout Placeholders Заполнители макета +Line: Rising Линия: Восходящая +Loop de Loop Мертвая петля +Move Guide Переместить направляющую +Move Handle Переместить маркер +Move Point Переместить точку +Neutron Нейтрон +New Window Новое окно +Next Comment Следующий комментарий +No comments. Комментариев нет. +no presentation open Нет открытой презентации +no slides Нет слайдов +no text insertion point Нет точки ввода текста +Notes Placeholders Заполнители заметок +nothing selected Ничего не выбрано +nothing to redo Нет действий для повтора +nothing to undo Нет действий для отмены +Open Открыть +Particles In Частицы, появление +Particles Out Частицы, исчезновение +Paste Special Специальная вставка +Paste Special… Специальная вставка… +Peanut Арахис +Peek Out Подглядывание наружу +Photo Album… Фотоальбом… +Pick a design for this slide. Ideas are generated on your device. Выберите дизайн для этого слайда. Идеи генерируются на вашем устройстве. +Picture Style Gallery Галерея стилей рисунков +Point Type Тип точки +Points Точки +Preserve Сохранить +Preview Animations Просмотр анимации +Previous Comment Предыдущий комментарий +Print Печать +Print… Печать… +Promote Повысить уровень +Quarter Wedge Четверть клина +Quick Access Toolbar Панель быстрого доступа +Recolor Перекрасить +Recolor Gallery Галерея перекраски +Remove Shape Удалить фигуру +Replace Заменить +Replace Fonts Замена шрифтов +Replace… Заменить… +Rescan Installed Fonts Пересканировать установленные шрифты +Reuse Slides… Повторное использование слайдов… +Revisions Исправления +Ribbon: Curved and Tilted Down Лента: изогнутая с наклоном вниз +Ribbon: Curved and Tilted Up Лента: изогнутая с наклоном вверх +Ribbon: Left-Right Fold Лента: сгиб влево-вправо +S Curve 1 S-кривая 1 +S Curve 2 S-кривая 2 +select text or a shape Выберите текст или фигуру +select two or more objects Выберите два или более объектов +Set Transparent Color Установить прозрачный цвет +Set Zoom Задать масштаб +Sine Wave Синусоида +Single L Одиночный слева +Single R Одиночный справа +Sink Down Погружение +size (pt) размер (пт) +Size and Position… Размер и положение… +SmartArt Styles Стили SmartArt +Smooth Corners Скругленные углы +Sound Звук +Spelling Dictionary Орфографический словарь +Spiral Left Спираль влево +Spiral Right Спираль вправо +Spring Пружина +Stairs Down Ступени вниз +Starter Templates Стартовые шаблоны +Strips In Полосы, появление +Strips Out Полосы, исчезновение +Swoosh Взмах +Table Eraser Ластик таблиц +Tabs… Табуляция… +Text Pane Область текста +Text Transform Преобразовать текст +Text Transparency Прозрачность текста +tOGGLE cASE иЗМЕНИТЬ рЕГИСТР +Trapezoid: Uneven Sides Трапеция: Неравные стороны +unknown interface language Неизвестный язык интерфейса +Unlock Разблокировать +Variant Gallery Галерея вариантов +Variants Варианты +Vertical Figure 8 Вертикальная восьмерка +Zigzag Зигзаг + (not checked) (не проверено) +4 Point Star Звезда с 4 лучами +5 Point Star Звезда с 5 лучами +6 Point Star Звезда с 6 лучами +8 Point Star Звезда с 8 лучами +{ch} Bullet {ch} Маркер +{f} (Body) {f} (Основной текст) +{f} (Headings) {f} (Заголовки) +{name}: DeckCraft can't open this kind of file {name}: DeckCraft не может открыть файл этого типа +{n} Column{} {n} Столбец{} +{r} pt {r} пт +{r} pt glow Свечение {r} пт +{w} pt {w} пт +{} ({} slides) {} ({} слайдов) +{} Slide Master Образец слайдов {} +{} contributors · {} commits Участники: {} · Коммиты: {} +{} presentations {} презентаций +{}x{} Table Таблица {}×{} +“{}” is not available yet. «{}» пока недоступно. +−Bin −Интервал +▶ Play All ▶ Воспроизвести все +◀ Previous ◀ Назад +✏ on ✏ включено diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv new file mode 100644 index 000000000..fe8a21a20 --- /dev/null +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -0,0 +1,1408 @@ +# Ukrainian interface catalog. English sourcetranslation; \n denotes a line break. +# Contributor-original translation, MIT OR Apache-2.0. + Fixed date (empty = update automatically): Фіксована дата (порожнє поле = автоматичне оновлення): + Footer text: Текст нижнього колонтитула: + Present Показати + pt пт + — Edited — Змінено +"Not Allowed" Symbol Знак «Не дозволено» +% of all commits % усіх комітів ++ New Comment + Новий коментар ++ New Slide + Новий слайд ++ Row + Рядок ++ Series + Ряд даних ++Bin +Бін +100% Stacked Bar Нормована лінійчата з накопиченням +100% Stacked Column Нормована стовпчаста з накопиченням +35mm Slides Слайди 35 мм +@ribbon:Home Основне +@ribbon:Insert Вставлення +@{}: {} PRs, {} commits, +{} / −{} lines (Δ {}), +{} / −{} binary assets, {} – {} @{}: запити на злиття: {}, коміти: {}, рядки: +{} / −{} (Δ {}), двійкові ресурси: +{} / −{}, {} – {} +A3 Paper (297x420 mm) Папір A3 (297×420 мм) +A4 Paper (210x297 mm) Папір A4 (210×297 мм) +Aa Aa +Abc Abc +About Про програму +About DeckCraft Про DeckCraft +Accent 1 Акцент 1 +Accent 2 Акцент 2 +Accent 3 Акцент 3 +Accent 4 Акцент 4 +Accent 5 Акцент 5 +Accent 6 Акцент 6 +Accessibility Checker Перевірка доступності +Across Поперек +Action Дія +Action Button: Custom Кнопка дії: Власна +Action Button: Document Кнопка дії: Документ +Action Button: Get Information Кнопка дії: Отримати відомості +Action Button: Go Back Кнопка дії: Повернутися +Action Button: Go Back or Previous Кнопка дії: Назад або до попереднього +Action Button: Go Forward or Next Кнопка дії: Уперед або до наступного +Action Button: Go Home Кнопка дії: На початок +Action Button: Go to Beginning Кнопка дії: До початку +Action Button: Go to End Кнопка дії: До кінця +Action Button: Help Кнопка дії: Довідка +Action Button: Sound Кнопка дії: Звук +Action Button: Video Кнопка дії: Відео +Action Button: {k} Кнопка дії: {k} +Action Buttons Кнопки дій +Add Animation Додати анімацію +Add Section Додати розділ +Add\nAnimation Додати анімацію +Address: Адреса: +Adjust Shape Змінити фігуру +After Previous Після попереднього +After: Після: +Airplane Літак +Align Вирівняти +Align Bottom Вирівняти за нижнім краєм +Align Center Вирівняти по центру +Align Left Вирівняти за лівим краєм +Align Middle Вирівняти посередині +Align Right Вирівняти за правим краєм +Align Text Вирівняти текст +Align Top Вирівняти за верхнім краєм +Alt Text Альтернативний текст +Alt+ Alt+ +Alt+F9 Alt+F9 +Alt\nText Альтернативний текст +An open-source, clean-room project. Not affiliated with Microsoft. Незалежний проєкт із відкритим кодом. Не пов’язаний із Microsoft. +Angle Кут +Animation Gallery Галерея анімації +Animation Pane Панель анімації +Animation Styles Стилі анімації +Animation\nPane Панель анімації +Animations Анімації +Animation Painter Копіювання анімації +Apply Animation Застосувати анімацію +Play/Pause GIF Відтворити/призупинити GIF +Animations on Slide Анімації на слайді +Appear Поява +Apply Застосувати +Apply To All Застосувати до всіх +Apply to All Застосувати до всіх +Apply\nTo All Застосувати до всіх +Arc Дуга +Arcs Дуги +Area З областями +Arrange Упорядкувати +Arrow Стрілка +Arrow at end Стрілка в кінці +Arrow at start Стрілка на початку +Arrow: Bent Стрілка: Зігнута +Arrow: Bent-Up Стрілка: Зігнута вгору +Arrow: Chevron Стрілка: Шеврон +Arrow: Down Стрілка: Униз +Arrow: Left Стрілка: Ліворуч +Arrow: Left-Right Стрілка: Ліворуч і праворуч +Arrow: Left-Right-Up Стрілка: Ліворуч, праворуч і вгору +Arrow: Left-Up Стрілка: Ліворуч і вгору +Arrow: Notched Right Стрілка: Праворуч із вирізом +Arrow: Pentagon Стрілка: П’ятикутник +Arrow: Quad Стрілка: У чотири боки +Arrow: Right Стрілка: Праворуч +Arrow: Striped Right Стрілка: Смугаста праворуч +Arrow: U-Turn Стрілка: Розворот +Arrow: Up Стрілка: Угору +Arrow: Up-Down Стрілка: Угору й униз +Arrows Стрілки +Arrows at both ends Стрілки на обох кінцях +As One Object Як один об’єкт +Audio Аудіо +Audio from File… Аудіо з файлу… +AutoCorrect as you type Автовиправлення під час введення +Autofit Автоматичний добір +Automatic Автоматично +B4 (ISO) Paper (250x353 mm) Папір B4 (ISO) (250×353 мм) +B5 (ISO) Paper (176x250 mm) Папір B5 (ISO) (176×250 мм) +Background Тло +Background Styles Стилі тла +Background\nStyles Стилі тла +Backspace Backspace +Banded Columns Смугасті стовпці +Banded Rows Смугасті рядки +Banner Стрічка +Basic Cycle Простий цикл +Basic List Простий список +Basic Process Простий процес +Basic Shapes Основні фігури +Before text (in): Перед текстом (дюйми): +Bevel Скіс +Binary assets added Додані двійкові ресурси +Binary assets removed Видалені двійкові ресурси +Black Left Через чорний ліворуч +Black Pen Чорне перо +Black Right Через чорний праворуч +Blinds Жалюзі +Block Arc Блокова дуга +Block Arrows Блокові стрілки +Blue Синій +Blue Pen Синє перо +Bold Напівжирний +Bold Flash Спалах напівжирного +Both Обидва +Bottom Низ +Bounce Відскок +Box Коробка +Box In Коробка всередину +Box Out Коробка назовні +Box and Whisker Ящик із вусами +Brightness Яскравість +Brightness {:+}% Яскравість {:+}% +Bring Forward Перемістити вперед +Bring to Front На передній план +Bring\nForward Перемістити вперед +Browsed at a kiosk (full screen) Перегляд у кіоску (повноекранний) +Browsed by an individual (window) Індивідуальний перегляд (у вікні) +Bubble Бульбашкова +Bullets Маркери +Burst Спалах +By Paragraph За абзацами +Callout: Down Arrow Виноска: Стрілка вниз +Callout: Left Arrow Виноска: Стрілка ліворуч +Callout: Line Виноска: Лінія +Callout: Right Arrow Виноска: Стрілка праворуч +Callout: Up Arrow Виноска: Стрілка вгору +Callouts Виноски +Cameo Камео +Camera capture is not available yet Захоплення з камери ще недоступне +Cancel Скасувати +Capitalize Each Word Кожне слово з великої літери +Caps Великі літери +Center По центру +Centered По центру +Change Case Змінити регістр +Change Chart Type Змінити тип діаграми +Change Picture Змінити зображення +Change Shape Змінити фігуру +Change\nChart Type Змінити тип діаграми +Character Spacing Міжсимвольний інтервал +Characters Символи +Chart Діаграма +Chart Data Дані діаграми +Chart Design Оформлення діаграми +Chart Elements Елементи діаграми +Chart… Діаграма… +Check Accessibility Перевірити доступність +Check\nAccessibility Перевірити доступність +Checkerboard Шахова дошка +Chevron Шеврон +Choose a SmartArt Graphic Виберіть графіку SmartArt +Chord Хорда +Circle Коло +Circle In Коло всередину +Circle Out Коло назовні +Clear All Formatting Очистити все форматування +Click a symbol to insert it at the insertion point. Натисніть символ, щоб вставити його в позиції курсора. +Click icon to add SmartArt graphic Натисніть піктограму, щоб додати графіку SmartArt +Click icon to add chart Натисніть піктограму, щоб додати діаграму +Click icon to add media Натисніть піктограму, щоб додати медіа +Click icon to add picture Натисніть піктограму, щоб додати зображення +Click icon to add table Натисніть піктограму, щоб додати таблицю +Click to add first slide Натисніть, щоб додати перший слайд +Click to add notes Натисніть, щоб додати примітки +Click to add subtitle Натисніть, щоб додати підзаголовок +Click to add text Натисніть, щоб додати текст +Click to add title Натисніть, щоб додати заголовок +Click to edit Master text styles Натисніть, щоб змінити стилі тексту зразка +Click to edit Master title style Натисніть, щоб змінити стиль заголовка зразка +Clock Годинник +Clockwise За годинниковою стрілкою +Close Закрити +Close Master View Закрити режим зразка +Close\nMaster View Закрити режим зразка +Cloud Хмара +Clustered Bar Групована лінійчата +Clustered Column Групована стовпчаста +Cmd+ Cmd+ +Cmd+, Cmd+, +Cmd+- Cmd+- +Cmd+= Cmd+= +Cmd+F1 Cmd+F1 +Cmd+Shift+P Cmd+Shift+P +Collapse the Ribbon Згорнути стрічку +Color Колір +Color Pulse Пульсація кольору +Colors Кольори +Columns Стовпці +Comb Гребінка +Combo Комбінована +Command Palette Палітра команд +Comment Коментар +Comments Коментарі +Commits Коміти +Community Links Посилання спільноти +Company Компанія +Complementary Color Доповняльний колір +Connect Shapes З’єднати фігури +Connection Sites Точки з’єднання +Connector: Curved З’єднувач: кривий +Connector: Elbow З’єднувач: кутовий +Connector: Elbow (one bend) З’єднувач: кутовий (один згин) +Content Вміст +Contrast Контрастність +Contrast {:+}% Контраст {:+}% +Contributors Учасники +Conveyor Конвеєр +Copy Копіювати +Corrections Корекція +Couldn't save AutoRecover information: {e} Не вдалося зберегти дані автоматичного відновлення: {e} +Counter Clockwise Проти годинникової стрілки +Cover Накриття +Create Створити +Crop Обітнути +Crop 10% each side Обітнути на 10% з кожного боку +Crop 20% each side Обітнути на 20% з кожного боку +Crop to Shape Обітнути за фігурою +Cross Хрест +Crush Зминання +Ctrl+ Ctrl+ +Cube Куб +Currency Валюта +Curtains Штори +Custom Довільний +Custom Path Власний шлях +Custom Show Власний показ +Custom Show 1 Власний показ 1 +Custom Shows Власні покази +Custom Slide Show Власний показ слайдів +Custom\nShow Власний показ +Cut Вирізати +Cylinder Циліндр +Dark Blue Темно-синій +Dark Mode Темний режим +Dark Red Темно-червоний +Dark appearance Темне оформлення +Dark\nMode Темний режим +Darken Затемнення +Dash Штрих +Dash Dot Штрих і крапка +Dashes Штрихи +Database База даних +Date Дата +Date & Time Дата й час +Date &\nTime Дата й час +Date and Time Дата й час +Date and time Дата й час +Decagon Десятикутник +Decision Рішення +DeckCraft DeckCraft +Decrease Font Size Зменшити розмір шрифту +Decrease List Level Знизити рівень списку +Delay: Затримка: +Delete Видалити +Delete Columns Видалити стовпці +Delete Comment Видалити коментар +Delete Layout Видалити макет +Delete Rows Видалити рядки +Delete Slide Видалити слайд +Delete Table Видалити таблицю +Delete Text Видалити текст +Desaturate Знебарвити +Deselect Скасувати вибір +Design Оформлення +Design Ideas Ідеї оформлення +Design\nIdeas Ідеї оформлення +Deutsch Deutsch +Diagonal Stripe Діагональна смуга +Diamond Ромб +Diamond In Ромб усередину +Diamond Out Ромб назовні +Direction Напрямок +Disappear Зникнення +Discard Recovered Presentations Відкинути відновлені презентації +Display name Відображуване ім'я +Dissolve Розчинення +Dissolve In Поступова поява +Dissolve Out Поступове зникнення +Distribute Розподілити +Distribute Columns Розподілити стовпці +Distribute Horizontally Розподілити горизонтально +Distribute Rows Розподілити рядки +Distribute Vertically Розподілити вертикально +Division Sign Знак ділення +Do not Autofit Без автоматичного добору +Do you want to save the changes you made to {what}? Зберегти зміни, внесені до {what}? +Document Документ +Dodecagon Дванадцятикутник +Don't Save Не зберігати +Don't show on title slide Не показувати на титульному слайді +Done Готово +Donut Кільце +Doors Двері +Double Brace Подвійна фігурна дужка +Double Bracket Подвійна квадратна дужка +Double Wave Подвійна хвиля +Doughnut Кільцева +Down Униз +Drape Завіса +Draw Малювання +Drop Shadow Rectangle Прямокутник із тінню +Duplicate Дублювати +Duplicate Selected Slides Дублювати вибрані слайди +Duplicate Slide Дублювати слайд +Duration: Тривалість: +Dynamic Content Динамічний вміст +Edit Редагування +Edit Alt Text… Змінити альтернативний текст… +Edit Data Змінити дані +Edit Shape Змінити фігуру +Edit Text Редагувати текст +Edit the data: first row = series names, first column = categories. Змініть дані: перший рядок — назви рядів, перший стовпець — категорії. +Edit\nData Змінити дані +Edit\nShape Змінити фігуру +Editing Редагування +Effect Options Параметри ефекту +Effect\nOptions Параметри ефекту +Effects Ефекти +Email Address Адреса електронної пошти +Email address: Адреса електронної пошти: +Emphasis Виділення +End Кінець +End Show Завершити показ +End of slide show Кінець показу слайдів +End of slide show, click to exit. Кінець показу слайдів. Натисніть, щоб вийти. +End trim (s): Обрізання в кінці (с): +English (United Kingdom) Англійська (Велика Британія) +English (United States) Англійська (США) +Enter Enter +Entrance Поява +Equals Дорівнює +Equation Рівняння +Equation Shapes Фігури рівнянь +Eraser Гумка +Escape Escape +Español Español +Exciting Виразні +Exit Зникнення +Expand Розгорнути +Explosion: 14 Points Спалах: 14 променів +Explosion: 8 Points Спалах: 8 променів +Export Експорт +Export the presentation as: Експортувати презентацію як: +Exported {path} Експортовано: {path} +Export… Експортувати… +Fade Послабити +Fade in (s): Поступова поява (с): +Fade out (s): Поступове зникнення (с): +Fall Over Падіння +Ferris Wheel Оглядове колесо +File Файл +Fill Заливка +Fill & Line Заливка й лінія +Fill Color Колір заливки +Filled Radar Заповнена пелюсткова +Find… Знайти… +First Перший +First Column Перший стовпець +First Slide Перший слайд +First commit Перший коміт +Fit Умістити +Fit slide to current window Підігнати слайд до поточного вікна +Fit to Window Умістити у вікні +Fit to\nWindow Умістити у вікні +Flash Спалах +Flip Віддзеркалити +Flip Horizontal Віддзеркалити горизонтально +Flip Vertical Віддзеркалити вертикально +Float In Плавна поява +Float Out Плавне зникнення +Flowchart Блок-схема +Flowchart: Alternate Process Блок-схема: Альтернативний процес +Flowchart: Card Блок-схема: Картка +Flowchart: Collate Блок-схема: Зіставлення +Flowchart: Connector Блок-схема: З’єднувач +Flowchart: Data Блок-схема: Дані +Flowchart: Decision Блок-схема: Рішення +Flowchart: Delay Блок-схема: Затримка +Flowchart: Direct Access Storage Блок-схема: Сховище прямого доступу +Flowchart: Display Блок-схема: Екран +Flowchart: Document Блок-схема: Документ +Flowchart: Extract Блок-схема: Видобування +Flowchart: Internal Storage Блок-схема: Внутрішнє сховище +Flowchart: Magnetic Disk Блок-схема: Магнітний диск +Flowchart: Manual Input Блок-схема: Ручне введення +Flowchart: Manual Operation Блок-схема: Ручна операція +Flowchart: Merge Блок-схема: Об’єднання +Flowchart: Multidocument Блок-схема: Кілька документів +Flowchart: Off-page Connector Блок-схема: З’єднувач між сторінками +Flowchart: Or Блок-схема: Або +Flowchart: Predefined Process Блок-схема: Визначений процес +Flowchart: Preparation Блок-схема: Підготовка +Flowchart: Process Блок-схема: Процес +Flowchart: Punched Tape Блок-схема: Перфострічка +Flowchart: Sequential Access Storage Блок-схема: Сховище послідовного доступу +Flowchart: Sort Блок-схема: Сортування +Flowchart: Stored Data Блок-схема: Збережені дані +Flowchart: Summing Junction Блок-схема: Вузол підсумовування +Flowchart: Terminator Блок-схема: Початок/кінець +Fly In Влітати +Fly Out Вилітання +Fly Through Пролітання +Folded Corner Загнутий кут +Follow the layout Відповідно до макета +Followed Hyperlink Відвідане гіперпосилання +Font Шрифт +Font Color Колір шрифту +Font Size Розмір шрифту +Fonts Шрифти +Footer Нижній колонтитул +Foreground Передній план +Format Формат +Format Background Формат тла +Format Background… Формат тла… +Format Painter Копіювання формату +Format Painter (double-click to keep it on) Копіювання формату (подвійне натискання для постійного застосування) +Format Pane Панель форматування +Format Shape Формат фігури +Format Shape… Формат фігури… +Format\nBackground Формат тла +Format\nPane Панель форматування +Formatting State Стан форматування +Fracture Розлом +Frame Рамка +Français Français +Freeform Довільна фігура +From Від +From Beginning Від початку +From Bottom Знизу +From Bottom Left Знизу ліворуч +From Bottom Right Знизу праворуч +From Current Slide Від поточного слайда +From Left Зліва +From Right Справа +From Top Згори +From Top Left Згори ліворуч +From Top Right Згори праворуч +From bottom left Знизу ліворуч +From bottom right Знизу праворуч +From center Від центра +From top left Згори ліворуч +From top right Згори праворуч +From\nBeginning Від початку +From\nCurrent Slide Від поточного слайда +Full Повна +Full Page Slides Слайди на всю сторінку +Funnel Лійкова +Gallery Галерея +General Загальні +Get Text Отримати текст +Glitter Блиск +Glow Світіння +Go to Перейти +Go to Slide Перейти до слайда +Grab bag Випадкова добірка +Gradient fill Градієнтна заливка +Gradient stops Опорні точки градієнта +Gradient… Градієнт… +Grayscale Градації сірого +Greek Грецька +Green Зелений +Gridlines Лінії сітки +Group Згрупувати +Group Objects Згрупувати об’єкти +Grow & Turn Збільшення й обертання +Grow/Shrink Збільшення/зменшення +Guides Напрямні +Half Половина +Half Frame Половина рамки +Handout Master Зразок видачі +Handout Master (coming soon) Зразок видачі (незабаром) +Handout\nMaster Зразок видачі +Handouts (1 slide per page) Видача (1 слайд на сторінку) +Handouts (2 slides per page) Видача (2 слайди на сторінку) +Handouts (3 slides per page) Видача (3 слайди на сторінку) +Handouts (4 slides per page) Видача (4 слайди на сторінку) +Handouts (6 slides per page) Видача (6 слайдів на сторінку) +Handouts (9 slides per page) Видача (9 слайдів на сторінку) +Header Верхній колонтитул +Header & Footer Колонтитули +Header &\nFooter Колонтитули +Header Row Рядок заголовка +Header and Footer Колонтитули +Header and Footer… Колонтитули… +Heart Серце +Height Висота +Height (in): Висота (дюйми): +Height: Висота: +Help Довідка +Heptagon Семикутник +Hexagon Шестикутник +Hide All Приховати все +Hide Background Graphics Приховати графіку тла +Hide During Show Приховати під час показу +Hide Slide Приховати слайд +Hide background graphics Приховати графіку тла +Hide\nSlide Приховати слайд +Hierarchy Ієрархія +High Висока +Highlighter Маркер виділення +Histogram Гістограма +Home Початковий екран +Honeycomb Стільники +Horizontal Горизонтально +Horz In Горизонтально всередину +Horz Out Горизонтально назовні +How would you describe this object and its context to someone who is blind or has low vision? Як би ви описали цей об’єкт та його контекст людині з порушенням зору? +Hyperlink Гіперпосилання +Icons Піктограми +In Усередину +In Bounce Усередину з відскоком +Include hidden slides Включити приховані слайди +Increase Font Size Збільшити розмір шрифту +Increase List Level Підвищити рівень списку +Ink to Math Рукописне введення в рівняння +Ink to Math (coming soon) Рукописне введення в рівняння (незабаром) +Ink to Shape Рукописне введення у фігуру +Ink to Shape (coming soon) Рукописне введення у фігуру (незабаром) +Ink to Text Рукописне введення в текст +Ink to Text (coming soon) Рукописне введення в текст (незабаром) +Ink to\nMath Рукописне введення в рівняння +Ink to\nShape Рукописне введення у фігуру +Ink to\nText Рукописне введення в текст +Inner Внутрішня +Insert Вставити +Insert Above Вставити вище +Insert Below Вставити нижче +Insert Hyperlink Вставити гіперпосилання +Insert Layout Вставити макет +Insert Left Вставити ліворуч +Insert Placeholder Вставити заповнювач +Insert Right Вставити праворуч +Insert Table Вставити таблицю +Insert Table… Вставити таблицю… +Insert picture from file… Вставити зображення з файлу… +Insert\nAbove Вставити вище +Insert\nBelow Вставити нижче +Insert\nLayout Вставити макет +Insert\nLeft Вставити ліворуч +Insert\nPlaceholder Вставити заповнювач +Insert\nRight Вставити праворуч +Inspect Presentation Переглянути дані презентації +Inspect Shape Переглянути дані фігури +Inspect Slide Переглянути дані слайда +Interface Language Мова інтерфейсу +Interface language: Мова інтерфейсу: +Interface size Розмір інтерфейсу +Isosceles Triangle Рівнобедрений трикутник +Italiano Italiano +Italic Курсивний +JPEG image (current slide) Зображення JPEG (поточний слайд) +Join our community on Discord Приєднуйтеся до нашої спільноти в Discord +Join the ArtCraft community on Discord Приєднуйтеся до спільноти ArtCraft у Discord +Justify По ширині +L-Shape Г-подібна фігура +Language Мова +Last Останній +Last Column Останній стовпець +Last Slide Останній слайд +Last commit Останній коміт +Layout Макет +Learn More Докладніше +Learn\nMore Докладніше +Ledger Paper (11x17 in) Папір Ledger (11×17 дюймів) +Left Ліворуч +Left Brace Ліва фігурна дужка +Left Bracket Ліва квадратна дужка +Letter Paper (8.5x11 in) Папір Letter (8,5×11 дюймів) +Liberation Serif Liberation Serif +Light Blue Світло-синій +Light Green Світло-зелений +Light/Dark appearance Світле/темне оформлення +Lighten Освітлення +Lightning Блискавка +Lightning Bolt Блискавка +Line Лінія +Line Color Колір лінії +Line Spacing Міжрядковий інтервал +Line Spacing Options… Параметри міжрядкового інтервалу… +Line delta Різниця рядків +Line spacing (lines): Міжрядковий інтервал (рядки): +Line with Markers Лінійна з маркерами +Linear Лінійний +Lines Лінії +Lines +/− Рядки +/− +Lines added Додані рядки +Lines deleted Видалені рядки +Link Посилання +Link… Посилання… +List Commands Список команд +Lock Заблокувати +Long Dash Довгий штрих +Long Dash Dot Довгий штрих і крапка +Loop continuously until 'Esc' Повторювати безперервно до натискання «Esc» +Loop until Stopped Повторювати до зупинки +Loops Петлі +Loose Розріджений +Low Низька +MIT OR Apache-2.0 · © 2026 ArtCraft Team and the DeckCraft contributors MIT OR Apache-2.0 · © 2026 Команда ArtCraft та учасники DeckCraft +Margins (pt) Поля (пт) +Mark as decorative Позначити як декоративний +Mark selected text as: Позначити вибраний текст як: +Math Математика +Matrix Матриця +Maximize content (else ensure fit) Збільшити вміст (інакше вмістити) +Media Медіа +Media Info Відомості про медіа +Medium Середній +Merge Cells Об’єднати клітинки +Merge Shapes Об’єднати фігури +Merge\nCells Об’єднати клітинки +Merge\nShapes Об’єднати фігури +Merged PRs Об’єднані запити на злиття +Middle Посередині +Minus Sign Знак мінуса +Model Модель +Models Моделі +Moon Місяць +More Colors… # Інші кольори… # +Morph Трансформація +Motion Рух +Motion Paths Шляхи переміщення +Move Переміщення +Move Down Перемістити вниз +Move Insertion Point Перемістити курсор введення +Move Section Перемістити розділ +Move Section Down Перемістити розділ униз +Move Section Up Перемістити розділ угору +Move Slide Перемістити слайд +Move Up Перемістити вгору +Multiplication Sign Знак множення +Multiply Множення +Mute Вимкнути звук +Name Ім’я +Name (A–Z) Ім'я (А–Я) +Name: Назва: +New Comment Новий коментар +New Presentation Нова презентація +New Slide Новий слайд +New Slide (⇧⌘N) Новий слайд (⇧⌘N) +New presentation Нова презентація +New show name: Назва нового показу: +New\nComment Новий коментар +New\nSlide Новий слайд +Next Далі +Next Slide Наступний слайд +Next Window Наступне вікно +Next ▶ Далі ▶ +No Color Без кольору +No Fill Без заливки +No Glow Без світіння +No Outline Без обведення +No Reflection Без відбиття +No Shadow Без тіні +No Soft Edges Без розмиття країв +No accessibility issues found. People with disabilities should not have difficulty reading this document. Проблем доступності не виявлено. Люди з інвалідністю не повинні мати труднощів із читанням цього документа. +No comments on this slide. На цьому слайді немає коментарів. +No contributor data was built into this copy. У цю копію не вбудовано дані про учасників. +No fill Без заливки +No line Без лінії +No model credits were built into this copy. У цю копію не вбудовано дані про використані моделі. +No notes. Немає приміток. +No sound: {err} Немає звуку: {err} +None Немає +Normal Звичайний +Not Equal Не дорівнює +Not allowed Не дозволено +Notes Примітки +Notes Master Зразок приміток +Notes Master (coming soon) Зразок приміток (незабаром) +Notes Page Сторінка приміток +Notes Pages Сторінки приміток +Notes\nMaster Зразок приміток +Notes\nPage Сторінка приміток +Nudge Зсунути +Number of columns: Кількість стовпців: +Number of rows: Кількість рядків: +Numbering Нумерація +Object Color Колір об’єкта +Objects Об’єкти +Octagon Восьмикутник +On Click Після натискання +On Click of {name} Після натискання на {name} +On Click of… (none) Після натискання на… (немає) +On Mouse Click Після натискання мишею +On-screen Show (16:10) Екранний показ (16:10) +Open Data Відкрити дані +Open Dialog Відкрити діалог +Open Recovered Presentations Відкрити відновлені презентації +Open the sample deck Відкрити зразок презентації +Open… Відкрити… +Orange Помаранчевий +Orbit Орбіта +Order Objects Порядок об’єктів +Origami Оригамі +Out Назовні +Out Bounce Назовні з відскоком +Outer Зовнішня +Outline Структура +Outline (.txt) Структура (.txt) +Outline View Режим структури +Outline\nView Режим структури +Oval Овал +Oval ends Овальні кінці +Overhead Діапроєктор +PDF document (.pdf) Документ PDF (.pdf) +PNG images (all slides) Зображення PNG (усі слайди) +PNG images (current slide) Зображення PNG (поточний слайд) +PRs Запити на злиття +Page Curl Завертання сторінки +Page Setup… Параметри сторінки… +PageDown PageDown +PageUp PageUp +Pan Панорамування +Pane Панель +Paragraph Абзац +Paragraph… Абзац… +Parallelogram Паралелограм +Pareto Парето +Partial Circle Частина кола +Particles Частинки +Paste Вставити +Paste (⌘V) Вставити (⌘V) +Paste Formatting Вставити форматування +Paste and Match Formatting Вставити з відповідним форматуванням +Paste or type an outline. Unindented lines become slide titles; tab-indented lines become bullets. Вставте або введіть структуру. Рядки без відступу стають заголовками слайдів; рядки з відступом табуляції — пунктами списку. +Pasted image.png Вставлене зображення.png +Path Контур +Pattern fill Візерункова заливка +Pause Пауза +Peek In Визирання +Peel Off Відшарування +Pencil Олівець +Pentagon П’ятикутник +Perspective Перспектива +Pick a graphic; type one item per line. Виберіть графіку; введіть по одному елементу в рядку. +Pick a look for your slides. Ideas are generated on your device. Виберіть оформлення слайдів. Ідеї створюються на вашому пристрої. +Picture Зображення +Picture Format Формат зображення +Picture Styles Стилі зображення +Picture from File… Зображення з файлу… +Picture or texture fill Заливка зображенням або текстурою +Picture\nStyles Стилі зображення +Pictures Зображення +Pie Секторна +Pin Прикріпити +Placeholder colour Колір заповнювача +Plan\nBuild\nLaunch Планування\nСтворення\nЗапуск +Plaque Табличка +Play Відтворити +Play Across Slides Відтворювати на кількох слайдах +Play Full Screen Відтворювати на весь екран +Play Narrations Відтворювати звуковий супровід +Play from Current Slide Відтворити з поточного слайда +Play from Start Відтворити від початку +Play from Start (F5) Відтворити від початку (F5) +Play from\nCurrent Slide Відтворити з поточного слайда +Play from\nStart Відтворити від початку +Play/Pause Відтворити/призупинити +Playback Відтворення +Plus Плюс +Plus In Плюс усередину +Plus Out Плюс назовні +Plus Sign Знак плюса +Portrait (9:16) Портретний (9:16) +Português Português +Position Положення +Position Objects Позиція об’єктів +Position and Size Позиція та розмір +Post Надіслати +Poster Frame Кадр афіші +PowerPoint Presentation (.pptx) Презентація PowerPoint (.pptx) +Preferences Налаштування +Preferences… Налаштування… +Presentation Презентація +Presentations Презентації +Presentations and slide shows, rebuilt from scratch in pure Rust. Презентації та покази слайдів, створені з нуля мовою Rust. +Presented by a speaker (full screen) Доповідачем (повноекранний режим) +Presenter View Режим доповідача +Presenter View — DeckCraft Режим доповідача — DeckCraft +Presenter\nView Режим доповідача +Preset gradients Готові градієнти +Prestige Престиж +Preview Попередній перегляд +Previous Slide Попередній слайд +Print layout: Макет друку: +Properties Властивості +Pulse Пульсація +Punctuation Пунктуація +Purple Фіолетовий +Push Зсув +Pyramid Піраміда +Quick Styles Експрес-стилі +Quick\nStyles Експрес-стилі +Radar Пелюсткова +Radial Радіальний +Random Випадковий +Random Bars Випадкові смуги +Reading View Режим читання +Reading\nView Режим читання +Real name Справжнє ім'я +Recent Нещодавні +Record Запис +Recording narration needs audio capture (coming soon) Для запису звукового супроводу потрібне захоплення аудіо (незабаром) +Recovered Presentations Відновлені презентації +Recovered {} from the last session Відновлено {} з попереднього сеансу +Rectangle Прямокутник +Rectangle: Diagonal Corners Rounded Прямокутник: заокруглені діагональні кути +Rectangle: Diagonal Corners Snipped Прямокутник: зрізані діагональні кути +Rectangle: Rounded Corners Прямокутник: заокруглені кути +Rectangle: Single Corner Rounded Прямокутник: один заокруглений кут +Rectangle: Single Corner Snipped Прямокутник: один зрізаний кут +Rectangle: Top Corners One Rounded and One Snipped Прямокутник: один верхній кут заокруглений, інший зрізаний +Rectangle: Top Corners Rounded Прямокутник: заокруглені верхні кути +Rectangle: Top Corners Snipped Прямокутник: зрізані верхні кути +Rectangles Прямокутники +Rectangular Прямокутний +Red Червоний +Red Pen Червоне перо +Redo Повторити +Redo (⌘Y) Повторити (⌘Y) +Reflected Rounded Rectangle Заокруглений прямокутник із відбиттям +Reflection Відбиття +Regroup Перегрупувати +Regular Pentagon Правильний п’ятикутник +Rehearse Timings Репетиція часу показу +Rehearse\nTimings Репетиція часу показу +Remove Вилучити +Remove All Animations Видалити всі анімації +Remove All Sections Видалити всі розділи +Remove Animation Видалити анімацію +Remove Background Видалити тло +Remove Background (coming soon) Видалення тла (незабаром) +Remove Section Видалити розділ +Remove Section & Slides Видалити розділ і слайди +Remove stop Видалити опорну точку +Remove\nBackground Видалити тло +Rename Перейменувати +Rename Layout Перейменувати макет +Rename Section Перейменувати розділ +Rename Section… Перейменувати розділ… +Rename Slide Перейменувати слайд +Rename… Перейменувати… +Render Slide Візуалізувати слайд +Reopen Відкрити знову +Reorder Animation Змінити порядок анімації +Reorder Objects Змінити порядок об’єктів +Replace straight quotes with smart quotes Замінювати прямі лапки типографськими +Reply Відповісти +Reply… Відповісти… +Reset Скинути +Reset Background Скинути тло +Reset Crop Скинути обтинання +Reset Effects Скинути ефекти +Reset Picture Скинути зображення +Reset Slide Скинути слайд +Reset Slide Background Скинути тло слайда +Resize shape to fit text Змінити розмір фігури за текстом +Resolve Позначити як вирішений +Resolve Thread Завершити обговорення +Return Повернутися +Reveal Відкриття +Reverse the order Зворотний порядок +Revert Повернути попередню версію +Review Рецензування +Rewind after Playing Перемотати після відтворення +Ribbon Tab Вкладка стрічки +Ribbon: Tilted Down Стрічка: нахил униз +Ribbon: Tilted Up Стрічка: нахил угору +Right Праворуч +Right Brace Права фігурна дужка +Right Bracket Права квадратна дужка +Right Triangle Прямокутний трикутник +Right-to-Left Text Direction Напрямок тексту справа наліво +Ring Кільце +Ripple Брижі +Rise Up Підняття +Rotate Повернути +Rotate Left 90° Повернути ліворуч на 90° +Rotate Right 90° Повернути праворуч на 90° +Rotate all text 270° Повернути весь текст на 270° +Rotate all text 90° Повернути весь текст на 90° +Rotate with shape Повертати разом із фігурою +Rotation Обертання +Round Dot Кругла крапка +Rounded Diagonal Corner Заокруглений діагональний кут +Ruler Лінійка +Saturation Насиченість +Saturation {}% Насиченість {}% +Save Зберегти +Save (⌘S) Зберегти (⌘S) +Save As… Зберегти як… +Save AutoRecover Information Зберегти дані автоматичного відновлення +Save as Template… Зберегти як шаблон… +Save to Data Зберегти в дані +Saved Збережено +Saved {path} Збережено: {path} +Scatter Точкова +ScreenTip: Підказка: +Screenshot Знімок екрана +Screenshot (not available yet) Знімок екрана (ще недоступно) +Scroll: Horizontal Сувій: горизонтальний +Scroll: Vertical Сувій: вертикальний +Search commands (⇧⌘P) Пошук команд (⇧⌘P) +Search commands… Пошук команд… +Section Розділ +Seek Перейти до позиції +Select Виділення +Select All Виділити все +Select All Text Вибрати весь текст +Select Cells Вибрати клітинки +Select Objects Вибрати об’єкти +Select Paragraph Вибрати абзац +Select Slides Вибрати слайди +Select Text Вибрати текст +Select Word Вибрати слово +Select a chart first. Спочатку виберіть діаграму. +Select a shape to format it. Виберіть фігуру для форматування. +Select an object on the slide and add an animation from the Animations tab. Виберіть об’єкт на слайді та додайте анімацію на вкладці «Анімації». +Selection Виділення +Selection Pane Панель вибору +Selection Pane… Панель вибору… +Selection\nPane Панель вибору +Send Backward Перемістити назад +Send to Back На задній план +Send\nBackward Перемістити назад +Sentence case. Як у реченні. +Set Text Задати текст +Set Up Show… Налаштувати показ… +Set Up Slide Show Налаштувати показ слайдів +Set Up Slide Show… Налаштувати показ слайдів… +Set Up\nSlide Show Налаштувати показ слайдів +Set as Default Shape Установити як стандартну фігуру +Shading Затінення +Shadow Тінь +Shape Фігура +Shape Effects Ефекти фігури +Shape Fill Заливка фігури +Shape Format Формат фігури +Shape Gallery Галерея фігур +Shape Outline Обведення фігури +Shape Styles Стилі фігур +Shape {} Фігура {} +Shape\nStyles Стилі фігур +Shapes Фігури +Shift+ Shift+ +Shift+F9 Shift+F9 +Show Показати +Show All Показати всі +Show Comments Показати коментарі +Show Media Controls Показати елементи керування медіа +Show Slide Показати слайд +Show smart guides Показувати розумні напрямні +Show type Тип показу +Show without animation Показ без анімації +Show without narration Показ без звукового супроводу +Show/Hide Показати/приховати +Show\nComments Показати коментарі +Shred Подрібнення +Shrink & Turn Зменшення й обертання +Shrink text on overflow Зменшувати текст у разі переповнення +Simple Frame, White Проста біла рамка +Size Розмір +Size & Properties Розмір і властивості +Slide Master Зразок слайдів +Slide Number Номер слайда +Slide Show Показ слайдів +Slide Size Розмір слайда +Slide Sorter Сортувальник слайдів +Slide number Номер слайда +Slide timings recorded. Час показу слайдів записано. +Slide {:02}:{:04.1} Total {:02}:{:02} Слайд {:02}:{:04.1} Загалом {:02}:{:02} +Slide {} of {} Слайд {} з {} +Slide {}: {}{} Слайд {}: {}{} +Slide {}: “{w}” Слайд {}: «{w}» +Slide\nMaster Зразок слайдів +Slide\nNumber Номер слайда +Slide\nSize Розмір слайда +Slide\nSorter Сортувальник слайдів +Slides (e.g. 1,3,5): Слайди (наприклад, 1,3,5): +Slides from Outline Слайди зі структури +Slides from Outline… Слайди зі структури… +Slides sized for: Розмір слайдів для: +SmartArt SmartArt +Smile Усмішка +Smiley Face Усміхнене обличчя +Smoothly Плавно +Smoothly Left Плавно ліворуч +Smoothly Right Плавно праворуч +Snap objects to grid Прив’язувати об’єкти до сітки +Soft Edge Rectangle Прямокутник із розмитими краями +Soft Edges Розмиті краї +Solid Суцільний +Solid fill Суцільна заливка +Solid line Суцільна лінія +Sort Сортування +Source on GitHub Вихідний код на GitHub +Space Space +Spacing after (pt): Інтервал після (пт): +Spacing before (pt): Інтервал перед (пт): +Special — hanging (in): Спеціальний — виступ (дюйми): +Speech Мовлення +Speech Bubble: Oval Овальна мовна бульбашка +Speech Bubble: Rectangle Прямокутна мовна бульбашка +Speech Bubble: Rectangle with Corners Rounded Мовна бульбашка: прямокутник із заокругленими кутами +Spelling Орфографія +Spin Обертання +Spinner Кругове обертання +Split Розділення +Split Cells Розділити клітинки +Split\nCells Розділити клітинки +Square Квадрат +Square (1:1) Квадратний (1:1) +Square Dot Квадратна крапка +Stacked Накопичувальна +Stacked Area З областями з накопиченням +Stacked Bar Лінійчата з накопиченням +Stacked Column Стовпчаста з накопиченням +Stacked Line Лінійна з накопиченням +Standard (4:3) Стандартний (4:3) +Standard Colors Стандартні кольори +Star Зірка +Star: 10 Points Зірка: 10 променів +Star: 12 Points Зірка: 12 променів +Star: 16 Points Зірка: 16 променів +Star: 24 Points Зірка: 24 промені +Star: 32 Points Зірка: 32 промені +Star: 4 Points Зірка: 4 промені +Star: 5 Points Зірка: 5 променів +Star: 6 Points Зірка: 6 променів +Star: 7 Points Зірка: 7 променів +Star: 8 Points Зірка: 8 променів +Stars and Banners Зірки та стрічки +Start After Previous Почати після попереднього +Start Automatically Почати автоматично +Start On Click Почати після натискання +Start With Previous Почати разом із попереднім +Start a conversation Почніть розмову +Start time (s): Час початку (с): +Start: Початок: +Stealth end Вістря +Stock Біржова +Stop Зупинити +Stop Editing Text Завершити редагування тексту +Strikethrough Закреслення +Strips Смуги +Style {i} Стиль {i} +Subscript Підрядковий +Subtle Стримані +Sun Сонце +Sunburst Сонячні промені +Superscript Надрядковий +Surface Поверхнева +Switch Перемикання +Swivel Обертання +Symbol Символ +System language Мова системи +Tab Табуляція +Table Таблиця +Table Design Оформлення таблиці +Table Style Options Параметри стилю таблиці +Table Styles Стилі таблиці +Table… Таблиця… +Task Pane Панель завдань +Teardrop Крапля +Teeter Хитання +Text Текст +Text Box Текстове поле +Text Box Margins Поля текстового блока +Text Direction Напрямок тексту +Text Effects Текстові ефекти +Text Fill Заливка тексту +Text Highlight Color Колір виділення тексту +Text Options Параметри тексту +Text Outline Обведення тексту +Text Shadow Тінь тексту +Text/Background - Dark 1 Текст/тло — темний 1 +Text/Background - Dark 2 Текст/тло — темний 2 +Text/Background - Light 1 Текст/тло — світлий 1 +Text/Background - Light 2 Текст/тло — світлий 2 +Text\nBox Текстове поле +The spelling check is complete. No issues found. Перевірку правопису завершено. Помилок не виявлено. +Theme Colors Кольори теми +Theme Gallery Галерея тем +Themes Теми +Thesaurus Тезаурус +Thesaurus (coming soon) Тезаурус (незабаром) +This Document Цей документ +Thought Думка +Thought Bubble: Cloud Бульбашка думки: хмара +Through Black Через чорний +Tight Ущільнений +Timing Час показу +Top Верх +Total Row Рядок підсумку +Transition Перехід +Transition Gallery Галерея переходів +Transitions Переходи +Translate Перекласти +Translation needs a language model (not bundled) Для перекладу потрібна мовна модель (не входить до комплекту) +Transparency Прозорість +Trapezoid Трапеція +Treemap Деревоподібна +Triangle Трикутник +Trigger Умова запуску +Trim Обрізати +Trim Media Обрізати медіа +Turns Повороти +Type Тип +Type Text Ввести текст +Type an equation in linear form (e.g. a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). Введіть рівняння в лінійному вигляді (наприклад, a^2+b^2=c^2, x=(-b±√(b^2-4ac))/2a). +Uncover Відкривання +Underline Підкреслення +Undo Скасувати +Undo (⌘Z) Скасувати (⌘Z) +Ungroup Розгрупувати +Up Угору +Use Timings Використовувати час показу +Use timings, if present Використовувати час показу, якщо задано +Username Ім'я користувача +Version Версія +Version {} Версія {} +Vert In Вертикально всередину +Vert Out Вертикально назовні +Vertical Вертикально +Vertical alignment Вертикальне вирівнювання +Very Loose Дуже розріджений +Very Tight Дуже ущільнений +Video Відео +Video from File… Відео з файлу… +View Перегляд +Volume Гучність +Vortex Вихор +Waterfall Водоспадна +Wave Хвиля +Web Page or File Вебсторінка або файл +Wedge Клин +Weight Товщина +Wheel Колесо +Widescreen (13.333x7.5 in) Широкоекранний (13,333×7,5 дюймів) +Widescreen (16:9) Широкоекранний (16:9) +Width Ширина +Width (in): Ширина (дюйми): +Width: Ширина: +Width: Ширина: +Wind Вітер +Window Вікно +Wipe Витирання +With Previous Разом із попереднім +WordArt WordArt +WordArt style {} Стиль WordArt {} +Words Слова +Wrap Text in Shape Переносити текст у фігурі +Wrap text in shape Переносити текст у фігурі +Yellow Жовтий +Your changes will be lost if you don't save them. Якщо не зберегти, зміни будуть втрачені. +Your name (comments): Ваше ім’я (коментарі): +Zoom Масштаб +Zoom In Збільшити +Zoom Out Зменшити +Zoom… Масштаб… +a) b) c) a) b) c) +a. b. c. a. b. c. +Accept Revision Прийняти виправлення +Action Settings Параметри дії +Add Font Додати шрифт +Add Guide Додати напрямну +Add Point Додати точку +Add Shape Додати фігуру +Add to Dictionary Додати до словника +Align Cell Text Вирівняти текст клітинки +Apply Design Idea Застосувати ідею оформлення +Arrow: Circular Стрілка: Кругова +Arrow: Circular Counter-clockwise Стрілка: Кругова проти годинникової стрілки +Arrow: Circular Two-headed Стрілка: Кругова двостороння +Arrow: Curved Down Стрілка: Дугова вниз +Arrow: Curved Left Стрілка: Дугова ліворуч +Arrow: Curved Right Стрілка: Дугова праворуч +Arrow: Curved Up Стрілка: Дугова вгору +Arrow: Swoosh Стрілка: Свист +Artistic Effects Художні ефекти +AutoCorrect Options Параметри автовиправлення +Bean Квасолина +Borders Межі +Bounce Left Відскок ліворуч +Bounce Right Відскок праворуч +Browse for Themes… Огляд тем… +Callout: Bent Line Виноска: Зігнута лінія +Callout: Bent Line with Accent Bar Виноска: Зігнута лінія зі смугою акценту +Callout: Bent Line with Border and Accent Bar Виноска: Зігнута лінія з рамкою та смугою акценту +Callout: Bent Line with No Border Виноска: Зігнута лінія без рамки +Callout: Double Bent Line Виноска: Подвійна зігнута лінія +Callout: Double Bent Line with Accent Bar Виноска: Подвійна зігнута лінія зі смугою акценту +Callout: Double Bent Line with Border and Accent Bar Виноска: Подвійна зігнута лінія з рамкою та смугою акценту +Callout: Double Bent Line with No Border Виноска: Подвійна зігнута лінія без рамки +Callout: Left-Right Arrow Виноска: Стрілка ліворуч і праворуч +Callout: Line with Accent Bar Виноска: Лінія зі смугою акценту +Callout: Line with Border and Accent Bar Виноска: Лінія з рамкою та смугою акценту +Callout: Line with No Border Виноска: Лінія без рамки +Callout: Quad Arrow Виноска: Стрілка в чотири боки +Callout: Up-Down Arrow Виноска: Стрілка вгору й униз +Cell Margins Поля клітинки +Change Colors Змінити кольори +Change Layout Змінити макет +Change Picture… Змінити зображення… +Change Spelling Змінити написання +Chart Marker: Cross Lines Маркер діаграми: лінії хреста +Chart Marker: Plus Lines Маркер діаграми: лінії плюса +Chart Marker: Star Lines Маркер діаграми: лінії зірки +Color At Колір у точці +Commit Composition Завершити складання +Compare Порівняти +Compare… Порівняти… +Compose Text Складання тексту +Compress Pictures Стиснути зображення +Contract Стискання +Convert to Shapes Перетворити на фігури +Convert to SmartArt Перетворити на SmartArt +Convert to Text Перетворити на текст +Corner Tabs: Quarter Circles Кутові виступи: Чверті кіл +Corner Tabs: Squares Кутові виступи: Квадрати +Corner Tabs: Triangles Кутові виступи: Трикутники +Crescent Moon Місячний серп +Curved Square Заокруглений квадрат +Decaying Wave Затухаюча хвиля +Delete Guide Видалити напрямну +Delete Point Видалити точку +Demote Знизити рівень +Diagonal Down Right Діагональ униз праворуч +Diagonal Up Right Діагональ угору праворуч +Draw Table Малювати таблицю +dropped file перетягнутий файл +Edit Photo Album… Редагувати фотоальбом… +Edit Points Редагувати точки +Edit SmartArt Text Редагувати текст SmartArt +End Review Завершити рецензування +Find Знайти +Flowchart: Offline Storage Блок-схема: Автономне сховище +Fonts in Presentation Шрифти в презентації +Font… Шрифт… +Football М’яч +Gear: 6 Teeth Шестерня: 6 зубців +Gear: 9 Teeth Шестерня: 9 зубців +Grid and Guides Сітка й напрямні +Grid Options… Параметри сітки… +Handout Placeholders Заповнювачі видачі +Heartbeat Серцебиття +Hex D Шестикутник униз +Hex L Шестикутник ліворуч +Hex R Шестикутник праворуч +Hex U Шестикутник угору +Horizontal Figure 8 Горизонтальна вісімка +i. ii. iii. i. ii. iii. +Icon Gallery Галерея піктограм +Info Відомості +Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes Рукопис у фігуру: перетворює намальовані лінії, прямокутники, овали й трикутники на фігури +Insert Picture in SmartArt Вставити зображення в SmartArt +Insert Picture in SmartArt… Вставити зображення в SmartArt… +Insert Synonym Вставити синонім +Layout Placeholders Заповнювачі макета +Line: Rising Лінія: Висхідна +Loop de Loop Петля +Move Guide Перемістити напрямну +Move Handle Перемістити маркер +Move Point Перемістити точку +Neutron Нейтрон +New Window Нове вікно +Next Comment Наступний коментар +No comments. Коментарів немає. +no presentation open Немає відкритої презентації +no slides Немає слайдів +no text insertion point Немає позиції введення тексту +Notes Placeholders Заповнювачі приміток +nothing selected Нічого не вибрано +nothing to redo Немає дій для повторення +nothing to undo Немає дій для скасування +Open Відкрити +Particles In Частинки, поява +Particles Out Частинки, зникнення +Paste Special Спеціальна вставка +Paste Special… Спеціальна вставка… +Peanut Арахіс +Peek Out Визирання, зникнення +Photo Album… Фотоальбом… +Pick a design for this slide. Ideas are generated on your device. Виберіть дизайн для цього слайда. Ідеї створюються на вашому пристрої. +Picture Style Gallery Галерея стилів зображення +Point Type Тип точки +Points Точки +Preserve Зберегти +Preview Animations Попередній перегляд анімацій +Previous Comment Попередній коментар +Print Друк +Print… Друк… +Promote Підвищити рівень +Quarter Wedge Чверть клина +Quick Access Toolbar Панель швидкого доступу +Recolor Перефарбувати +Recolor Gallery Галерея перефарбування +Remove Shape Видалити фігуру +Replace Замінити +Replace Fonts Замінити шрифти +Replace… Замінити… +Rescan Installed Fonts Повторне сканування встановлених шрифтів +Reuse Slides… Повторне використання слайдів… +Revisions Виправлення +Ribbon: Curved and Tilted Down Стрічка: зігнута з нахилом униз +Ribbon: Curved and Tilted Up Стрічка: зігнута з нахилом угору +Ribbon: Left-Right Fold Стрічка: згин ліворуч і праворуч +S Curve 1 S-подібна крива 1 +S Curve 2 S-подібна крива 2 +select text or a shape Виберіть текст або фігуру +select two or more objects Виберіть два або більше об’єктів +Set Transparent Color Установити прозорий колір +Set Zoom Задати масштаб +Sine Wave Синусоїда +Single L Одинарний зліва +Single R Одинарний справа +Sink Down Занурення +size (pt) розмір (пт) +Size and Position… Розмір і положення… +SmartArt Styles Стилі SmartArt +Smooth Corners Згладжені кути +Sound Звук +Spelling Dictionary Орфографічний словник +Spiral Left Спіраль ліворуч +Spiral Right Спіраль праворуч +Spring Пружина +Stairs Down Сходи вниз +Starter Templates Початкові шаблони +Strips In Смуги, поява +Strips Out Смуги, зникнення +Swoosh Свист +Table Eraser Гумка для таблиці +Tabs… Табуляція… +Text Pane Панель тексту +Text Transform Перетворення тексту +Text Transparency Прозорість тексту +tOGGLE cASE tOGGLE cASE +Trapezoid: Uneven Sides Трапеція: Нерівні боки +unknown interface language Невідома мова інтерфейсу +Unlock Розблокувати +Variant Gallery Галерея варіантів +Variants Варіанти +Vertical Figure 8 Вертикальна вісімка +Zigzag Зигзаг + (not checked) (не перевірено) +4 Point Star Зірка з 4 променями +5 Point Star Зірка з 5 променями +6 Point Star Зірка з 6 променями +8 Point Star Зірка з 8 променями +{ch} Bullet {ch} Маркер +{f} (Body) {f} (Основний текст) +{f} (Headings) {f} (Заголовки) +{name}: DeckCraft can't open this kind of file {name}: DeckCraft не може відкрити файл цього типу +{n} Column{} {n} Стовпець{} +{r} pt {r} пт +{r} pt glow світіння {r} пт +{w} pt {w} пт +{} ({} slides) {} ({} слайдів) +{} Slide Master {} Зразок слайдів +{} contributors · {} commits Учасники: {} · Коміти: {} +{} presentations {} презентацій +{}x{} Table Таблиця {}×{} +“{}” is not available yet. «{}» ще недоступно. +−Bin −Бін +▶ Play All ▶ Відтворити все +◀ Previous ◀ Назад +✏ on ✏ увімкнено diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 886740706..a304a693a 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -15,6 +15,7 @@ pub mod dialogs; pub mod doc_window; pub mod eyedropper; pub mod fillui; +pub mod i18n; pub mod icons; pub mod media; pub mod menus; @@ -191,7 +192,7 @@ fn command_for(purpose: FilePurpose, name: &str, bytes: &[u8]) -> Result<&'stati FilePurpose::Open => open_command(name), FilePurpose::Infer => infer_command(name, bytes), }; - cmd.ok_or_else(|| format!("{name}: DeckCraft can't open this kind of file")) + cmd.ok_or_else(|| crate::i18n::format("{name}: DeckCraft can't open this kind of file", &[name.to_string()])) } /// How long a transient status message stays visible. @@ -200,6 +201,8 @@ const STATUS_LINGER_MS: f64 = 6000.0; /// Platform services injected by the host (desktop or web). #[derive(Default)] pub struct Services { + /// Host locale (OS on desktop, navigator.language on the web). + pub system_locale: Option, /// Open-file dialog for a purpose (`open`, `picture`, `audio`, `video`) → path. pub pick_open: Option, /// Save dialog with a suggested name → path. @@ -237,6 +240,7 @@ pub enum ViewMode { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] pub struct UiState { + pub interface_language: i18n::Language, pub brightness: theme::Brightness, pub tab: String, pub ribbon_collapsed: bool, @@ -279,6 +283,7 @@ pub struct UiState { impl Default for UiState { fn default() -> Self { UiState { + interface_language: i18n::Language::System, brightness: theme::Brightness::Light, tab: "Home".into(), ribbon_collapsed: false, @@ -395,6 +400,7 @@ pub const UI_COMMANDS: &[(&str, &str, Option<&str>, &str)] = &[ ("app.about", "About DeckCraft", None, "{}"), ("app.palette", "Command Palette", Some("Cmd+Shift+P"), "{}"), ("app.preferences", "Preferences…", Some("Cmd+,"), "{}"), + ("app.language", "Interface Language", None, "{language: system|en|uk}"), ("app.openDialog", "Open…", None, "{purpose?}"), ("app.insertPictureDialog", "Picture from File…", None, "{}"), ("app.smartArtPictureDialog", "Insert Picture in SmartArt…", None, "{id?, index}"), @@ -589,7 +595,9 @@ impl SlideApp { } pub fn set_status(&mut self, msg: impl Into) { - self.status = Some((msg.into(), now_ms())); + i18n::set_current(self.ui.interface_language.resolve(self.services.system_locale.as_deref())); + let msg = msg.into(); + self.status = Some((i18n::tr(&msg).to_string(), now_ms())); } /// A message that must be seen wherever the user is: a toast, which also shows over the start @@ -651,6 +659,7 @@ impl SlideApp { /// Run a command by id (UI commands here, everything else in the engine). Errors show in the /// status bar and are returned. pub fn run(&mut self, id: &str, params: Value) -> Result { + i18n::set_current(self.ui.interface_language.resolve(self.services.system_locale.as_deref())); let r = if UI_COMMANDS.iter().any(|c| c.0 == id) { self.run_ui(id, ¶ms) } else { @@ -999,6 +1008,21 @@ impl SlideApp { } "app.about" => self.dialog = Some(dialogs::Dialog::new("about")), "app.palette" => self.palette = Some((String::new(), 0)), + "app.language" => { + let language = p.get("language").and_then(Value::as_str).unwrap_or("system"); + self.ui.interface_language = match language { + "system" => i18n::Language::System, + "en" => i18n::Language::En, + "uk" => i18n::Language::Uk, + "ru" => i18n::Language::Ru, + "es" => i18n::Language::Es, + "fr" => i18n::Language::Fr, + "pt" => i18n::Language::Pt, + "de" => i18n::Language::De, + _ => return Err("unknown interface language".into()), + }; + i18n::set_current(self.ui.interface_language.resolve(self.services.system_locale.as_deref())); + } "app.preferences" => self.dialog = Some(dialogs::Dialog::new("preferences")), "app.openDialog" => self.pick_and_open(), "app.insertPictureDialog" => self.pick_and_insert("picture", "insert.picture"), @@ -1262,7 +1286,7 @@ impl SlideApp { if let Some(path) = pick(&suggested) { match self.session.execute("file.saveAs", &json!({"path": path})) { Ok(_) => { - self.set_status(format!("Saved {path}")); + self.set_status(crate::i18n::format("Saved {path}", std::slice::from_ref(&path))); self.ui.recent.retain(|p| *p != path); self.ui.recent.insert(0, path); } @@ -1514,6 +1538,7 @@ impl SlideApp { /// Per-frame logic before layout: styles, control requests, screenshots, shortcuts. pub fn logic(&mut self, ctx: &egui::Context) { + i18n::set_current(self.ui.interface_language.resolve(self.services.system_locale.as_deref())); let scale = self.ui.ui_scale.clamp(0.5, 3.0); if (ctx.zoom_factor() - scale).abs() > 1e-3 { ctx.set_zoom_factor(scale); @@ -1562,7 +1587,7 @@ impl SlideApp { if self.session.documents().iter().any(|d| d.is_dirty()) && let Err(e) = self.session.execute("file.recovery.save", &json!({})) { - self.set_status(format!("Couldn't save AutoRecover information: {e}")); + self.set_status(crate::i18n::format("Couldn't save AutoRecover information: {e}", &[(e).to_string()])); } } // On the web, dropped files can only be read asynchronously: the host reads them and @@ -1772,6 +1797,7 @@ impl SlideApp { /// Lay out the whole window. pub fn ui(&mut self, ui: &mut egui::Ui) { + i18n::set_current(self.ui.interface_language.resolve(self.services.system_locale.as_deref())); let ctx = ui.ctx().clone(); if !self.fonts_ready { ctx.request_repaint(); diff --git a/crates/ui-egui/src/media.rs b/crates/ui-egui/src/media.rs index 7fd8fda72..ddb29cc90 100644 --- a/crates/ui-egui/src/media.rs +++ b/crates/ui-egui/src/media.rs @@ -459,7 +459,7 @@ pub fn control_bar(ui: &mut Ui, rect: Rect, status: Option<&VoiceStatus>, clip: // Time label on the right, timeline between. let label = clock(pos); let label_w = 64.0; - painter.text(pos2(rect.max.x - 6.0, rect.center().y), Align2::RIGHT_CENTER, label, egui::FontId::monospace(11.0), white); + painter.text(pos2(rect.max.x - 6.0, rect.center().y), Align2::RIGHT_CENTER, &label, egui::FontId::monospace(11.0), white); let track = Rect::from_min_max(pos2(x + 6.0, rect.center().y - 3.0), pos2(rect.max.x - label_w - 6.0, rect.center().y + 3.0)); if track.width() > 10.0 { painter.rect_filled(track, CornerRadius::same(3), Color32::from_gray(90)); @@ -493,7 +493,7 @@ pub fn control_bar(ui: &mut Ui, rect: Rect, status: Option<&VoiceStatus>, clip: painter.text( pos2(rect.min.x, rect.max.y + 3.0), Align2::LEFT_TOP, - format!("No sound: {err}"), + crate::i18n::format("No sound: {err}", std::slice::from_ref(err)), egui::FontId::proportional(10.0), Color32::from_rgb(0xC0, 0x40, 0x40), ); diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 440fd9392..f2bbfe8a8 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -86,8 +86,13 @@ fn palette_items(session: &deckcraft_engine::Session, q: &str) -> Vec<(String, S .into_iter() // Commands that need a path or other value fail when the palette runs them with `{}`. .filter(|c| c.enabled && !crate::UI_COMMANDS.iter().any(|u| u.1 == c.label) && !deckcraft_engine::cmd::needs_arguments(c.params)) - .map(|c| (c.id.to_string(), c.label.to_string(), c.shortcut)) - .chain(crate::UI_COMMANDS.iter().filter(|c| !deckcraft_engine::cmd::needs_arguments(c.3)).map(|c| (c.0.to_string(), c.1.to_string(), c.2))) + .map(|c| (c.id.to_string(), crate::i18n::tr(c.label).to_string(), c.shortcut)) + .chain( + crate::UI_COMMANDS + .iter() + .filter(|c| !deckcraft_engine::cmd::needs_arguments(c.3)) + .map(|c| (c.0.to_string(), crate::i18n::tr(c.1).to_string(), c.2)), + ) .filter(|(id, label, _)| q.is_empty() || label.to_lowercase().contains(q) || id.to_lowercase().contains(q)) .collect(); items.sort_by_key(|(_, l, _)| !l.to_lowercase().starts_with(q)); @@ -106,7 +111,12 @@ pub fn palette(app: &mut SlideApp, ctx: &egui::Context) { .anchor(egui::Align2::CENTER_TOP, egui::vec2(0.0, 90.0)) .fixed_size(egui::vec2(520.0, 380.0)) .show(ctx, |ui| { - let r = ui.add(egui::TextEdit::singleline(&mut query).hint_text("Search commands…").desired_width(f32::INFINITY).font(theme::font(15.0))); + let r = ui.add( + egui::TextEdit::singleline(&mut query) + .hint_text(crate::i18n::tr("Search commands…")) + .desired_width(f32::INFINITY) + .font(theme::font(15.0)), + ); r.request_focus(); let q = query.to_lowercase(); let items = palette_items(&app.session, &q); @@ -133,7 +143,7 @@ pub fn palette(app: &mut SlideApp, ctx: &egui::Context) { egui::ScrollArea::vertical().max_height(320.0).show(ui, |ui| { for (k, (id, label, sc)) in items.iter().enumerate() { let r = ui.horizontal(|ui| { - let resp = ui.selectable_label(k == sel, label); + let resp = ui.selectable_label(k == sel, crate::i18n::tr(label)); if let Some(s) = sc { ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { ui.label(egui::RichText::new(crate::ribbon::pretty_shortcut(s)).color(t.text_faint)); diff --git a/crates/ui-egui/src/panes.rs b/crates/ui-egui/src/panes.rs index 39bab0785..a21b74602 100644 --- a/crates/ui-egui/src/panes.rs +++ b/crates/ui-egui/src/panes.rs @@ -34,7 +34,7 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { _ => "Pane", }; ui.horizontal(|ui| { - ui.label(egui::RichText::new(title).font(theme::bold(16.0))); + ui.label(egui::RichText::new(crate::i18n::tr(title)).font(theme::bold(16.0))); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { let (r, resp) = ui.allocate_exact_size(vec2(20.0, 20.0), Sense::click()); if resp.hovered() { @@ -191,7 +191,7 @@ fn color_button( ) { let sc = scheme(app); ui.horizontal(|ui| { - ui.label(label); + ui.label(crate::i18n::tr(label)); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { let r = widgets::drop_button(ui, "Color", vec2(70.0, 22.0), true); widgets::color_popup(&r).show(|ui| { @@ -208,7 +208,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { let t = Tokens::get(ui.ctx()); let Some(st) = app.session.active() else { return }; let Some(sh) = st.selected_shapes().first().map(|s| (*s).clone()) else { - ui.label(egui::RichText::new("Select a shape to format it.").color(t.text_dim)); + ui.label(egui::RichText::new(crate::i18n::tr("Select a shape to format it.")).color(t.text_dim)); return; }; let x = deckcraft_engine::cmd::xfrm_of(&st.doc, &st.selection, &sh); @@ -235,7 +235,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { ui.separator(); match app.ui.format_tab.as_str() { "effects" => { - ui.label(egui::RichText::new("Shadow").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Shadow")).font(theme::bold(13.0))); ui.horizontal_wrapped(|ui| { for (l, v) in [ ("None", "none"), @@ -245,7 +245,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { ("Inner", "inner"), ("Perspective", "perspective"), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.effects", json!({"shadow": v})); } } @@ -271,10 +271,10 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { fx_slider(app, ui, ("shadow", sh.id.0, "d"), "Distance", sw.dist, 0.0..=200.0, " pt", "shadowProps", "dist", 1.0); } ui.add_space(6.0); - ui.label(egui::RichText::new("Reflection").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Reflection")).font(theme::bold(13.0))); ui.horizontal_wrapped(|ui| { for (l, v) in [("None", "none"), ("Tight", "tight"), ("Half", "half"), ("Full", "full")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.effects", json!({"reflection": v})); } } @@ -297,16 +297,16 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { fx_slider(app, ui, ("refl", sh.id.0, "b"), "Blur", r.blur, 0.0..=100.0, " pt", "reflectionProps", "blur", 1.0); } ui.add_space(6.0); - ui.label(egui::RichText::new("Glow").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Glow")).font(theme::bold(13.0))); let radius = fx.glow.as_ref().map_or(0.0, |g| g.radius); - fx_slider(app, ui, ("glow", sh.id.0, "r"), "Size", radius, 0.0..=150.0, " pt", "glowProps", "radius", 1.0); + fx_slider(app, ui, ("glow", sh.id.0, "r"), crate::i18n::tr("Size"), radius, 0.0..=150.0, " pt", "glowProps", "radius", 1.0); if let Some(g) = &fx.glow { color_button(app, ui, "Color", None, |c| ("shape.effects".into(), json!({"glowProps": {"color": c.as_ref().map(cref_param)}}))); fx_slider( app, ui, ("glow", sh.id.0, "t"), - "Transparency", + crate::i18n::tr("Transparency"), (1.0 - g.color.alpha()) * 100.0, 0.0..=100.0, "%", @@ -315,14 +315,14 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { 0.01, ); } - ui.label(egui::RichText::new("Soft Edges").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Soft Edges")).font(theme::bold(13.0))); let mut s = sh.effects.as_ref().and_then(|e| e.soft_edge).unwrap_or(0.0); - if ui.add(egui::Slider::new(&mut s, 0.0..=50.0).text("size (pt)")).drag_stopped() { + if ui.add(egui::Slider::new(&mut s, 0.0..=50.0).text(crate::i18n::tr("size (pt)"))).drag_stopped() { run(app, "shape.effects", json!({"softEdges": s})); } let raw3d = sh.effects.as_ref().and_then(|e| e.raw3d.clone()); three_d_options(app, ui, sh.id.0, raw3d.as_deref()); - if ui.button("Reset Effects").clicked() { + if ui.button(crate::i18n::tr("Reset Effects")).clicked() { run(app, "shape.effects", json!({"reset": true})); } } @@ -332,7 +332,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { let locked = lock; let mut fields = |ui: &mut Ui, label: &str, id: &str, v: f64, key: &str, cmd: &str, unit: f64| { ui.horizontal(|ui| { - ui.add_sized(vec2(90.0, 20.0), egui::Label::new(label)); + ui.add_sized(vec2(90.0, 20.0), egui::Label::new(crate::i18n::tr(label))); if let Some(nv) = widgets::spinner(ui, id, v / unit, 0.1, if unit == 72.0 { "\"" } else { "°" }, 70.0) { let mut p = json!({key: nv * unit}); if cmd == "shape.resize" && locked { @@ -342,7 +342,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { } }); }; - ui.label(egui::RichText::new("Size").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Size")).font(theme::bold(13.0))); fields(ui, "Height", "fh", x.h, "h", "shape.resize", 72.0); fields(ui, "Width", "fw", x.w, "w", "shape.resize", 72.0); fields(ui, "Rotation", "fr", x.rot, "deg", "shape.rotate", 1.0); @@ -350,11 +350,11 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { ui.data_mut(|d| d.insert_temp(lock_id, lock)); } ui.add_space(6.0); - ui.label(egui::RichText::new("Position").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Position")).font(theme::bold(13.0))); fields(ui, "Horizontal", "fx", x.x, "x", "shape.move", 72.0); fields(ui, "Vertical", "fy", x.y, "y", "shape.move", 72.0); ui.add_space(6.0); - ui.label(egui::RichText::new("Alt Text").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Alt Text")).font(theme::bold(13.0))); let id = ui.id().with(("alt", uid, sh.id.0)); let stored: Option<(String, String)> = ui.data_mut(|d| d.get_temp(id)); let mut alt = widgets::text_draft(stored, &sh.descr); @@ -372,28 +372,28 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { }); text_transparency_slider(app, ui, &sh); ui.add_space(6.0); - ui.label(egui::RichText::new("Text Box").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Text Box")).font(theme::bold(13.0))); ui.horizontal(|ui| { - ui.label("Vertical alignment"); + ui.label(crate::i18n::tr("Vertical alignment")); for (l, a) in [("Top", "top"), ("Middle", "middle"), ("Bottom", "bottom")] { - if ui.small_button(l).clicked() { + if ui.small_button(crate::i18n::tr(l)).clicked() { run(app, "format.anchor", json!({"anchor": a})); } } }); ui.horizontal_wrapped(|ui| { for (l, m) in [("Do not Autofit", "none"), ("Shrink text on overflow", "shrink"), ("Resize shape to fit text", "resize")] { - if ui.small_button(l).clicked() { + if ui.small_button(crate::i18n::tr(l)).clicked() { run(app, "format.autofit", json!({"mode": m})); } } }); let wrap = sh.text.as_ref().and_then(|t| t.body.wrap).unwrap_or(true); let mut w = wrap; - if ui.checkbox(&mut w, "Wrap text in shape").changed() { + if ui.checkbox(&mut w, crate::i18n::tr("Wrap text in shape")).changed() { run(app, "format.wrap", json!({"on": w})); } - ui.label("Margins (pt)"); + ui.label(crate::i18n::tr("Margins (pt)")); let b = sh.text.as_ref().map(|t| t.body.clone()).unwrap_or_default(); for (l, k, v) in [ ("Left", "left", b.inset_l.unwrap_or(7.2)), @@ -402,14 +402,14 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { ("Bottom", "bottom", b.inset_b.unwrap_or(3.6)), ] { ui.horizontal(|ui| { - ui.add_sized(vec2(60.0, 20.0), egui::Label::new(l)); + ui.add_sized(vec2(60.0, 20.0), egui::Label::new(crate::i18n::tr(l))); if let Some(nv) = widgets::spinner(ui, &format!("m{k}"), v, 1.0, " pt", 60.0) { run(app, "format.margins", json!({k: nv.max(0.0)})); } }); } ui.horizontal(|ui| { - ui.label("Columns"); + ui.label(crate::i18n::tr("Columns")); for n in 1..=3 { if ui.small_button(n.to_string()).clicked() { run(app, "format.columns", json!({"count": n, "spacing": 18})); @@ -420,29 +420,29 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { "picture" => { let adj = if let ShapeKind::Picture { fill } = &sh.kind { fill.adjust.clone() } else { Default::default() }; let mut b = adj.brightness as f32; - if ui.add(egui::Slider::new(&mut b, -1.0..=1.0).text("Brightness")).drag_stopped() { + if ui.add(egui::Slider::new(&mut b, -1.0..=1.0).text(crate::i18n::tr("Brightness"))).drag_stopped() { run(app, "picture.adjust", json!({"brightness": b})); } let mut c = adj.contrast as f32; - if ui.add(egui::Slider::new(&mut c, -1.0..=1.0).text("Contrast")).drag_stopped() { + if ui.add(egui::Slider::new(&mut c, -1.0..=1.0).text(crate::i18n::tr("Contrast"))).drag_stopped() { run(app, "picture.adjust", json!({"contrast": c})); } let mut s = adj.saturation.unwrap_or(1.0) as f32; - if ui.add(egui::Slider::new(&mut s, 0.0..=4.0).text("Saturation")).drag_stopped() { + if ui.add(egui::Slider::new(&mut s, 0.0..=4.0).text(crate::i18n::tr("Saturation"))).drag_stopped() { run(app, "picture.adjust", json!({"saturation": s})); } let alpha = if let ShapeKind::Picture { fill } = &sh.kind { fill.alpha.unwrap_or(1.0) } else { 1.0 }; let mut tr = (1.0 - alpha) as f32; - if ui.add(egui::Slider::new(&mut tr, 0.0..=1.0).text("Transparency")).drag_stopped() { + if ui.add(egui::Slider::new(&mut tr, 0.0..=1.0).text(crate::i18n::tr("Transparency"))).drag_stopped() { run(app, "picture.adjust", json!({"transparency": tr})); } - if ui.button("Reset Picture").clicked() { + if ui.button(crate::i18n::tr("Reset Picture")).clicked() { run(app, "picture.reset", json!({})); } } _ => { // Fill & Line. - ui.label(egui::RichText::new("Fill").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Fill")).font(theme::bold(13.0))); let kind = match &sh.fill { None => "auto", Some(Fill::None) => "none", @@ -460,7 +460,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { ("Pattern fill", "pattern"), ("Automatic", "auto"), ] { - if ui.radio(kind == k, l).clicked() { + if ui.radio(kind == k, crate::i18n::tr(l)).clicked() { match k { "none" => run(app, "shape.fill", json!({"none": true})), "solid" => run(app, "shape.fill", json!({"color": "accent1"})), @@ -480,7 +480,7 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { None => ("shape.fill".into(), json!({"none": true})), }); ui.horizontal(|ui| { - ui.label("Transparency"); + ui.label(crate::i18n::tr("Transparency")); // Seed from this shape. A shared temp defaulted to 0, so a shape that was // already 40% transparent showed as opaque, and leaving the slider wrote 0. let seed = solid_fill_transparency_percent(sh.fill.as_ref()); @@ -505,21 +505,21 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { run(app, "shape.fill", json!({"gradient": crate::fillui::gradient_json(&ng)})); } let mut rot = g.rotate_with_shape; - if ui.checkbox(&mut rot, "Rotate with shape").changed() { + if ui.checkbox(&mut rot, crate::i18n::tr("Rotate with shape")).changed() { let ng = deckcraft_model::style::Gradient { rotate_with_shape: rot, ..g.clone() }; run(app, "shape.fill", json!({"gradient": crate::fillui::gradient_json(&ng)})); } } ui.add_space(8.0); - ui.label(egui::RichText::new("Line").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Line")).font(theme::bold(13.0))); let none = matches!(sh.line.as_ref().and_then(|l| l.fill.as_ref()), Some(Fill::None)); - if ui.radio(none, "No line").clicked() { + if ui.radio(none, crate::i18n::tr("No line")).clicked() { run(app, "shape.line", json!({"none": true})); } - if ui.radio(!none && sh.line.is_some(), "Solid line").clicked() { + if ui.radio(!none && sh.line.is_some(), crate::i18n::tr("Solid line")).clicked() { run(app, "shape.line", json!({"color": "tx1", "width": 1})); } - if ui.radio(sh.line.is_none(), "Automatic").clicked() { + if ui.radio(sh.line.is_none(), crate::i18n::tr("Automatic")).clicked() { run(app, "shape.line", json!({"reset": true})); } color_button(app, ui, "Color", Some("No Outline"), |c| match c { @@ -527,16 +527,16 @@ fn format_shape(app: &mut SlideApp, ui: &mut Ui) { None => ("shape.line".into(), json!({"none": true})), }); ui.horizontal(|ui| { - ui.label("Width"); + ui.label(crate::i18n::tr("Width")); let w = sh.line.as_ref().and_then(|l| l.width).unwrap_or(0.75); if let Some(v) = widgets::spinner(ui, "lw", w, 0.25, " pt", 60.0) { run(app, "shape.line", json!({"width": v.max(0.0)})); } }); ui.horizontal_wrapped(|ui| { - ui.label("Dash"); + ui.label(crate::i18n::tr("Dash")); for (l, d) in [("—", "solid"), ("···", "sysDot"), ("- -", "dash"), ("-·-", "dashDot"), ("— —", "lgDash")] { - if ui.small_button(l).clicked() { + if ui.small_button(crate::i18n::tr(l)).clicked() { run(app, "shape.line", json!({"dash": d})); } } @@ -817,7 +817,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { }; // What "Apply to All" re-applies: the current slide's background as command params. let mut current: Option = None; - ui.label(egui::RichText::new("Fill").font(theme::bold(13.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Fill")).font(theme::bold(13.0))); for (l, k) in [ ("Solid fill", "solid"), ("Gradient fill", "gradient"), @@ -825,7 +825,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { ("Pattern fill", "pattern"), ("Follow the layout", "auto"), ] { - if ui.radio(kind == k, l).clicked() && kind != k { + if ui.radio(kind == k, crate::i18n::tr(l)).clicked() && kind != k { match k { "solid" => run(app, "design.background", json!({"color": "bg1"})), "gradient" => { @@ -851,7 +851,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { Some(Fill::Solid { color }) => { current = Some(json!({"color": cref_param(color)})); ui.horizontal(|ui| { - ui.label("Color"); + ui.label(crate::i18n::tr("Color")); let r = widgets::drop_button(ui, "Color", vec2(70.0, 20.0), true); widgets::color_popup(&r).show(|ui| { if let Some(Some(c)) = widgets::color_grid(ui, &sc, None) { @@ -881,7 +881,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { }); for (label, fg) in [("Foreground", true), ("Background", false)] { ui.horizontal(|ui| { - ui.label(label); + ui.label(crate::i18n::tr(label)); let r = widgets::drop_button(ui, "Color", vec2(70.0, 20.0), true); widgets::color_popup(&r).show(|ui| { if let Some(Some(c)) = widgets::color_grid(ui, &sc, None) { @@ -893,7 +893,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { } } Some(Fill::Picture(pf)) => { - if ui.button("Insert picture from file…").clicked() + if ui.button(crate::i18n::tr("Insert picture from file…")).clicked() && let Some(pick) = app.services.pick_open.as_mut() && let Some(path) = pick("picture") && let Some(Ok(bytes)) = app.services.read.as_ref().map(|r| r(&path)) @@ -907,13 +907,13 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { ui.add_space(4.0); let hide = app.session.active().and_then(|d| d.current_slide().map(|s| !s.show_master_shapes)).unwrap_or(false); let mut h = hide; - if ui.checkbox(&mut h, "Hide background graphics").changed() { + if ui.checkbox(&mut h, crate::i18n::tr("Hide background graphics")).changed() { run(app, "design.hideBackgroundGraphics", json!({"hide": h})); } ui.add_space(8.0); let picture = matches!(fill, Some(Fill::Picture(_))); ui.horizontal(|ui| { - if ui.add_enabled(current.is_some() || picture, egui::Button::new("Apply to All")).clicked() { + if ui.add_enabled(current.is_some() || picture, egui::Button::new(crate::i18n::tr("Apply to All"))).clicked() { if let Some(Value::Object(mut o)) = current.clone() { o.insert("all".into(), json!(true)); run(app, "design.background", Value::Object(o)); @@ -921,7 +921,7 @@ fn background(app: &mut SlideApp, ui: &mut Ui) { run(app, "design.background", json!({"copy": true})); } } - if ui.button("Reset Background").clicked() { + if ui.button(crate::i18n::tr("Reset Background")).clicked() { run(app, "design.background", json!({"reset": true})); } }); @@ -1018,13 +1018,15 @@ fn animation(app: &mut SlideApp, ui: &mut Ui) { let selected: Vec = st.selection.shapes.iter().map(|i| i.0).collect(); ui.horizontal(|ui| { let playing = app.anim_preview_active(); - if ui.button(if playing { "■ Stop" } else { "▶ Play All" }).clicked() { + if ui.button(if playing { "■ Stop" } else { crate::i18n::tr("▶ Play All") }).clicked() { run(app, "animation.preview", json!({"on": !playing})); } }); ui.separator(); if anims.is_empty() { - ui.label(egui::RichText::new("Select an object on the slide and add an animation from the Animations tab.").color(t.text_dim)); + ui.label( + egui::RichText::new(crate::i18n::tr("Select an object on the slide and add an animation from the Animations tab.")).color(t.text_dim), + ); return; } let bars = animtimeline::bars(anims.len(), &effects); @@ -1036,7 +1038,11 @@ fn animation(app: &mut SlideApp, ui: &mut Ui) { if a.start == AnimStart::OnClick { click += 1; } - let name = names.iter().find(|(id, _)| *id == a.shape.0).map(|(_, n)| n.clone()).unwrap_or_else(|| format!("Shape {}", a.shape)); + let name = names + .iter() + .find(|(id, _)| *id == a.shape.0) + .map(|(_, n)| n.clone()) + .unwrap_or_else(|| crate::i18n::format("Shape {}", &[(a.shape).to_string()])); let (r, resp) = ui.allocate_exact_size(vec2(ui.available_width(), 30.0), Sense::click()); let sel = selected.contains(&a.shape.0); if sel || resp.hovered() { @@ -1127,21 +1133,21 @@ fn animation(app: &mut SlideApp, ui: &mut Ui) { } resp.context_menu(|ui| { for (l, v) in [("Start On Click", "onClick"), ("Start With Previous", "withPrevious"), ("Start After Previous", "afterPrevious")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "animation.timing", json!({"index": i, "start": v})); ui.close(); } } ui.separator(); - if ui.button("Move Up").clicked() { + if ui.button(crate::i18n::tr("Move Up")).clicked() { run(app, "animation.move", json!({"index": i, "to": i.saturating_sub(1)})); ui.close(); } - if ui.button("Move Down").clicked() { + if ui.button(crate::i18n::tr("Move Down")).clicked() { run(app, "animation.move", json!({"index": i, "to": i + 1})); ui.close(); } - if ui.button("Remove").clicked() { + if ui.button(crate::i18n::tr("Remove")).clicked() { run(app, "animation.remove", json!({"index": i})); ui.close(); } @@ -1221,7 +1227,7 @@ fn revisions(app: &mut SlideApp, ui: &mut Ui) { fn comments(app: &mut SlideApp, ui: &mut Ui) { let t = Tokens::get(ui.ctx()); - if ui.button("+ New Comment").clicked() { + if ui.button(crate::i18n::tr("+ New Comment")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("comment")); } ui.separator(); @@ -1231,7 +1237,7 @@ fn comments(app: &mut SlideApp, ui: &mut Ui) { .map(|st| st.doc.slides.iter().enumerate().filter(|(_, sl)| !sl.comments.is_empty()).map(|(i, sl)| (i, sl.comments.clone())).collect()) .unwrap_or_default(); if threads.is_empty() { - ui.label(egui::RichText::new("No comments.").color(t.text_dim)); + ui.label(egui::RichText::new(crate::i18n::tr("No comments.")).color(t.text_dim)); return; } let focus = app.ui.comment_focus; @@ -1287,7 +1293,7 @@ fn comment_card(app: &mut SlideApp, ui: &mut Ui, slide: usize, index: usize, c: ui.horizontal(|ui| { let id = ui.id().with(("reply", slide, index)); let mut txt: String = ui.data_mut(|d| d.get_temp(id).unwrap_or_default()); - let r = ui.add(egui::TextEdit::singleline(&mut txt).hint_text("Reply…").desired_width(ui.available_width() - 70.0)); + let r = ui.add(egui::TextEdit::singleline(&mut txt).hint_text(crate::i18n::tr("Reply…")).desired_width(ui.available_width() - 70.0)); if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) && !txt.trim().is_empty() { focus_comment(app, slide, index); run(app, "comment.reply", json!({"index": index, "text": txt})); @@ -1330,7 +1336,7 @@ struct IdeaThumbs { fn designer(app: &mut SlideApp, ui: &mut Ui) { let t = Tokens::get(ui.ctx()); - ui.label(egui::RichText::new("Pick a design for this slide. Ideas are generated on your device.").color(t.text_dim)); + ui.label(egui::RichText::new(crate::i18n::tr("Pick a design for this slide. Ideas are generated on your device.")).color(t.text_dim)); ui.add_space(6.0); let Some(st) = app.session.active() else { return }; let doc = st.doc.clone(); diff --git a/crates/ui-egui/src/ribbon.rs b/crates/ui-egui/src/ribbon.rs index 3e43a68b9..eca76e686 100644 --- a/crates/ui-egui/src/ribbon.rs +++ b/crates/ui-egui/src/ribbon.rs @@ -76,7 +76,7 @@ pub fn title_bar(app: &mut SlideApp, ui: &mut Ui) { let dirty = app.session.active().is_some_and(|d| d.is_dirty()); crate::qat::show(app, &mut child); let title = - app.session.active().map(|d| format!("{}{}", d.title(), if dirty { " — Edited" } else { "" })).unwrap_or_else(|| "DeckCraft".into()); + app.session.active().map(|d| format!("{}{}", d.title(), if dirty { crate::i18n::tr(" — Edited") } else { "" })).unwrap_or_else(|| "DeckCraft".into()); ui.painter().text(rect.center(), Align2::CENTER_CENTER, title, theme::font(13.0), t.text); // Right side. let mut right = ui.new_child( @@ -89,7 +89,7 @@ pub fn title_bar(app: &mut SlideApp, ui: &mut Ui) { app.palette = Some((String::new(), 0)); } let share = right.add( - egui::Button::new(egui::RichText::new(" Present ").color(t.accent_text).font(theme::bold(13.0))) + egui::Button::new(egui::RichText::new(crate::i18n::tr(" Present ")).color(t.accent_text).font(theme::bold(13.0))) .fill(t.accent) .corner_radius(control_h / 2.0) .min_size(vec2(84.0, control_h)), @@ -183,8 +183,13 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { } let all: Vec<(&str, bool)> = TABS.iter().map(|s| (*s, false)).chain(ctx_tabs.iter().map(|s| (*s, true))).collect(); for (name, contextual) in all { + let label = match name { + "Home" => crate::i18n::tr_context(name, "@ribbon:Home"), + "Insert" => crate::i18n::tr_context(name, "@ribbon:Insert"), + _ => crate::i18n::tr(name), + }; let font = theme::font(13.0); - let w = ui.fonts_mut(|f| f.layout_no_wrap(name.to_string(), font.clone(), t.text).size().x) + 18.0; + let w = ui.fonts_mut(|f| f.layout_no_wrap(label.to_string(), font.clone(), t.text).size().x) + 18.0; let r = Rect::from_min_size(pos2(x, y), vec2(w, 24.0)); let resp = ui.interact(r, ui.id().with(("tab", name)), Sense::click()); let active = app.ui.tab == name; @@ -193,7 +198,7 @@ pub fn show(app: &mut SlideApp, ui: &mut Ui) { } let col = if contextual { t.contextual } else { t.text }; let f = if active { theme::bold(13.0) } else { font }; - ui.painter().text(r.center(), Align2::CENTER_CENTER, name, f, col); + ui.painter().text(r.center(), Align2::CENTER_CENTER, label, f, col); if active { let uw = (w - 20.0).max(16.0); ui.painter().rect_filled(Rect::from_center_size(pos2(r.center().x, r.max.y - 1.0), vec2(uw, 3.0)), CornerRadius::same(1), t.accent); @@ -302,6 +307,7 @@ fn toggle(app: &mut SlideApp, ui: &mut Ui, icon: Icon, label: &str, id: &str, on } fn tip(id: &str, label: &str) -> String { + let label = crate::i18n::tr(label); let sc = deckcraft_engine::find_command(id).and_then(|c| c.shortcut).or_else(|| crate::UI_COMMANDS.iter().find(|c| c.0 == id).and_then(|c| c.2)); match sc { Some(s) => format!("{label} ({})", pretty_shortcut(s)), @@ -334,21 +340,21 @@ pub fn fmt_state(app: &mut SlideApp) -> Value { fn clipboard_group(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let (main, arrow) = big_button_ex(ui, Icon::Paste, "Paste", enabled(app, "edit.paste"), true, false); - if main.on_hover_text("Paste (⌘V)").clicked() { + if main.on_hover_text(crate::i18n::tr("Paste (⌘V)")).clicked() { run(app, "edit.paste", json!({})); } if let Some(a) = arrow { egui::Popup::menu(&a).show(|ui| { - if ui.button("Paste").clicked() { + if ui.button(crate::i18n::tr("Paste")).clicked() { run(app, "edit.paste", json!({})); } - if ui.button("Paste and Match Formatting").clicked() { + if ui.button(crate::i18n::tr("Paste and Match Formatting")).clicked() { run(app, "edit.pasteText", json!({})); } if ui.button("Paste Special…").clicked() { run(app, "app.pasteSpecial", json!({})); } - if ui.button("Paste Formatting").clicked() { + if ui.button(crate::i18n::tr("Paste Formatting")).clicked() { run(app, "format.painterApply", json!({})); } }); @@ -358,7 +364,8 @@ fn clipboard_group(app: &mut SlideApp, ui: &mut Ui) { small(app, ui, Icon::Copy, "Copy", "edit.copy", json!({})); let on = app.session.painter.is_some(); let en = enabled(app, "format.painter"); - let r = small_button(ui, Icon::FormatPainter, "Format", en, on).on_hover_text("Format Painter (double-click to keep it on)"); + let r = + small_button(ui, Icon::FormatPainter, "Format", en, on).on_hover_text(crate::i18n::tr("Format Painter (double-click to keep it on)")); if r.double_clicked() { run(app, "format.painter", json!({"sticky": true})); } else if r.clicked() { @@ -423,17 +430,17 @@ fn layout_menu(app: &mut SlideApp, ui: &mut Ui, cmd: &str) { fn slides_group(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let (main, arrow) = big_button_ex(ui, Icon::NewSlide, "New\nSlide", enabled(app, "slide.new"), true, false); - if main.on_hover_text("New Slide (⇧⌘N)").clicked() { + if main.on_hover_text(crate::i18n::tr("New Slide (⇧⌘N)")).clicked() { run(app, "slide.new", json!({})); } if let Some(a) = arrow { egui::Popup::menu(&a).width(420.0).show(|ui| { layout_menu(app, ui, "slide.new"); ui.separator(); - if ui.button("Duplicate Selected Slides").clicked() { + if ui.button(crate::i18n::tr("Duplicate Selected Slides")).clicked() { run(app, "slide.duplicate", json!({})); } - if ui.button("Slides from Outline…").clicked() { + if ui.button(crate::i18n::tr("Slides from Outline…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("outline")); } let desktop = app.services.pick_open.is_some(); @@ -452,10 +459,10 @@ fn slides_group(app: &mut SlideApp, ui: &mut Ui) { small(app, ui, Icon::ResetSlide, "Reset", "slide.reset", json!({})); let (r, _) = small_button_ex(ui, Icon::Section, "Section", enabled(app, "section.add"), false, true); egui::Popup::menu(&r).show(|ui| { - if ui.button("Add Section").clicked() { + if ui.button(crate::i18n::tr("Add Section")).clicked() { run(app, "section.add", json!({})); } - if ui.button("Remove All Sections").clicked() { + if ui.button(crate::i18n::tr("Remove All Sections")).clicked() { run(app, "section.removeAll", json!({})); } }); @@ -487,9 +494,9 @@ fn font_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { dropdown(ui, "font", &font, 150.0, en, |ui| { for (k, f) in fams.iter().enumerate() { let label = if k == 0 && theme_fonts.len() == 2 { - format!("{f} (Headings)") + crate::i18n::format("{f} (Headings)", std::slice::from_ref(f)) } else if k == 1 && theme_fonts.len() == 2 { - format!("{f} (Body)") + crate::i18n::format("{f} (Body)", std::slice::from_ref(f)) } else { f.clone() }; @@ -534,7 +541,7 @@ fn font_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { let r = icon_toggle(ui, Icon::CharSpacing, "Character Spacing", en, false); egui::Popup::menu(&r).show(|ui| { for (label, pt) in [("Very Tight", -3.0), ("Tight", -1.5), ("Normal", 0.0), ("Loose", 3.0), ("Very Loose", 6.0)] { - if ui.button(label).clicked() { + if ui.button(crate::i18n::tr(label)).clicked() { run(app, "format.spacing", json!({"pt": pt})); } } @@ -548,7 +555,7 @@ fn font_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { ("Capitalize Each Word", "title"), ("tOGGLE cASE", "toggle"), ] { - if ui.button(label).clicked() { + if ui.button(crate::i18n::tr(label)).clicked() { run(app, "format.case", json!({"mode": mode})); } } @@ -693,16 +700,16 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { ui.spacing_mut().item_spacing.x = 1.0; let b = |k: &str| st.get(k).and_then(Value::as_bool).unwrap_or(false); let (m, a) = small_button_ex(ui, Icon::Bullets, "", en, b("bullets"), true); - if m.on_hover_text("Bullets").clicked() { + if m.on_hover_text(crate::i18n::tr("Bullets")).clicked() { run(app, "format.bullets", json!({})); } if let Some(a) = a { egui::Popup::menu(&a).show(|ui| { - if ui.button("None").clicked() { + if ui.button(crate::i18n::tr("None")).clicked() { run(app, "format.bullets", json!({"on": false})); } for ch in ["•", "○", "■", "□", "◆", "➢", "✓", "–", "★"] { - if ui.button(egui::RichText::new(format!("{ch} Bullet")).size(14.0)).clicked() { + if ui.button(egui::RichText::new(crate::i18n::format("{ch} Bullet", &[(ch).to_string()])).size(14.0)).clicked() { run(app, "format.bullets", json!({"on": true, "char": ch})); } } @@ -715,12 +722,12 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { }); } let (m, a) = small_button_ex(ui, Icon::Numbering, "", en, b("numbering"), true); - if m.on_hover_text("Numbering").clicked() { + if m.on_hover_text(crate::i18n::tr("Numbering")).clicked() { run(app, "format.numbering", json!({})); } if let Some(a) = a { egui::Popup::menu(&a).show(|ui| { - if ui.button("None").clicked() { + if ui.button(crate::i18n::tr("None")).clicked() { run(app, "format.numbering", json!({"on": false})); } for (label, sch) in [ @@ -732,7 +739,7 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { ("a) b) c)", "alphaLcParenR"), ("a. b. c.", "alphaLcPeriod"), ] { - if ui.button(label).clicked() { + if ui.button(crate::i18n::tr(label)).clicked() { run(app, "format.numbering", json!({"on": true, "scheme": sch})); } } @@ -753,7 +760,7 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { run(app, "format.lineSpacing", json!({"lines": v})); } } - if ui.button("Line Spacing Options…").clicked() { + if ui.button(crate::i18n::tr("Line Spacing Options…")).clicked() { run(app, "format.paragraphDialog", json!({})); } if ui.button("Tabs…").clicked() { @@ -763,7 +770,8 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { let r = icon_toggle(ui, Icon::Columns, "Columns", en, false); egui::Popup::menu(&r).show(|ui| { for n in 1..=3 { - if ui.button(format!("{n} Column{}", if n > 1 { "s" } else { "" })).clicked() { + if ui.button(crate::i18n::count(n, ("Column", "Columns"), ["стовпець", "стовпці", "стовпців"], ["столбец", "столбца", "столбцов"], ("columna", "columnas"), ("colonne", "colonnes"), ("coluna", "colunas"), ("Spalte", "Spalten"))).clicked() + { run(app, "format.columns", json!({"count": n, "spacing": 18})); } } @@ -785,7 +793,7 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { ("Rotate all text 270°", "rotate270"), ("Stacked", "stacked"), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "format.direction", json!({"dir": d})); } } @@ -793,7 +801,7 @@ fn paragraph_group(app: &mut SlideApp, ui: &mut Ui, st: &Value) { let r = icon_toggle(ui, Icon::AlignText, "Align Text", en, false); egui::Popup::menu(&r).show(|ui| { for (l, a) in [("Top", "top"), ("Middle", "middle"), ("Bottom", "bottom")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "format.anchor", json!({"anchor": a})); } } @@ -815,7 +823,7 @@ pub fn shapes_gallery(ui: &mut Ui) -> Option<&'static str> { ui.set_max_width(330.0); egui::ScrollArea::vertical().max_height(420.0).show(ui, |ui| { for cat in deckcraft_geom::preset::Category::ALL { - ui.label(egui::RichText::new(cat.label()).font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr(cat.label())).font(theme::bold(12.0))); ui.horizontal_wrapped(|ui| { ui.spacing_mut().item_spacing = vec2(1.0, 1.0); for p in deckcraft_geom::preset::CATALOG.iter().filter(|p| p.category == cat) { @@ -824,7 +832,7 @@ pub fn shapes_gallery(ui: &mut Ui) -> Option<&'static str> { ui.painter().rect_filled(r, CornerRadius::same(3), t.hover); } paint_preset(ui.painter(), r.shrink(4.0), p.name, Color32::TRANSPARENT, t.text); - if resp.on_hover_text(p.label).clicked() { + if resp.on_hover_text(crate::i18n::tr(p.label)).clicked() { out = Some(p.name); } } @@ -835,7 +843,7 @@ pub fn shapes_gallery(ui: &mut Ui) -> Option<&'static str> { ui.painter().rect_filled(r, CornerRadius::same(3), t.hover); } paint_freeform_icon(ui.painter(), r.shrink(5.0), name, t.text); - if resp.on_hover_text(label).clicked() { + if resp.on_hover_text(crate::i18n::tr(label)).clicked() { out = Some(name); } } @@ -909,7 +917,7 @@ fn kurbo_flatten(path: &deckcraft_geom::BezPath, mut f: impl FnMut(Fl)) { fn drawing_group(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let en = enabled(app, "shape.insert"); - let r = big_button(ui, Icon::Shapes, "Shapes", en).on_hover_text("Shapes"); + let r = big_button(ui, Icon::Shapes, "Shapes", en).on_hover_text(crate::i18n::tr("Shapes")); egui::Popup::menu(&r).show(|ui| { if let Some(p) = shapes_gallery(ui) { app.session.set_tool(deckcraft_engine::ToolKind::Shape { preset: p.to_string() }); @@ -959,15 +967,15 @@ pub fn outline_menu(app: &mut SlideApp, ui: &mut Ui, sc: &deckcraft_color::Color None => run(app, "shape.line", json!({"none": true})), } } - ui.menu_button("Weight", |ui| { + ui.menu_button(crate::i18n::tr("Weight"), |ui| { for w in [0.25, 0.5, 0.75, 1.0, 1.5, 2.25, 3.0, 4.5, 6.0] { - if ui.button(format!("{w} pt")).clicked() { + if ui.button(crate::i18n::format("{w} pt", &[(w).to_string()])).clicked() { run(app, "shape.line", json!({"width": w})); ui.close(); } } }); - ui.menu_button("Dashes", |ui| { + ui.menu_button(crate::i18n::tr("Dashes"), |ui| { for (l, d) in [ ("Solid", "solid"), ("Round Dot", "sysDot"), @@ -977,13 +985,13 @@ pub fn outline_menu(app: &mut SlideApp, ui: &mut Ui, sc: &deckcraft_color::Color ("Long Dash", "lgDash"), ("Long Dash Dot", "lgDashDot"), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.line", json!({"dash": d})); ui.close(); } } }); - ui.menu_button("Arrows", |ui| { + ui.menu_button(crate::i18n::tr("Arrows"), |ui| { for (l, h, tl) in [ ("None", "none", "none"), ("Arrow at end", "none", "triangle"), @@ -992,7 +1000,7 @@ pub fn outline_menu(app: &mut SlideApp, ui: &mut Ui, sc: &deckcraft_color::Color ("Stealth end", "none", "stealth"), ("Oval ends", "oval", "oval"), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.line", json!({"head": h, "tail": tl})); ui.close(); } @@ -1001,7 +1009,7 @@ pub fn outline_menu(app: &mut SlideApp, ui: &mut Ui, sc: &deckcraft_color::Color } pub fn effects_menu(app: &mut SlideApp, ui: &mut Ui) { - ui.menu_button("Shadow", |ui| { + ui.menu_button(crate::i18n::tr("Shadow"), |ui| { for (l, v) in [ ("No Shadow", "none"), ("Outer", "outer"), @@ -1010,36 +1018,36 @@ pub fn effects_menu(app: &mut SlideApp, ui: &mut Ui) { ("Inner", "inner"), ("Perspective", "perspective"), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.effects", json!({"shadow": v})); } } }); - ui.menu_button("Reflection", |ui| { + ui.menu_button(crate::i18n::tr("Reflection"), |ui| { for (l, v) in [("No Reflection", "none"), ("Tight", "tight"), ("Half", "half"), ("Full", "full")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "shape.effects", json!({"reflection": v})); } } }); - ui.menu_button("Glow", |ui| { - if ui.button("No Glow").clicked() { + ui.menu_button(crate::i18n::tr("Glow"), |ui| { + if ui.button(crate::i18n::tr("No Glow")).clicked() { run(app, "shape.effects", json!({"glow": null})); } for r in [5.0, 8.0, 11.0, 18.0] { - if ui.button(format!("{r} pt glow")).clicked() { + if ui.button(crate::i18n::format("{r} pt glow", &[(r).to_string()])).clicked() { run(app, "shape.effects", json!({"glow": r})); } } }); - ui.menu_button("Soft Edges", |ui| { + ui.menu_button(crate::i18n::tr("Soft Edges"), |ui| { for r in [0.0, 1.0, 2.5, 5.0, 10.0, 25.0] { - if ui.button(if r == 0.0 { "No Soft Edges".to_string() } else { format!("{r} pt") }).clicked() { + if ui.button(if r == 0.0 { "No Soft Edges".to_string() } else { crate::i18n::format("{r} pt", &[(r).to_string()]) }).clicked() { run(app, "shape.effects", json!({"softEdges": r})); } } }); - ui.menu_button("Bevel", |ui| { + ui.menu_button(crate::i18n::tr("Bevel"), |ui| { for b in [ "none", "circle", @@ -1060,7 +1068,7 @@ pub fn effects_menu(app: &mut SlideApp, ui: &mut Ui) { } } }); - if ui.button("Format Shape…").clicked() { + if ui.button(crate::i18n::tr("Format Shape…")).clicked() { let _ = app.run("view.pane", json!({"pane": "format", "tab": "effects"})); } } @@ -1089,7 +1097,7 @@ fn quick_styles(app: &mut SlideApp, ui: &mut Ui) { _ => (c, c.lerp_to_gamma(Color32::BLACK, 0.3), Color32::WHITE), }; p.rect(rect.shrink(2.0), CornerRadius::same(3), fill, Stroke::new(1.5, stroke), egui::StrokeKind::Inside); - p.text(rect.center(), Align2::CENTER_CENTER, "Abc", theme::font(11.0), text); + p.text(rect.center(), Align2::CENTER_CENTER, crate::i18n::tr("Abc"), theme::font(11.0), text); if resp.hovered() { p.rect_stroke(rect, CornerRadius::same(3), Stroke::new(1.5, Tokens::get(ui.ctx()).accent), egui::StrokeKind::Inside); } @@ -1104,7 +1112,7 @@ fn quick_styles(app: &mut SlideApp, ui: &mut Ui) { } pub fn arrange_menu(app: &mut SlideApp, ui: &mut Ui) { - ui.label(egui::RichText::new("Order Objects").font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Order Objects")).font(theme::bold(12.0))); for (l, id, ic) in [ ("Bring to Front", "arrange.bringToFront", Icon::BringToFront), ("Send to Back", "arrange.sendToBack", Icon::SendToBack), @@ -1114,20 +1122,20 @@ pub fn arrange_menu(app: &mut SlideApp, ui: &mut Ui) { menu_item(app, ui, ic, l, id, json!({})); } ui.separator(); - ui.label(egui::RichText::new("Group Objects").font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Group Objects")).font(theme::bold(12.0))); menu_item(app, ui, Icon::Group, "Group", "arrange.group", json!({})); menu_item(app, ui, Icon::Ungroup, "Ungroup", "arrange.ungroup", json!({})); menu_item(app, ui, Icon::Group, "Regroup", "arrange.regroup", json!({})); ui.separator(); - ui.label(egui::RichText::new("Position Objects").font(theme::bold(12.0))); - ui.menu_button("Align", |ui| align_menu(app, ui)); - ui.menu_button("Rotate", |ui| { + ui.label(egui::RichText::new(crate::i18n::tr("Position Objects")).font(theme::bold(12.0))); + ui.menu_button(crate::i18n::tr("Align"), |ui| align_menu(app, ui)); + ui.menu_button(crate::i18n::tr("Rotate"), |ui| { menu_item(app, ui, Icon::RotateRight, "Rotate Right 90°", "arrange.rotateRight", json!({})); menu_item(app, ui, Icon::RotateLeft, "Rotate Left 90°", "arrange.rotateLeft", json!({})); menu_item(app, ui, Icon::FlipV, "Flip Vertical", "arrange.flipVertical", json!({})); menu_item(app, ui, Icon::FlipH, "Flip Horizontal", "arrange.flipHorizontal", json!({})); }); - if ui.button("Selection Pane…").clicked() { + if ui.button(crate::i18n::tr("Selection Pane…")).clicked() { let _ = app.run("view.pane", json!({"pane": "selection"})); ui.close(); } @@ -1205,7 +1213,7 @@ fn insert(app: &mut SlideApp, ui: &mut Ui) { ui.close(); } ui.separator(); - if ui.button("Insert Table…").clicked() { + if ui.button(crate::i18n::tr("Insert Table…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("table")); ui.close(); } @@ -1219,7 +1227,7 @@ fn insert(app: &mut SlideApp, ui: &mut Ui) { big(app, ui, Icon::Picture, "Pictures", "app.insertPictureDialog", json!({})); photo_album_button(app, ui); let r = big_button(ui, Icon::Screenshot, "Screenshot", false); - let _ = r.on_hover_text("Screenshot (not available yet)"); + let _ = r.on_hover_text(crate::i18n::tr("Screenshot (not available yet)")); }); group(ui, |ui| { let r = big_button(ui, Icon::Shapes, "Shapes", enabled(app, "shape.insert")); @@ -1238,7 +1246,7 @@ fn insert(app: &mut SlideApp, ui: &mut Ui) { ui.separator(); } if let Some(k) = k - && ui.button(k.label()).clicked() + && ui.button(crate::i18n::tr(k.label())).clicked() { run(app, "insert.chart", json!({"type": format!("{k:?}")})); } @@ -1252,7 +1260,7 @@ fn insert(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::Action, "Action", enabled(app, "insert.actionButton")); egui::Popup::menu(&r).show(|ui| { for k in ["back", "forward", "beginning", "end", "home", "information", "return", "movie", "document", "sound", "help", "custom"] { - if ui.button(format!("Action Button: {k}")).clicked() { + if ui.button(crate::i18n::format("Action Button: {k}", &[(k).to_string()])).clicked() { run(app, "insert.actionButton", json!({"kind": k})); } } @@ -1272,7 +1280,7 @@ fn insert(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::WordArt, "WordArt", enabled(app, "insert.wordArt")); egui::Popup::menu(&r).show(|ui| { for i in 0..6 { - if ui.button(format!("WordArt style {}", i + 1)).clicked() { + if ui.button(crate::i18n::format("WordArt style {}", &[(i + 1).to_string()])).clicked() { run(app, "insert.wordArt", json!({"style": i})); } } @@ -1296,8 +1304,8 @@ pub fn table_grid_picker(ui: &mut Ui) -> Option<(usize, usize)> { let id = ui.id().with("tgrid"); let mut hover: (usize, usize) = ui.data_mut(|d| d.get_temp(id).unwrap_or((0, 0))); let cell = 16.0; - let label = if hover.0 > 0 { format!("{}x{} Table", hover.1, hover.0) } else { "Insert Table".into() }; - ui.label(label); + let label = if hover.0 > 0 { crate::i18n::format("{}x{} Table", &[(hover.1).to_string(), (hover.0).to_string()]) } else { "Insert Table".into() }; + ui.label(crate::i18n::tr(&label)); let (rect, resp) = ui.allocate_exact_size(vec2(10.0 * (cell + 2.0), 8.0 * (cell + 2.0)), Sense::click()); if let Some(p) = resp.hover_pos() { let c = ((p.x - rect.min.x) / (cell + 2.0)).floor() as usize + 1; @@ -1446,14 +1454,14 @@ fn draw(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let has_ink = app.session.doc().is_ok_and(|d| d.shapes().iter().any(|s| matches!(s.kind, deckcraft_model::ShapeKind::Ink { .. }))); let r = big_button(ui, Icon::InkToShape, "Ink to\nShape", has_ink); - if r.on_hover_text("Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes").clicked() { + if r.on_hover_text(crate::i18n::tr("Ink to Shape: turn drawn lines, rectangles, ovals and triangles into shapes")).clicked() { app.session.set_tool(ToolKind::Select); run(app, "draw.inkToShape", json!({})); } let r = big_button(ui, Icon::InkToText, "Ink to\nText", false); - let _ = r.on_hover_text("Ink to Text (coming soon)"); + let _ = r.on_hover_text(crate::i18n::tr("Ink to Text (coming soon)")); let r = big_button(ui, Icon::InkToMath, "Ink to\nMath", false); - let _ = r.on_hover_text("Ink to Math (coming soon)"); + let _ = r.on_hover_text(crate::i18n::tr("Ink to Math (coming soon)")); }); } @@ -1578,7 +1586,7 @@ fn design(app: &mut SlideApp, ui: &mut Ui) { }; let (rect, resp) = ui.allocate_exact_size(vec2(48.0, 28.0), Sense::click()); ui.painter().rect(rect, CornerRadius::same(2), shade, Stroke::new(1.0, Tokens::get(ui.ctx()).border), egui::StrokeKind::Inside); - if resp.on_hover_text(format!("Style {i}")).clicked() { + if resp.on_hover_text(crate::i18n::format("Style {i}", &[(i).to_string()])).clicked() { run(app, "design.background", json!({"style": i, "all": true})); ui.close(); } @@ -1587,7 +1595,7 @@ fn design(app: &mut SlideApp, ui: &mut Ui) { } } }); - if ui.button("Reset Slide Background").clicked() { + if ui.button(crate::i18n::tr("Reset Slide Background")).clicked() { run(app, "design.background", json!({"reset": true})); } }); @@ -1595,13 +1603,13 @@ fn design(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let r = big_button(ui, Icon::SlideSize, "Slide\nSize", true); egui::Popup::menu(&r).show(|ui| { - if ui.button("Standard (4:3)").clicked() { + if ui.button(crate::i18n::tr("Standard (4:3)")).clicked() { run(app, "design.slideSize", json!({"preset": "standard"})); } - if ui.button("Widescreen (16:9)").clicked() { + if ui.button(crate::i18n::tr("Widescreen (16:9)")).clicked() { run(app, "design.slideSize", json!({"preset": "widescreen"})); } - if ui.button("Page Setup…").clicked() { + if ui.button(crate::i18n::tr("Page Setup…")).clicked() { app.dialog = Some(crate::dialogs::Dialog::new("slideSize")); } }); @@ -1616,7 +1624,7 @@ pub fn paint_theme_tile(p: &egui::Painter, r: Rect, th: &deckcraft_model::Theme) let bg = theme::to_color32(th.colors.get(deckcraft_color::SchemeSlot::Lt1)); let fg = theme::to_color32(th.colors.get(deckcraft_color::SchemeSlot::Dk1)); p.rect(r, CornerRadius::same(2), bg, Stroke::new(1.0, Color32::from_gray(200)), egui::StrokeKind::Inside); - p.text(r.min + vec2(8.0, r.height() * 0.42), Align2::LEFT_CENTER, "Aa", theme::font(r.height() * 0.38), fg); + p.text(r.min + vec2(8.0, r.height() * 0.42), Align2::LEFT_CENTER, crate::i18n::tr("Aa"), theme::font(r.height() * 0.38), fg); let w = (r.width() - 16.0) / 6.0; for k in 0..6 { let c = theme::to_color32(th.colors.colors.get(4 + k).copied().unwrap_or(deckcraft_color::Rgba::BLACK)); @@ -1656,7 +1664,7 @@ fn transitions(app: &mut SlideApp, ui: &mut Ui) { let more = widgets::drop_button(ui, "", vec2(14.0, 52.0), true); egui::Popup::menu(&more).width(480.0).show(|ui| { for cat in ["Subtle", "Exciting", "Dynamic Content"] { - ui.label(egui::RichText::new(cat).font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr(cat)).font(theme::bold(12.0))); ui.horizontal_wrapped(|ui| { for x in list.iter().filter(|x| x.2 == cat) { let (r, resp) = ui.allocate_exact_size(vec2(56.0, 58.0), Sense::click()); @@ -1679,7 +1687,7 @@ fn transitions(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::EffectOptions, "Effect\nOptions", !rows.is_empty()); egui::Popup::menu(&r).show(|ui| { for &(o, on) in &rows { - if ui.selectable_label(on, deckcraft_model::anim::transition_option_label(&kind, o)).clicked() { + if ui.selectable_label(on, crate::i18n::tr(&deckcraft_model::anim::transition_option_label(&kind, o))).clicked() { run(app, "transition.options", json!({"option": o})); ui.close(); } @@ -1730,7 +1738,7 @@ fn transitions(app: &mut SlideApp, ui: &mut Ui) { }); rows(ui, |ui| { ui.horizontal(|ui| { - ui.label("Duration:"); + ui.label(crate::i18n::tr("Duration:")); let d = cur.as_ref().map(|t| t.duration_ms as f64 / 1000.0).unwrap_or(1.0); if let Some(v) = widgets::spinner(ui, "tdur", d, 0.25, "", 46.0) { run(app, "transition.timing", json!({"duration": (v.max(0.0) * 1000.0).round() as u64})); @@ -1738,14 +1746,14 @@ fn transitions(app: &mut SlideApp, ui: &mut Ui) { }); ui.horizontal(|ui| { let mut click = cur.as_ref().is_none_or(|t| t.advance_on_click); - if ui.checkbox(&mut click, "On Mouse Click").changed() { + if ui.checkbox(&mut click, crate::i18n::tr("On Mouse Click")).changed() { run(app, "transition.timing", json!({"onClick": click})); } }); ui.horizontal(|ui| { let after = cur.as_ref().and_then(|t| t.advance_after_ms); let mut on = after.is_some(); - if ui.checkbox(&mut on, "After:").changed() { + if ui.checkbox(&mut on, crate::i18n::tr("After:")).changed() { run(app, "transition.timing", json!({"after": if on { json!(after.unwrap_or(0)) } else { Value::Null }})); } if let Some(v) = widgets::spinner(ui, "tafter", after.unwrap_or(0) as f64 / 1000.0, 1.0, "", 46.0) { @@ -1757,12 +1765,17 @@ fn transitions(app: &mut SlideApp, ui: &mut Ui) { }); } -fn option_label(o: &str) -> String { +pub(crate) fn option_label(o: &str) -> String { match o { "l" => "From Left".into(), "r" => "From Right".into(), "u" => "From Top".into(), - "d" => "From Bottom".into(), + "d" | "b" => "From Bottom".into(), + "t" => "From Top".into(), + "lb" | "ld" => "From Bottom Left".into(), + "rb" | "rd" => "From Bottom Right".into(), + "lt" | "lu" => "From Top Left".into(), + "rt" | "ru" => "From Top Right".into(), "horz" => "Horizontal".into(), "vert" => "Vertical".into(), "in" => "In".into(), @@ -1849,7 +1862,7 @@ pub fn paint_transition_tile(p: &egui::Painter, r: Rect, (id, label): (&str, &st } } p.rect_stroke(pic, CornerRadius::same(2), Stroke::new(1.0, Color32::from_rgb(0x9B, 0xB4, 0xDB)), egui::StrokeKind::Inside); - p.text(pos2(r.center().x, r.max.y - 7.0), Align2::CENTER_CENTER, label, theme::font(10.0), t.text); + p.text(pos2(r.center().x, r.max.y - 7.0), Align2::CENTER_CENTER, crate::i18n::tr(label), theme::font(10.0), t.text); } // ---------- Animations ---------- @@ -1911,7 +1924,7 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { for (cls, label) in [(AnimClass::Entrance, "Entrance"), (AnimClass::Emphasis, "Emphasis"), (AnimClass::Exit, "Exit"), (AnimClass::Path, "Motion Paths")] { - ui.label(egui::RichText::new(label).font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr(label)).font(theme::bold(12.0))); ui.horizontal_wrapped(|ui| { for a in deckcraft_model::anim::ANIMATIONS.iter().filter(|a| a.2 == cls) { let (r, resp) = ui.allocate_exact_size(vec2(56.0, 54.0), Sense::click()); @@ -1933,7 +1946,7 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::EffectOptions, "Effect\nOptions", !effect_rows.is_empty()); egui::Popup::menu(&r).show(|ui| { for &(o, on) in &effect_rows { - if ui.selectable_label(on, option_label(o)).clicked() { + if ui.selectable_label(on, crate::i18n::tr(&option_label(o))).clicked() { run(app, "animation.options", json!({"option": o})); ui.close(); } @@ -1941,7 +1954,7 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { ui.separator(); for &(id, on) in &build_rows { let label = if id == "byParagraph" { "By Paragraph" } else { "As One Object" }; - if ui.selectable_label(on, label).clicked() { + if ui.selectable_label(on, crate::i18n::tr(label)).clicked() { run(app, "animation.options", json!({"textBuild": id})); ui.close(); } @@ -1972,13 +1985,13 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { big(app, ui, Icon::AnimationPane, "Animation\nPane", "view.pane", json!({"pane": "animation"})); let r = big_button(ui, Icon::Trigger, "Trigger", cur.is_some()); egui::Popup::menu(&r).show(|ui| { - if ui.button("On Click of… (none)").clicked() { + if ui.button(crate::i18n::tr("On Click of… (none)")).clicked() { run(app, "animation.timing", json!({"trigger": null})); } let shapes: Vec<(u32, String)> = app.session.active().map(|d| d.shapes().iter().map(|s| (s.id.0, s.name.clone())).collect()).unwrap_or_default(); for (id, name) in shapes { - if ui.button(format!("On Click of {name}")).clicked() { + if ui.button(crate::i18n::format("On Click of {name}", std::slice::from_ref(&name))).clicked() { run(app, "animation.timing", json!({"trigger": id})); } } @@ -2000,15 +2013,15 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { rows(ui, |ui| { ui.horizontal(|ui| { - ui.label("Start:"); + ui.label(crate::i18n::tr("Start:")); let s = cur.as_ref().map(|c| match c.start { deckcraft_model::AnimStart::OnClick => "On Click", deckcraft_model::AnimStart::WithPrevious => "With Previous", deckcraft_model::AnimStart::AfterPrevious => "After Previous", }); - dropdown(ui, "astart", s.unwrap_or(""), 112.0, cur.is_some(), |ui| { + dropdown(ui, "astart", crate::i18n::tr(s.unwrap_or("")), 112.0, cur.is_some(), |ui| { for (l, v) in [("On Click", "onClick"), ("With Previous", "withPrevious"), ("After Previous", "afterPrevious")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "animation.timing", json!({"start": v})); ui.close(); } @@ -2016,13 +2029,13 @@ fn animations(app: &mut SlideApp, ui: &mut Ui) { }); }); ui.horizontal(|ui| { - ui.label("Duration:"); + ui.label(crate::i18n::tr("Duration:")); if let Some(v) = widgets::spinner(ui, "adur", cur.as_ref().map(|c| c.duration_ms as f64 / 1000.0).unwrap_or(0.5), 0.25, "", 46.0) { run(app, "animation.timing", json!({"duration": (v.max(0.0) * 1000.0).round() as u64})); } }); ui.horizontal(|ui| { - ui.label("Delay:"); + ui.label(crate::i18n::tr("Delay:")); if let Some(v) = widgets::spinner(ui, "adelay", cur.as_ref().map(|c| c.delay_ms as f64 / 1000.0).unwrap_or(0.0), 0.25, "", 46.0) { run(app, "animation.timing", json!({"delay": (v.max(0.0) * 1000.0).round() as u64})); } @@ -2040,7 +2053,13 @@ pub fn paint_anim_tile(p: &egui::Painter, r: Rect, label: &str, class: AnimClass _ => Icon::AnimPath, }; icons::paint(p, Rect::from_center_size(pos2(r.center().x, r.min.y + 18.0), vec2(28.0, 28.0)), icon, t.text, !enabled); - p.text(pos2(r.center().x, r.max.y - 8.0), Align2::CENTER_CENTER, label, theme::font(10.0), if enabled { t.text } else { t.text_faint }); + p.text( + pos2(r.center().x, r.max.y - 8.0), + Align2::CENTER_CENTER, + crate::i18n::tr(label), + theme::font(10.0), + if enabled { t.text } else { t.text_faint }, + ); } // ---------- Slide Show / Record / Review / View ---------- @@ -2075,20 +2094,20 @@ fn slide_show(app: &mut SlideApp, ui: &mut Ui) { } } let r = big_button(ui, Icon::Record, "Record", false); - let _ = r.on_hover_text("Recording narration needs audio capture (coming soon)"); + let _ = r.on_hover_text(crate::i18n::tr("Recording narration needs audio capture (coming soon)")); }); group(ui, |ui| { rows(ui, |ui| { let mut use_t = app.session.active().is_none_or(|d| d.doc.show.use_timings); - if ui.checkbox(&mut use_t, "Use Timings").changed() { + if ui.checkbox(&mut use_t, crate::i18n::tr("Use Timings")).changed() { run(app, "show.setup", json!({"useTimings": use_t})); } let mut narr = app.session.active().is_none_or(|d| !d.doc.show.without_narration); - if ui.checkbox(&mut narr, "Play Narrations").changed() { + if ui.checkbox(&mut narr, crate::i18n::tr("Play Narrations")).changed() { run(app, "show.setup", json!({"noNarration": !narr})); } let mut mc = app.session.active().is_none_or(|d| d.doc.show.show_media_controls); - if ui.checkbox(&mut mc, "Show Media Controls").changed() { + if ui.checkbox(&mut mc, crate::i18n::tr("Show Media Controls")).changed() { run(app, "show.setup", json!({"showMediaControls": mc})); } }); @@ -2098,7 +2117,7 @@ fn slide_show(app: &mut SlideApp, ui: &mut Ui) { fn record(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let r = big_button(ui, Icon::Cameo, "Cameo", false); - let _ = r.on_hover_text("Camera capture is not available yet"); + let _ = r.on_hover_text(crate::i18n::tr("Camera capture is not available yet")); if big_button(ui, Icon::PlayFromStart, "From\nBeginning", true).clicked() { app.start_show(app.show_start_index(), false); if let Some(s) = app.show.as_mut() { @@ -2147,7 +2166,7 @@ fn review(app: &mut SlideApp, ui: &mut Ui) { }); group(ui, |ui| { let r = big_button(ui, Icon::Translate, "Translate", false); - let _ = r.on_hover_text("Translation needs a language model (not bundled)"); + let _ = r.on_hover_text(crate::i18n::tr("Translation needs a language model (not bundled)")); big(app, ui, Icon::Language, "Language", "app.dialog", json!({"id": "language"})); }); group(ui, |ui| { @@ -2210,15 +2229,15 @@ fn view(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { rows(ui, |ui| { let mut r = app.ui.ruler; - if ui.checkbox(&mut r, "Ruler").changed() { + if ui.checkbox(&mut r, crate::i18n::tr("Ruler")).changed() { app.ui.ruler = r; } let mut g = app.ui.gridlines; - if ui.checkbox(&mut g, "Gridlines").changed() { + if ui.checkbox(&mut g, crate::i18n::tr("Gridlines")).changed() { app.ui.gridlines = g; } let mut gd = app.ui.guides; - if ui.checkbox(&mut gd, "Guides").changed() { + if ui.checkbox(&mut gd, crate::i18n::tr("Guides")).changed() { app.ui.guides = gd; } }); @@ -2387,7 +2406,7 @@ fn shape_format(app: &mut SlideApp, ui: &mut Ui) { big(app, ui, Icon::TextBox, "Text\nBox", "insert.textBox", json!({})); let r = big_button(ui, Icon::EditShape, "Edit\nShape", sel); egui::Popup::menu(&r).show(|ui| { - ui.label("Change Shape"); + ui.label(crate::i18n::tr("Change Shape")); if let Some(p) = shapes_gallery(ui) { run(app, "shape.change", json!({"preset": p})); } @@ -2400,10 +2419,10 @@ fn shape_format(app: &mut SlideApp, ui: &mut Ui) { smooth_corners_row(app, ui); }); let can_merge = enabled(app, "shape.merge"); - let r = big_button(ui, Icon::MergeShapes, "Merge\nShapes", can_merge).on_hover_text("Merge Shapes"); + let r = big_button(ui, Icon::MergeShapes, "Merge\nShapes", can_merge).on_hover_text(crate::i18n::tr("Merge Shapes")); egui::Popup::menu(&r).show(|ui| { for (op, label) in deckcraft_engine::cmd::merge::OPS { - if ui.button(label).clicked() { + if ui.button(crate::i18n::tr(label)).clicked() { run(app, "shape.merge", json!({"op": op})); ui.close(); } @@ -2426,7 +2445,7 @@ fn shape_format(app: &mut SlideApp, ui: &mut Ui) { None => run(app, "shape.fill", json!({"none": true})), } } - if ui.button("Gradient…").clicked() { + if ui.button(crate::i18n::tr("Gradient…")).clicked() { let _ = app.run("view.pane", json!({"pane": "format", "tab": "fill"})); ui.close(); } @@ -2466,7 +2485,7 @@ fn shape_format(app: &mut SlideApp, ui: &mut Ui) { } let r = small_button(ui, Icon::TextEffects, "Text Effects", sel, false); egui::Popup::menu(&r).width(312.0).show(|ui| { - if ui.button("Shadow").clicked() { + if ui.button(crate::i18n::tr("Shadow")).clicked() { run(app, "format.textShadow", json!({})); ui.close(); } @@ -2541,18 +2560,18 @@ fn size_group(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { rows(ui, |ui| { let Some(x) = bx else { - ui.label("Height:"); - ui.label("Width:"); + ui.label(crate::i18n::tr("Height:")); + ui.label(crate::i18n::tr("Width:")); return; }; ui.horizontal(|ui| { - ui.label("Height:"); + ui.label(crate::i18n::tr("Height:")); if let Some(v) = widgets::spinner(ui, "sh", x.h / 72.0, 0.1, "\"", 54.0) { run(app, "shape.resize", json!({"h": v.max(0.0) * 72.0})); } }); ui.horizontal(|ui| { - ui.label("Width: "); + ui.label(crate::i18n::tr("Width: ")); if let Some(v) = widgets::spinner(ui, "sw", x.w / 72.0, 0.1, "\"", 54.0) { run(app, "shape.resize", json!({"w": v.max(0.0) * 72.0})); } @@ -2577,13 +2596,13 @@ fn picture_format(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::Corrections, "Corrections", true); egui::Popup::menu(&r).show(|ui| { for b in [-0.4, -0.2, 0.0, 0.2, 0.4] { - if ui.button(format!("Brightness {:+}%", (b * 100.0) as i32)).clicked() { + if ui.button(crate::i18n::format("Brightness {:+}%", &[format!("{:+}", (b * 100.0) as i32)])).clicked() { run(app, "picture.adjust", json!({"brightness": b})); } } ui.separator(); for c in [-0.4, -0.2, 0.0, 0.2, 0.4] { - if ui.button(format!("Contrast {:+}%", (c * 100.0) as i32)).clicked() { + if ui.button(crate::i18n::format("Contrast {:+}%", &[format!("{:+}", (c * 100.0) as i32)])).clicked() { run(app, "picture.adjust", json!({"contrast": c})); } } @@ -2591,7 +2610,7 @@ fn picture_format(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::ColorAdjust, "Color", true); egui::Popup::menu(&r).show(|ui| { for s in [0.0, 0.33, 0.66, 1.0, 1.5, 2.0, 3.0] { - if ui.button(format!("Saturation {}%", (s * 100.0) as i32)).clicked() { + if ui.button(crate::i18n::format("Saturation {}%", &[((s * 100.0) as i32).to_string()])).clicked() { run(app, "picture.adjust", json!({"saturation": s})); } } @@ -2717,13 +2736,13 @@ fn picture_format(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { let r = big_button(ui, Icon::Crop, "Crop", true); egui::Popup::menu(&r).show(|ui| { - ui.label("Crop to Shape"); + ui.label(crate::i18n::tr("Crop to Shape")); if let Some(p) = shapes_gallery(ui) { run(app, "shape.change", json!({"preset": p})); } ui.separator(); for (l, v) in [("Crop 10% each side", 0.1), ("Crop 20% each side", 0.2), ("Reset Crop", 0.0)] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "picture.crop", json!({"left": v, "top": v, "right": v, "bottom": v})); } } @@ -2742,31 +2761,31 @@ fn table_design(app: &mut SlideApp, ui: &mut Ui) { let flags = tbl.as_ref().map(|t| (t.first_row, t.last_row, t.band_row, t.first_col, t.last_col, t.band_col)).unwrap_or_default(); ui.horizontal(|ui| { let mut a = flags.0; - if ui.checkbox(&mut a, "Header Row").changed() { + if ui.checkbox(&mut a, crate::i18n::tr("Header Row")).changed() { run(app, "table.options", json!({"headerRow": a})); } let mut d = flags.3; - if ui.checkbox(&mut d, "First Column").changed() { + if ui.checkbox(&mut d, crate::i18n::tr("First Column")).changed() { run(app, "table.options", json!({"firstColumn": d})); } }); ui.horizontal(|ui| { let mut b = flags.1; - if ui.checkbox(&mut b, "Total Row").changed() { + if ui.checkbox(&mut b, crate::i18n::tr("Total Row")).changed() { run(app, "table.options", json!({"totalRow": b})); } let mut e = flags.4; - if ui.checkbox(&mut e, "Last Column").changed() { + if ui.checkbox(&mut e, crate::i18n::tr("Last Column")).changed() { run(app, "table.options", json!({"lastColumn": e})); } }); ui.horizontal(|ui| { let mut c = flags.2; - if ui.checkbox(&mut c, "Banded Rows").changed() { + if ui.checkbox(&mut c, crate::i18n::tr("Banded Rows")).changed() { run(app, "table.options", json!({"bandedRows": c})); } let mut f = flags.5; - if ui.checkbox(&mut f, "Banded Columns").changed() { + if ui.checkbox(&mut f, crate::i18n::tr("Banded Columns")).changed() { run(app, "table.options", json!({"bandedColumns": f})); } }); @@ -2799,7 +2818,7 @@ fn table_design(app: &mut SlideApp, ui: &mut Ui) { for (id, label) in &styles { let (r, resp) = ui.allocate_exact_size(vec2(48.0, 36.0), Sense::click()); paint_table_style(ui.painter(), r.shrink(2.0), id, &sc); - if resp.on_hover_text(label).clicked() { + if resp.on_hover_text(crate::i18n::tr(label)).clicked() { run(app, "table.style", json!({"style": id})); ui.close(); } @@ -3018,7 +3037,7 @@ fn table_layout(app: &mut SlideApp, ui: &mut Ui) { }); ui.horizontal(|ui| { for (l, a) in [("Top", "top"), ("Center", "middle"), ("Bottom", "bottom")] { - if ui.small_button(l).on_hover_text(format!("Align text to the {l} of the cell").to_lowercase()).clicked() { + if ui.small_button(crate::i18n::tr(l)).on_hover_text(format!("Align text to the {l} of the cell").to_lowercase()).clicked() { run(app, "table.cellAlign", json!({"anchor": a})); } } @@ -3045,7 +3064,7 @@ fn chart_design(app: &mut SlideApp, ui: &mut Ui) { ui.separator(); continue; }; - if ui.button(k.label()).clicked() { + if ui.button(crate::i18n::tr(k.label())).clicked() { // Replace the chart's type keeping its data. if let Some(id) = app.session.active().and_then(|d| d.selection.shapes.first().copied()) { let _ = app.run("chart.type", json!({"id": id.0, "type": format!("{k:?}")})); @@ -3163,29 +3182,29 @@ fn playback(app: &mut SlideApp, ui: &mut Ui) { group(ui, |ui| { rows(ui, |ui| { let mut auto = m.as_ref().is_some_and(|x| x.autoplay); - if ui.checkbox(&mut auto, "Start Automatically").changed() { + if ui.checkbox(&mut auto, crate::i18n::tr("Start Automatically")).changed() { run(app, "media.options", json!({"autoplay": auto})); } let mut across = m.as_ref().is_some_and(|x| x.play_across_slides); - if ui.checkbox(&mut across, "Play Across Slides").changed() { + if ui.checkbox(&mut across, crate::i18n::tr("Play Across Slides")).changed() { run(app, "media.options", json!({"acrossSlides": across})); } let mut lp = m.as_ref().is_some_and(|x| x.loop_play); - if ui.checkbox(&mut lp, "Loop until Stopped").changed() { + if ui.checkbox(&mut lp, crate::i18n::tr("Loop until Stopped")).changed() { run(app, "media.options", json!({"loop": lp})); } }); rows(ui, |ui| { let mut hide = m.as_ref().is_some_and(|x| x.hide_while_not_playing); - if ui.checkbox(&mut hide, "Hide During Show").changed() { + if ui.checkbox(&mut hide, crate::i18n::tr("Hide During Show")).changed() { run(app, "media.options", json!({"hide": hide})); } let mut rw = m.as_ref().is_some_and(|x| x.rewind); - if ui.checkbox(&mut rw, "Rewind after Playing").changed() { + if ui.checkbox(&mut rw, crate::i18n::tr("Rewind after Playing")).changed() { run(app, "media.options", json!({"rewind": rw})); } let mut fs = m.as_ref().is_some_and(|x| x.full_screen); - if ui.checkbox(&mut fs, "Play Full Screen").changed() { + if ui.checkbox(&mut fs, crate::i18n::tr("Play Full Screen")).changed() { run(app, "media.options", json!({"fullScreen": fs})); } }); @@ -3194,7 +3213,7 @@ fn playback(app: &mut SlideApp, ui: &mut Ui) { let r = big_button(ui, Icon::Volume, "Volume", m.is_some()); egui::Popup::menu(&r).show(|ui| { for (l, v) in [("Low", 0.25), ("Medium", 0.5), ("High", 1.0), ("Mute", 0.0)] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "media.options", json!({"volume": v})); } } @@ -3244,7 +3263,7 @@ fn slide_master(app: &mut SlideApp, ui: &mut Ui) { for (l, k) in [("Content", "content"), ("Text", "text"), ("Picture", "picture"), ("Chart", "chart"), ("Table", "table"), ("Media", "media")] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { run(app, "master.insertPlaceholder", json!({"kind": k})); } } diff --git a/crates/ui-egui/src/show.rs b/crates/ui-egui/src/show.rs index a875773cd..2b8a5faac 100644 --- a/crates/ui-egui/src/show.rs +++ b/crates/ui-egui/src/show.rs @@ -688,7 +688,7 @@ pub fn ui(app: &mut SlideApp, ui: &mut Ui) { painter.text( pos2(full.center().x, full.min.y + 40.0), Align2::CENTER_CENTER, - "End of slide show, click to exit.", + crate::i18n::tr("End of slide show, click to exit."), theme::font(18.0), Color32::from_gray(200), ); @@ -954,7 +954,7 @@ pub fn ui(app: &mut SlideApp, ui: &mut Ui) { painter.text( pos2(bar.min.x + 14.0, bar.center().y), Align2::LEFT_CENTER, - format!("Slide {} of {}", show.state.slide + 1, doc.slides.len()), + crate::i18n::format("Slide {} of {}", &[(show.state.slide + 1).to_string(), (doc.slides.len()).to_string()]), theme::font(12.0), Color32::from_gray(200), ); @@ -963,7 +963,7 @@ pub fn ui(app: &mut SlideApp, ui: &mut Ui) { .max_rect(Rect::from_min_max(pos2(bar.max.x - 260.0, bar.min.y), bar.max)) .layout(egui::Layout::right_to_left(egui::Align::Center)), ); - if child.button("Close").clicked() { + if child.button(crate::i18n::tr("Close")).clicked() { keep = false; } if child.button("▶").clicked() { @@ -1026,7 +1026,15 @@ pub fn ui(app: &mut SlideApp, ui: &mut Ui) { painter.text( r.center(), Align2::CENTER_CENTER, - format!("Slide {:02}:{:04.1} Total {:02}:{:02}", (t / 60.0) as u32, t % 60.0, (total / 60.0) as u32, (total % 60.0) as u32), + crate::i18n::format( + "Slide {:02}:{:04.1} Total {:02}:{:02}", + &[ + format!("{:02}", (t / 60.0) as u32), + format!("{:04.1}", t % 60.0), + format!("{:02}", (total / 60.0) as u32), + format!("{:02}", (total % 60.0) as u32), + ], + ), theme::font(13.0), Color32::WHITE, ); @@ -1754,7 +1762,7 @@ fn presenter_window(ctx: &egui::Context, show: &mut Show, doc: &Presentation, no }; ctx.show_viewport_immediate( egui::ViewportId::from_hash_of("deckcraft_presenter"), - egui::ViewportBuilder::default().with_title("Presenter View — DeckCraft").with_inner_size([1100.0, 700.0]), + egui::ViewportBuilder::default().with_title(crate::i18n::tr("Presenter View — DeckCraft")).with_inner_size([1100.0, 700.0]), |ui, _| { if !keyboard(ui.ctx(), show, doc, now) { *keep = false; @@ -1772,15 +1780,19 @@ fn presenter_window(ctx: &egui::Context, show: &mut Show, doc: &Presentation, no ui.add_space(12.0); ui.label(egui::RichText::new(clock.clone()).size(16.0).color(Color32::from_gray(200))); ui.add_space(20.0); - ui.label(egui::RichText::new(format!("Slide {} of {}", cur + 1, doc.slides.len())).size(16.0).color(Color32::from_gray(200))); + ui.label( + egui::RichText::new(crate::i18n::format("Slide {} of {}", &[(cur + 1).to_string(), (doc.slides.len()).to_string()])) + .size(16.0) + .color(Color32::from_gray(200)), + ); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - if button(ui, "End Show").clicked() { + if button(ui, crate::i18n::tr("End Show")).clicked() { *keep = false; } - if button(ui, "Next ▶").clicked() { + if button(ui, crate::i18n::tr("Next ▶")).clicked() { actions.push(show.state.next(doc)); } - if button(ui, "◀ Previous").clicked() { + if button(ui, crate::i18n::tr("◀ Previous")).clicked() { actions.push(show.state.prev(doc)); } }); @@ -1833,14 +1845,20 @@ fn presenter_window(ctx: &egui::Context, show: &mut Show, doc: &Presentation, no ui.painter().rect_filled(cr, CornerRadius::ZERO, c); } let nr = next_rect(right, doc); - ui.painter().text(right.min, Align2::LEFT_TOP, "Next", theme::font(13.0), Color32::from_gray(170)); + ui.painter().text(right.min, Align2::LEFT_TOP, crate::i18n::tr("Next"), theme::font(13.0), Color32::from_gray(170)); match &next_tex { Some(t) => { ui.painter().image(t.id(), nr, Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0)), Color32::WHITE); } None => { ui.painter().rect_filled(nr, CornerRadius::ZERO, Color32::from_gray(40)); - ui.painter().text(nr.center(), Align2::CENTER_CENTER, "End of slide show", theme::font(13.0), Color32::from_gray(170)); + ui.painter().text( + nr.center(), + Align2::CENTER_CENTER, + crate::i18n::tr("End of slide show"), + theme::font(13.0), + Color32::from_gray(170), + ); } } let notes_head = Rect::from_min_size(pos2(right.min.x, nr.max.y + 12.0), vec2(right.width(), 28.0)); diff --git a/crates/ui-egui/src/sorter.rs b/crates/ui-egui/src/sorter.rs index 4c97605ca..bcddb5e8f 100644 --- a/crates/ui-egui/src/sorter.rs +++ b/crates/ui-egui/src/sorter.rs @@ -413,7 +413,7 @@ pub fn notes_page(app: &mut SlideApp, ui: &mut Ui) { let look = crate::notes::Look { size: 14.0, color: Some(Color32::from_gray(30)) }; let width = notes_rect.width(); let r = crate::notes::editor(&mut child, &mut draft, &look, |e| { - e.id(edit_id).hint_text("Click to add text").desired_width(width).desired_rows(12).frame(egui::Frame::NONE) + e.id(edit_id).hint_text(crate::i18n::tr("Click to add text")).desired_width(width).desired_rows(12).frame(egui::Frame::NONE) }) .response .response; diff --git a/crates/ui-egui/src/status.rs b/crates/ui-egui/src/status.rs index d5d03cdf1..c90d6788f 100644 --- a/crates/ui-egui/src/status.rs +++ b/crates/ui-egui/src/status.rs @@ -15,16 +15,22 @@ pub fn status_bar(app: &mut SlideApp, ui: &mut Ui) { let Some(st) = app.session.active() else { return }; let n = st.doc.slides.len(); let left = match st.selection.target { - deckcraft_engine::Target::Slides => format!("Slide {} of {}", (st.selection.slide + 1).min(n.max(1)), n), - _ => "Slide Master".to_string(), + deckcraft_engine::Target::Slides => { + crate::i18n::format("Slide {} of {}", &[((st.selection.slide + 1).min(n.max(1))).to_string(), (n).to_string()]) + } + _ => crate::i18n::tr("Slide Master").to_string(), }; let p = ui.painter(); p.text(pos2(rect.min.x + 14.0, rect.center().y), Align2::LEFT_CENTER, &left, theme::font(12.0), t.text_dim); // The selection's proofing language; a click opens Review › Language. let (lang, no_proof) = crate::dialogs::selected_language(app); - let name = crate::squiggles::lang_name(&lang) + if no_proof { " (not checked)" } else { "" }; + let name = crate::squiggles::lang_name(&lang) + if no_proof { crate::i18n::tr(" (not checked)") } else { "" }; let lr = p.text(pos2(rect.min.x + 120.0, rect.center().y), Align2::LEFT_CENTER, &name, theme::font(12.0), t.text_dim); - if ui.interact(lr.expand(3.0), ui.id().with("status_lang"), Sense::click()).on_hover_text("Language").clicked() { + if ui + .interact(lr.expand(3.0), ui.id().with("status_lang"), Sense::click()) + .on_hover_text(crate::i18n::tr("Language")) + .clicked() + { app.dialog = Some(crate::dialogs::Dialog::new("language")); } // Transient status message. @@ -95,10 +101,11 @@ fn small_icon(ui: &mut Ui, icon: Icon, tip: &str, on: bool) -> egui::Response { ui.painter().rect_filled(r, CornerRadius::same(4), if on { t.selected } else { t.hover }); } icons::paint(ui.painter(), Rect::from_center_size(r.center(), vec2(16.0, 16.0)), icon, t.text_dim, false); - resp.on_hover_text(tip) + resp.on_hover_text(crate::i18n::tr(tip)) } fn labeled(ui: &mut Ui, icon: Icon, label: &str, on: bool) -> egui::Response { + let label = crate::i18n::tr(label); let t = Tokens::get(ui.ctx()); let w = 22.0 + ui.fonts_mut(|f| f.layout_no_wrap(label.into(), theme::font(12.0), t.text).size().x) + 8.0; let (r, resp) = ui.allocate_exact_size(vec2(w, 20.0), Sense::click()); @@ -106,7 +113,7 @@ fn labeled(ui: &mut Ui, icon: Icon, label: &str, on: bool) -> egui::Response { ui.painter().rect_filled(r, CornerRadius::same(4), if on { t.selected } else { t.hover }); } icons::paint(ui.painter(), Rect::from_center_size(pos2(r.min.x + 11.0, r.center().y), vec2(15.0, 15.0)), icon, t.text_dim, false); - ui.painter().text(pos2(r.min.x + 22.0, r.center().y), Align2::LEFT_CENTER, label, theme::font(12.0), t.text_dim); + ui.painter().text(pos2(r.min.x + 22.0, r.center().y), Align2::LEFT_CENTER, crate::i18n::tr(label), theme::font(12.0), t.text_dim); resp } @@ -156,7 +163,7 @@ pub fn notes_pane(app: &mut SlideApp, ui: &mut Ui) { .auto_shrink([false, false]) .show(ui, |ui| { crate::notes::editor(ui, &mut draft, &look, |e| { - e.id(id).hint_text("Click to add notes").frame(egui::Frame::NONE).desired_width(f32::INFINITY).desired_rows(2) + e.id(id).hint_text(crate::i18n::tr("Click to add notes")).frame(egui::Frame::NONE).desired_width(f32::INFINITY).desired_rows(2) }) }) .inner; diff --git a/crates/ui-egui/src/textures.rs b/crates/ui-egui/src/textures.rs index 49df4144c..2ab516b5b 100644 --- a/crates/ui-egui/src/textures.rs +++ b/crates/ui-egui/src/textures.rs @@ -18,6 +18,7 @@ struct Key { master: usize, size: (u32, u32), edit: bool, + language: crate::i18n::Language, extra: u64, /// The pasteboard region the slide's drawing calls for (canvas only). want: Region, @@ -287,6 +288,7 @@ impl Textures { master: master.as_ref().map(|m| Arc::as_ptr(m) as usize).unwrap_or(0), size, edit, + language: if edit { crate::i18n::current() } else { crate::i18n::Language::En }, extra: extra ^ grayscale as u64 ^ anim_key(anim), want, editing_text, @@ -304,6 +306,7 @@ impl Textures { scale, edit, gif_times, + placeholder_prompt: Some(crate::i18n::placeholder_prompt), threads: threads(), offset: region.offset(), size: Some(region.size()), @@ -364,6 +367,7 @@ impl Textures { master: master.as_ref().map(|m| Arc::as_ptr(m) as usize).unwrap_or(0), size: (width_px, h), edit: false, + language: crate::i18n::Language::En, extra: 0, want: Region::slide(width_px, h), editing_text: None, @@ -401,7 +405,10 @@ impl Textures { #[cfg(test)] mod tests { + #![allow(clippy::unwrap_used, clippy::expect_used)] + use super::device_pixel_rect; + use super::*; use egui::{Rect, pos2, vec2}; fn on_grid(v: f32, ppp: f32) -> bool { @@ -430,6 +437,46 @@ mod tests { assert_eq!(device_pixel_rect(r, 0.0), r); assert_eq!(device_pixel_rect(r, f32::NAN), r); } + + #[test] + fn switching_interface_language_refreshes_cached_hints_and_preserves_user_content() { + fn updated_canvas(ctx: &egui::Context, textures: &mut Textures, p: &Presentation, language: crate::i18n::Language) -> egui::ImageData { + crate::i18n::set_current(language); + let tex = textures.slide(ctx, p, 0, (480, 270), Region::slide(480, 270), true, 0, false, &[], None, None).unwrap(); + let mut delta = ctx.tex_manager().write().take_delta(); + let image = delta.set.get(&tex.0.id()).and_then(|images| images.last()).map(|image| image.image.clone()); + delta.clear(); + image.expect("the changed interface language must update the canvas texture") + } + + let ctx = egui::Context::default(); + let mut textures = Textures::default(); + let mut p = Presentation::default(); + let before = p.clone(); + let english = updated_canvas(&ctx, &mut textures, &p, crate::i18n::Language::En); + let ukrainian = updated_canvas(&ctx, &mut textures, &p, crate::i18n::Language::Uk); + assert!(english != ukrainian, "the default placeholder hints must change visibly"); + assert_eq!(p, before); + + for master in &mut p.masters { + for layout in &mut Arc::make_mut(master).layouts { + for shape in &mut layout.shapes { + if let Some(ph) = &mut shape.ph { + ph.has_custom_prompt = true; + shape.text = Some(deckcraft_model::TextBody::from_text("Custom {project} prompt")); + } + } + } + } + Arc::make_mut(p.slides.first_mut().unwrap()).shapes.first_mut().unwrap().text = + Some(deckcraft_model::TextBody::from_text("User File {project}")); + let before = p.clone(); + let english = updated_canvas(&ctx, &mut textures, &p, crate::i18n::Language::En); + let ukrainian = updated_canvas(&ctx, &mut textures, &p, crate::i18n::Language::Uk); + assert!(english == ukrainian, "stored text and custom prompts must retain their original wording"); + assert_eq!(p, before); + crate::i18n::set_current(crate::i18n::Language::En); + } } /// `r` cut to at most `max` pixels a side, keeping as much of `visible` as fits. diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 1847d47f1..1fa9b82dd 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -182,8 +182,16 @@ pub fn font_definitions(extra: &[std::sync::Arc]) -> } let regular: Vec = names.iter().filter(|(fam, st, _)| !(*fam == "Inter" && *st != "Regular")).map(|(_, _, n)| n.clone()).collect(); if let Some(list) = defs.families.get_mut(&FontFamily::Proportional) { - for (k, n) in regular.iter().enumerate() { - list.insert(k, n.clone()); + // The craft faces lead the interface only when they include the Latin face (Inter); the + // Latin manifest is optional in craft-fonts, and without it BIZ UDPGothic would become the + // primary interface font, with much wider Latin metrics (clipped ribbons, shifted hit + // targets). Then the script faces still serve, as fallbacks after egui's bundled ones. + if regular.iter().any(|n| n.contains("-Inter-")) { + for (k, n) in regular.iter().enumerate() { + list.insert(k, n.clone()); + } + } else { + list.extend(regular.iter().cloned()); } } // A bold family for headings and selected tabs. @@ -191,9 +199,8 @@ pub fn font_definitions(extra: &[std::sync::Arc]) -> bold.extend(defs.families.get(&FontFamily::Proportional).cloned().unwrap_or_default()); defs.families.insert(FontFamily::Name("bold".into()), bold); add_fallback_faces(&mut defs, extra); - // The Japanese interface face (the first one when Inter isn't embedded) hints its en and em - // dashes, bars thinner than a pixel, down to nothing, so they drew as gaps in interface text; - // unhinted, they draw. + // The Japanese interface face hints its en and em dashes, bars thinner than a pixel, down to + // nothing, so they drew as gaps in interface text; unhinted, they draw. for (name, d) in defs.font_data.iter_mut() { if name.contains("BIZ UDPGothic") { let mut data = (**d).clone(); diff --git a/crates/ui-egui/src/thumbs.rs b/crates/ui-egui/src/thumbs.rs index d6c9c02cc..a923151a9 100644 --- a/crates/ui-egui/src/thumbs.rs +++ b/crates/ui-egui/src/thumbs.rs @@ -69,25 +69,25 @@ fn list(app: &mut SlideApp, ui: &mut Ui) { t.text_dim, ); resp.context_menu(|ui| { - if ui.button("Rename Section…").clicked() { + if ui.button(crate::i18n::tr("Rename Section…")).clicked() { let mut d = crate::dialogs::Dialog::new("renameSection"); d.params = json!({"index": si, "name": sec.name}); app.dialog = Some(d); ui.close(); } - if ui.button("Remove Section").clicked() { + if ui.button(crate::i18n::tr("Remove Section")).clicked() { let _ = app.run("section.remove", json!({"index": si})); ui.close(); } - if ui.button("Remove Section & Slides").clicked() { + if ui.button(crate::i18n::tr("Remove Section & Slides")).clicked() { let _ = app.run("section.remove", json!({"index": si, "slides": true})); ui.close(); } - if ui.button("Move Section Up").clicked() { + if ui.button(crate::i18n::tr("Move Section Up")).clicked() { let _ = app.run("section.move", json!({"index": si, "to": si.saturating_sub(1)})); ui.close(); } - if ui.button("Move Section Down").clicked() { + if ui.button(crate::i18n::tr("Move Section Down")).clicked() { let _ = app.run("section.move", json!({"index": si, "to": si + 1})); ui.close(); } @@ -103,7 +103,7 @@ fn list(app: &mut SlideApp, ui: &mut Ui) { p.text( pos2(row.min.x + 14.0, img.min.y + 2.0), Align2::CENTER_TOP, - format!("{}", i + 1), + (i + 1).to_string(), theme::font(12.0), if selected { t.text } else { t.text_dim }, ); @@ -194,7 +194,7 @@ fn list(app: &mut SlideApp, ui: &mut Ui) { // Click on empty space below: new slide prompt. let (r, resp) = ui.allocate_exact_size(vec2(width, 40.0), Sense::click()); if resp.hovered() { - ui.painter().text(r.center(), Align2::CENTER_CENTER, "+ New Slide", theme::font(12.0), t.text_faint); + ui.painter().text(r.center(), Align2::CENTER_CENTER, crate::i18n::tr("+ New Slide"), theme::font(12.0), t.text_faint); } if resp.clicked() { let _ = app.run("slide.new", json!({})); @@ -210,30 +210,30 @@ pub fn slide_menu(app: &mut SlideApp, ui: &mut Ui, i: usize) { ("Copy", "edit.copy", json!({"scope": "slides"})), ("Paste", "edit.paste", json!({"scope": "slides"})), ] { - if ui.button(l).clicked() { + if ui.button(crate::i18n::tr(l)).clicked() { let _ = app.run(id, p); ui.close(); } } ui.separator(); - if ui.button("New Slide").clicked() { + if ui.button(crate::i18n::tr("New Slide")).clicked() { let _ = app.run("slide.new", json!({})); ui.close(); } - if ui.button("Duplicate Slide").clicked() { + if ui.button(crate::i18n::tr("Duplicate Slide")).clicked() { let _ = app.run("slide.duplicate", json!({})); ui.close(); } - if ui.button("Delete Slide").clicked() { + if ui.button(crate::i18n::tr("Delete Slide")).clicked() { let _ = app.run("slide.delete", json!({})); ui.close(); } ui.separator(); - if ui.button("Add Section").clicked() { + if ui.button(crate::i18n::tr("Add Section")).clicked() { let _ = app.run("section.add", json!({"at": i})); ui.close(); } - ui.menu_button("Layout", |ui| { + ui.menu_button(crate::i18n::tr("Layout"), |ui| { let layouts: Vec<(String, u32)> = app .session .active() @@ -246,11 +246,11 @@ pub fn slide_menu(app: &mut SlideApp, ui: &mut Ui, i: usize) { } } }); - if ui.button("Reset Slide").clicked() { + if ui.button(crate::i18n::tr("Reset Slide")).clicked() { let _ = app.run("slide.reset", json!({})); ui.close(); } - if ui.button("Format Background…").clicked() { + if ui.button(crate::i18n::tr("Format Background…")).clicked() { let _ = app.run("view.pane", json!({"pane": "background"})); ui.close(); } @@ -309,7 +309,7 @@ fn master_list(app: &mut SlideApp, ui: &mut Ui) { ); let name = match li { Some(l) => m.layouts.get(l).map(|x| x.name.clone()).unwrap_or_default(), - None => format!("{} Slide Master", m.name), + None => crate::i18n::format("{} Slide Master", std::slice::from_ref(&m.name)), }; let resp = resp.on_hover_text(name); if resp.clicked() { diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index 6903f1bf6..cbc62a002 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -33,6 +33,7 @@ pub fn big_button(ui: &mut Ui, icon: Icon, label: &str, enabled: bool) -> Respon /// Large button; with `split`, the label row is a separate dropdown target (returns its response). pub fn big_button_ex(ui: &mut Ui, icon: Icon, label: &str, enabled: bool, split: bool, selected: bool) -> (Response, Option) { + let label = crate::i18n::tr(label); let t = Tokens::get(ui.ctx()); let font = theme::font(11.0); let lines: Vec<&str> = wrap_label(label); @@ -68,7 +69,7 @@ pub fn big_button_ex(ui: &mut Ui, icon: Icon, label: &str, enabled: bool, split: let label_w = ui.fonts_mut(|f| f.layout_no_wrap(l.to_string(), font.clone(), col).size().x); let extra = if split && last { 9.0 } else { 0.0 }; let x = rect.center().x - (label_w + extra) / 2.0; - painter.text(pos2(x, y), Align2::LEFT_TOP, l, font.clone(), col); + painter.text(pos2(x, y), Align2::LEFT_TOP, crate::i18n::tr(l), font.clone(), col); if split && last { chevron(&painter, pos2(x + label_w + 5.0, y + 7.0), 3.0, col); } @@ -114,6 +115,7 @@ pub fn small_button(ui: &mut Ui, icon: Icon, label: &str, enabled: bool, selecte } pub fn small_button_ex(ui: &mut Ui, icon: Icon, label: &str, enabled: bool, selected: bool, split: bool) -> (Response, Option) { + let label = crate::i18n::tr(label); let t = Tokens::get(ui.ctx()); let font = theme::font(12.0); let tw = if label.is_empty() { 0.0 } else { ui.fonts_mut(|f| f.layout_no_wrap(label.to_string(), font.clone(), t.text).size().x) + 5.0 }; @@ -144,7 +146,13 @@ pub fn small_button_ex(ui: &mut Ui, icon: Icon, label: &str, enabled: bool, sele } icons::paint(&painter, Rect::from_center_size(pos2(rect.min.x + 12.0, rect.center().y), vec2(17.0, 17.0)), icon, t.text, !enabled); if !label.is_empty() { - painter.text(pos2(rect.min.x + 24.0, rect.center().y), Align2::LEFT_CENTER, label, font, if enabled { t.text } else { t.text_faint }); + painter.text( + pos2(rect.min.x + 24.0, rect.center().y), + Align2::LEFT_CENTER, + crate::i18n::tr(label), + font, + if enabled { t.text } else { t.text_faint }, + ); } if split { chevron(&painter, pos2(rect.max.x - 6.0, rect.center().y), 2.8, t.text_dim); @@ -162,8 +170,8 @@ pub fn icon_toggle(ui: &mut Ui, icon: Icon, tip: &str, enabled: bool, on: bool) } icons::paint(&painter, rect.shrink(3.0), icon, t.text, !enabled); // Named for screen readers (and tests) by its tooltip. - resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, enabled, tip)); - resp.on_hover_text(tip) + resp.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, enabled, crate::i18n::tr(tip))); + resp.on_hover_text(crate::i18n::tr(tip)) } /// Icon with a colour bar under it and a dropdown arrow (Font Color, Highlight, Shape Fill…). @@ -190,7 +198,7 @@ pub fn color_split(ui: &mut Ui, icon: Icon, tip: &str, color: Color32, enabled: if enabled { color } else { t.text_faint }, ); chevron(&painter, pos2(rect.max.x - 5.5, rect.center().y), 2.6, t.text_dim); - (main.on_hover_text(tip), arrow) + (main.on_hover_text(crate::i18n::tr(tip)), arrow) } /// A ribbon group: contents, then a thin vertical separator. @@ -273,7 +281,7 @@ pub fn color_grid(ui: &mut Ui, scheme: &ColorScheme, none_label: Option<&str>) - let t = Tokens::get(ui.ctx()); let mut out = None; ui.set_min_width(220.0); - ui.label(egui::RichText::new("Theme Colors").font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Theme Colors")).font(theme::bold(12.0))); let slots = [ SchemeSlot::Lt1, SchemeSlot::Dk1, @@ -296,7 +304,7 @@ pub fn color_grid(ui: &mut Ui, scheme: &ColorScheme, none_label: Option<&str>) - Stroke::new(if resp.hovered() { 2.0 } else { 1.0 }, if resp.hovered() { t.accent } else { t.border }), egui::StrokeKind::Inside, ); - resp.on_hover_text(tip).clicked() + resp.on_hover_text(crate::i18n::tr(tip)).clicked() }; egui::Grid::new("theme_colors").spacing(vec2(3.0, 1.0)).show(ui, |ui| { for slot in slots { @@ -335,7 +343,7 @@ pub fn color_grid(ui: &mut Ui, scheme: &ColorScheme, none_label: Option<&str>) - } }); ui.add_space(4.0); - ui.label(egui::RichText::new("Standard Colors").font(theme::bold(12.0))); + ui.label(egui::RichText::new(crate::i18n::tr("Standard Colors")).font(theme::bold(12.0))); ui.horizontal(|ui| { ui.spacing_mut().item_spacing.x = 3.0; for (c, name) in deckcraft_color::STANDARD_COLORS { @@ -346,7 +354,7 @@ pub fn color_grid(ui: &mut Ui, scheme: &ColorScheme, none_label: Option<&str>) - }); ui.separator(); if let Some(n) = none_label - && ui.button(n).clicked() + && ui.button(crate::i18n::tr(n)).clicked() { out = Some(None); } @@ -354,7 +362,7 @@ pub fn color_grid(ui: &mut Ui, scheme: &ColorScheme, none_label: Option<&str>) - let id = ui.id().with("hex"); let mut hex: String = ui.data_mut(|d| d.get_temp::(id).unwrap_or_default()); ui.horizontal(|ui| { - ui.label("More Colors… #"); + ui.label(crate::i18n::tr("More Colors… #")); let r = ui.add(egui::TextEdit::singleline(&mut hex).desired_width(70.0).hint_text("RRGGBB")); if r.lost_focus() && ui.input(|i| i.key_pressed(egui::Key::Enter)) @@ -396,7 +404,8 @@ pub fn gallery( if sel { painter.rect_stroke(rect.expand(1.0), CornerRadius::same(4), Stroke::new(1.5, t.accent), egui::StrokeKind::Inside); } - if resp.on_hover_text(tip(i)).clicked() { + let caption = tip(i); + if resp.on_hover_text(crate::i18n::tr(&caption)).clicked() { clicked = Some(i); } }