diff --git a/Cargo.lock b/Cargo.lock index 747bf455..20764a20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1062,6 +1062,27 @@ dependencies = [ "smol_str", ] +[[package]] +name = "bevy_fluent" +version = "0.14.0" +source = "git+https://github.com/ThierryBerger/bevy_fluent.git?branch=asset_path_resolve#84fbf955b4028bfedc9b4778f957c24dad550ae6" +dependencies = [ + "bevy", + "fluent", + "fluent-langneg", + "fluent_content", + "futures-lite", + "indexmap", + "intl-memoizer", + "ron", + "serde", + "serde_yaml", + "thiserror 1.0.69", + "tracing", + "unic-langid", + "uuid", +] + [[package]] name = "bevy_gilrs" version = "0.18.1" @@ -2115,7 +2136,7 @@ dependencies = [ "cosmic-text 0.16.0", "serde", "smallvec", - "sys-locale", + "sys-locale 0.3.2", "thiserror 2.0.18", "tracing", "wgpu-types 27.0.1", @@ -2269,7 +2290,7 @@ dependencies = [ "cosmic-text 0.16.0", "cosmic_undo_2", "once_cell", - "sys-locale", + "sys-locale 0.3.2", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -2941,10 +2962,10 @@ dependencies = [ "rangemap", "rustc-hash 1.1.0", "rustybuzz", - "self_cell", + "self_cell 1.2.2", "smol_str", "swash", - "sys-locale", + "sys-locale 0.3.2", "ttf-parser 0.21.1", "unicode-bidi", "unicode-linebreak", @@ -2965,11 +2986,11 @@ dependencies = [ "log", "rangemap", "rustc-hash 1.1.0", - "self_cell", + "self_cell 1.2.2", "skrifa 0.39.0", "smol_str", "swash", - "sys-locale", + "sys-locale 0.3.2", "unicode-bidi", "unicode-linebreak", "unicode-script", @@ -3653,6 +3674,64 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fluent" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" +dependencies = [ + "fluent-bundle", + "unic-langid", +] + +[[package]] +name = "fluent-bundle" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash 1.1.0", + "self_cell 0.10.3", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eebbe59450baee8282d71676f3bfed5689aeab00b27545e83e5f14b1195e8b0" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" +dependencies = [ + "thiserror 1.0.69", +] + +[[package]] +name = "fluent_content" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38dc4630a89c85160410fd062826b505218a0ca68121f92d9fbd9a0e71c1a148" +dependencies = [ + "fluent", + "fluent-langneg", + "intl-memoizer", + "thiserror 1.0.69", + "tracing", + "unic-langid", +] + [[package]] name = "fnv" version = "1.0.7" @@ -4494,6 +4573,25 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9c13ae9d91148fcb4aab6654c4c2a7d02a15395ea9e23f65170f175f8b269ce" +[[package]] +name = "intl-memoizer" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +dependencies = [ + "unic-langid", +] + [[package]] name = "inventory" version = "0.3.24" @@ -4577,6 +4675,7 @@ dependencies = [ "jackdaw_geometry", "jackdaw_jsn", "jackdaw_loader", + "jackdaw_localization", "jackdaw_node_graph", "jackdaw_panels", "jackdaw_remote", @@ -4603,6 +4702,7 @@ dependencies = [ "jackdaw_commands", "jackdaw_feathers", "jackdaw_jsn", + "jackdaw_localization", "jackdaw_node_graph", "lucide-icons", "serde", @@ -4700,6 +4800,7 @@ dependencies = [ "bevy_ui_text_input", "jackdaw_fuzzy", "jackdaw_jsn", + "jackdaw_localization", "jackdaw_widgets", "lucide-icons", ] @@ -4745,6 +4846,17 @@ dependencies = [ "libloading", ] +[[package]] +name = "jackdaw_localization" +version = "0.4.1" +dependencies = [ + "bevy", + "bevy_fluent", + "fluent_content", + "sys-locale 0.2.4", + "unic-langid", +] + [[package]] name = "jackdaw_node_graph" version = "0.4.1" @@ -4755,6 +4867,7 @@ dependencies = [ "jackdaw_commands", "jackdaw_feathers", "jackdaw_jsn", + "jackdaw_localization", "jackdaw_widgets", "serde", ] @@ -6214,6 +6327,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.106" @@ -6741,6 +6860,12 @@ dependencies = [ "twox-hash", ] +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + [[package]] name = "safe_arch" version = "0.7.4" @@ -6784,6 +6909,15 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "self_cell" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.2.2", +] + [[package]] name = "self_cell" version = "1.2.2" @@ -6871,6 +7005,19 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "sha1" version = "0.10.6" @@ -6882,6 +7029,12 @@ dependencies = [ "digest", ] +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + [[package]] name = "sharded-slab" version = "0.1.7" @@ -7184,6 +7337,19 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "sys-locale" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" +dependencies = [ + "js-sys", + "libc", + "wasm-bindgen", + "web-sys", + "windows-sys 0.45.0", +] + [[package]] name = "sys-locale" version = "0.3.2" @@ -7365,6 +7531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", + "serde_core", "zerovec", ] @@ -7624,6 +7791,15 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" +[[package]] +name = "type-map" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90" +dependencies = [ + "rustc-hash 2.1.2", +] + [[package]] name = "typeid" version = "1.0.3" @@ -7653,6 +7829,50 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "unic-langid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" +dependencies = [ + "unic-langid-impl", + "unic-langid-macros", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" +dependencies = [ + "serde", + "tinystr", +] + +[[package]] +name = "unic-langid-macros" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25" +dependencies = [ + "proc-macro-hack", + "tinystr", + "unic-langid-impl", + "unic-langid-macros-impl", +] + +[[package]] +name = "unic-langid-macros-impl" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1249a628de3ad34b821ecb1001355bca3940bcb2f88558f1a8bd82e977f75b5" +dependencies = [ + "proc-macro-hack", + "quote", + "syn 2.0.117", + "unic-langid-impl", +] + [[package]] name = "unicode-bidi" version = "0.3.18" @@ -7713,6 +7933,12 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" @@ -7781,6 +8007,7 @@ dependencies = [ "getrandom 0.4.2", "js-sys", "serde_core", + "sha1_smol", "wasm-bindgen", ] @@ -9261,6 +9488,7 @@ version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ + "serde", "yoke", "zerofrom", "zerovec-derive", diff --git a/Cargo.toml b/Cargo.toml index 6b82d917..b9ca207b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,6 +132,7 @@ ctrlc = "3" bevy_simple_subsecond_system = { version = "0.2", optional = true } winit.workspace = true image.workspace = true +jackdaw_localization = { version = "0.4.1", path = "crates/jackdaw_localization" } [workspace.dependencies] bevy = { version = "0.18", features = [ @@ -156,6 +157,7 @@ jackdaw_remote = { version = "0.4.1", path = "crates/jackdaw_remote" } jackdaw_node_graph = { version = "0.4.1", path = "crates/jackdaw_node_graph" } jackdaw_animation = { version = "0.4.1", path = "crates/jackdaw_animation" } jackdaw_fuzzy = { version = "0.4.1", path = "crates/jackdaw_fuzzy" } +jackdaw_localization = { version = "0.4.1", path = "crates/jackdaw_localization" } noise = "0.9" rand = "0.9" serde = "1" @@ -195,6 +197,10 @@ tracing = "0.1" tracing-subscriber = "0.3" winit = "0.30.13" image = { version = "0.25.10", default-features = false, features = ["png"] } +fluent_content = "0.0.5" +bevy_fluent = { git = "https://github.com/ThierryBerger/bevy_fluent.git", branch = "asset_path_resolve" } +unic-langid = { version = "0.9", features = ["macros"] } +sys-locale = "0.2" # Idiomatic Bevy code often triggers these lints, and the CI workflow treats them as errors. [workspace.lints.clippy] diff --git a/crates/jackdaw_animation/Cargo.toml b/crates/jackdaw_animation/Cargo.toml index 68f27414..a28a0214 100644 --- a/crates/jackdaw_animation/Cargo.toml +++ b/crates/jackdaw_animation/Cargo.toml @@ -13,6 +13,7 @@ jackdaw_feathers.workspace = true jackdaw_commands.workspace = true jackdaw_node_graph.workspace = true jackdaw_jsn.workspace = true +jackdaw_localization.workspace = true lucide-icons = { workspace = true } serde = { workspace = true, features = ["derive"] } diff --git a/crates/jackdaw_animation/src/timeline.rs b/crates/jackdaw_animation/src/timeline.rs index 3c6cca9c..ad16c80a 100644 --- a/crates/jackdaw_animation/src/timeline.rs +++ b/crates/jackdaw_animation/src/timeline.rs @@ -18,6 +18,7 @@ use jackdaw_feathers::button::{ }; use jackdaw_feathers::icons::IconFont; use jackdaw_feathers::tokens; +use jackdaw_localization::LocalizedText; use lucide_icons::Icon; use crate::blend_graph::AnimationBlendGraph; @@ -358,7 +359,7 @@ fn spawn_placeholder(commands: &mut Commands, parent: Entity) { .id(); commands.spawn(( - Text::new("No animation clip on selection. Pick a named entity and create one."), + LocalizedText::new("no-animation-clip-on-selection"), TextColor(tokens::TEXT_MUTED_COLOR.into()), TextFont { font_size: tokens::FONT_SM, diff --git a/crates/jackdaw_feathers/Cargo.toml b/crates/jackdaw_feathers/Cargo.toml index 28c8a4cb..cc55afcc 100644 --- a/crates/jackdaw_feathers/Cargo.toml +++ b/crates/jackdaw_feathers/Cargo.toml @@ -16,6 +16,7 @@ jackdaw_fuzzy.workspace = true jackdaw_jsn.workspace = true jackdaw_widgets.workspace = true lucide-icons.workspace = true +jackdaw_localization.workspace = true [lints] workspace = true diff --git a/crates/jackdaw_feathers/src/status_bar.rs b/crates/jackdaw_feathers/src/status_bar.rs index 5be1037e..e49a0750 100644 --- a/crates/jackdaw_feathers/src/status_bar.rs +++ b/crates/jackdaw_feathers/src/status_bar.rs @@ -1,4 +1,5 @@ use bevy::{feathers::theme::ThemedText, prelude::*}; +use jackdaw_localization::LocalizedText; use crate::tokens; @@ -36,7 +37,7 @@ pub fn status_bar() -> impl Bundle { children![ ( StatusBarLeft, - Text::new("Ready"), + LocalizedText::new("ready"), TextFont { font_size: tokens::FONT_SM, ..Default::default() diff --git a/crates/jackdaw_localization/Cargo.toml b/crates/jackdaw_localization/Cargo.toml new file mode 100644 index 00000000..5f658062 --- /dev/null +++ b/crates/jackdaw_localization/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "jackdaw_localization" +version = "0.4.1" +edition = "2024" +description = "Internal crate for Jackdaw localization" +license = "MIT OR Apache-2.0" +repository = "https://github.com/jbuehler23/jackdaw" + +[features] + +[dependencies] +bevy.workspace = true +fluent_content.workspace = true +bevy_fluent.workspace = true +unic-langid.workspace = true +sys-locale.workspace = true + +[lints] +workspace = true diff --git a/crates/jackdaw_localization/src/lib.rs b/crates/jackdaw_localization/src/lib.rs new file mode 100644 index 00000000..47ae5ea4 --- /dev/null +++ b/crates/jackdaw_localization/src/lib.rs @@ -0,0 +1,129 @@ +//! Localization for jackdaw Editor. + +use bevy::asset::{LoadedFolder, embedded_asset}; +use bevy::prelude::*; +use bevy_fluent::prelude::*; +use fluent_content::Content; +use unic_langid::langid; + +macro_rules! supported_languages { + ($($lang:literal),+ $(,)?) => { + pub const SUPPORTED_LANGUAGES: &[&str] = &[$($lang),+]; + + /// Macro-generated boilerplate to register our locale assets. + fn embed_locale_assets(app: &mut App) { + $( + embedded_asset!(app, concat!("locales/", $lang, "/main.ftl")); + embedded_asset!(app, concat!("locales/", $lang, "/main.ftl.yml")); + )+ + } + }; +} + +supported_languages!("en-US"); + +pub struct LocalizationPlugin; + +impl Plugin for LocalizationPlugin { + fn build(&self, app: &mut App) { + embed_locale_assets(app); + + // TODO: Offer a way for user to customize language + persist to disk. + let locale = sys_locale::get_locale().unwrap_or_else(|| String::from("en-US")); + let parsed_locale = locale.parse().unwrap_or(langid!("en-US")); + app.insert_resource(SelectedLocale { locale }); + app.insert_resource(Locale::new(parsed_locale).with_default(langid!("en-US"))); + + app.add_plugins(FluentPlugin); + app.init_resource::(); + app.init_resource::(); + + app.add_systems(PreStartup, load_editor_locales); + app.add_systems( + Update, + ( + update_used_locale.run_if(resource_changed::), + rebuild_localization.run_if(localization_needs_rebuild), + update_all_text.run_if(resource_changed::), + update_changed_text, + ) + .chain(), + ); + } +} + +#[derive(Resource)] +pub struct SelectedLocale { + pub locale: String, +} + +#[derive(Resource, Default)] +pub struct LocaleFolder(pub Option>); + +#[derive(Component, Default, Reflect)] +#[require(Text)] +pub struct LocalizedText(pub String); + +impl LocalizedText { + pub fn new(request: impl Into) -> Self { + Self(request.into()) + } +} + +fn load_editor_locales(asset_server: Res, mut folder: ResMut) { + folder.0 = Some(asset_server.load_folder("embedded://jackdaw_localization/locales")); +} + +/// Parse [`SelectedLocale`] and store it into [`Locale`]. +pub fn update_used_locale(selected: Res, mut locale: ResMut) { + locale.requested = selected.locale.parse().unwrap_or(langid!("en-US")); +} + +fn localization_needs_rebuild( + locale: Res, + mut folder_events: MessageReader>, + mut bundle_events: MessageReader>, +) -> bool { + let folder_ready = folder_events + .read() + .any(|e| matches!(e, AssetEvent::LoadedWithDependencies { .. })); + let bundle_ready = bundle_events.read().any(|e| { + matches!( + e, + AssetEvent::LoadedWithDependencies { .. } | AssetEvent::Modified { .. } + ) + }); + locale.is_changed() || folder_ready || bundle_ready +} + +fn rebuild_localization( + builder: LocalizationBuilder, + folder: Res, + mut localization: ResMut, +) { + let Some(handle) = folder.0.as_ref() else { + return; + }; + *localization = builder.build(handle); +} + +/// Re-resolve every [`LocalizedText`] after the active locale changes. +fn update_all_text(localization: Res, mut q: Query<(&LocalizedText, &mut Text)>) { + for (loc, mut text) in q.iter_mut() { + text.0 = localization + .content(&loc.0) + .unwrap_or_else(|| loc.0.clone()); + } +} + +/// Resolve newly inserted or mutated [`LocalizedText`] entries. +fn update_changed_text( + localization: Res, + mut q: Query<(&LocalizedText, &mut Text), Changed>, +) { + for (loc, mut text) in q.iter_mut() { + text.0 = localization + .content(&loc.0) + .unwrap_or_else(|| loc.0.clone()); + } +} diff --git a/crates/jackdaw_localization/src/locales/en-US/main.ftl b/crates/jackdaw_localization/src/locales/en-US/main.ftl new file mode 100644 index 00000000..034e3971 --- /dev/null +++ b/crates/jackdaw_localization/src/locales/en-US/main.ftl @@ -0,0 +1,12 @@ +cancel = Cancel +submit = Submit +add-node = Add Node +add-entity = Add Entity +add-component = Add Component +ready = Ready +no-animation-clip-on-selection = No animation clip on selection. Pick a named entity and create one. +new-workspace = New Workspace +preparing-build = Preparing build... +source-checkout = Source checkout +read-only = (read-only) +material-not-loaded = (material not loaded) diff --git a/crates/jackdaw_localization/src/locales/en-US/main.ftl.yml b/crates/jackdaw_localization/src/locales/en-US/main.ftl.yml new file mode 100644 index 00000000..bb3f0028 --- /dev/null +++ b/crates/jackdaw_localization/src/locales/en-US/main.ftl.yml @@ -0,0 +1,4 @@ +# Locale files may be in YAML as in this example, or in RON +locale: en-US +resources: + - embedded://jackdaw_localization/locales/en-US/main.ftl diff --git a/crates/jackdaw_node_graph/Cargo.toml b/crates/jackdaw_node_graph/Cargo.toml index 478f6a27..9c8b8148 100644 --- a/crates/jackdaw_node_graph/Cargo.toml +++ b/crates/jackdaw_node_graph/Cargo.toml @@ -15,6 +15,7 @@ jackdaw_widgets.workspace = true jackdaw_feathers.workspace = true jackdaw_commands.workspace = true jackdaw_jsn.workspace = true +jackdaw_localization.workspace = true serde = { workspace = true, features = ["derive"] } [lints] diff --git a/crates/jackdaw_node_graph/src/add_node_popover.rs b/crates/jackdaw_node_graph/src/add_node_popover.rs index fc5fc2a1..619be098 100644 --- a/crates/jackdaw_node_graph/src/add_node_popover.rs +++ b/crates/jackdaw_node_graph/src/add_node_popover.rs @@ -17,6 +17,7 @@ use bevy::picking::pointer::PointerButton; use bevy::prelude::*; use bevy::ui::UiGlobalTransform; use jackdaw_commands::CommandHistory; +use jackdaw_localization::LocalizedText; use crate::canvas::{GraphCanvasViewport, GraphCanvasWorld}; use crate::commands::AddGraphNodeCmd; @@ -150,7 +151,7 @@ pub fn spawn_popover( BackgroundColor(HEADER_BG), ChildOf(popover_entity), children![( - Text::new("Add Node"), + LocalizedText::new("add-node"), TextFont { font_size: 12.0, ..default() diff --git a/src/inspector/component_display.rs b/src/inspector/component_display.rs index 2e5d52a9..b170faa9 100644 --- a/src/inspector/component_display.rs +++ b/src/inspector/component_display.rs @@ -20,6 +20,7 @@ use jackdaw_feathers::{ icons::{EditorFont, Icon, IconFont}, tokens, }; +use jackdaw_localization::LocalizedText; use jackdaw_widgets::collapsible::{ CollapsibleBody, CollapsibleHeader, CollapsibleSection, ToggleCollapsible, }; @@ -445,7 +446,7 @@ pub(crate) fn build_inspector_displays( // Fallback: no reflection data commands.spawn(( - Text::new("(read-only)"), + LocalizedText::new("read-only"), TextFont { font_size: tokens::FONT_SM, ..Default::default() diff --git a/src/inspector/material_display.rs b/src/inspector/material_display.rs index acd31dab..861d2af3 100644 --- a/src/inspector/material_display.rs +++ b/src/inspector/material_display.rs @@ -3,6 +3,7 @@ use jackdaw_feathers::{ text_edit::{self, TextEditCommitEvent, TextEditProps}, tokens, }; +use jackdaw_localization::LocalizedText; /// Marker for material field UI entities #[derive(Component)] @@ -46,7 +47,7 @@ fn spawn_material_fields(world: &mut World, body_entity: Entity, source_entity: mat_data else { world.spawn(( - Text::new("(material not loaded)"), + LocalizedText::new("material-not-loaded"), TextFont { font_size: tokens::FONT_SM, ..Default::default() diff --git a/src/layout.rs b/src/layout.rs index 6f3f8833..3b9d266d 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -8,6 +8,7 @@ use jackdaw_feathers::{ tokens, tree_view::tree_container_drop_observers, }; +use jackdaw_localization::LocalizedText; use crate::{ EditorEntity, @@ -637,7 +638,7 @@ pub fn hierarchy_content(icon_font: Handle) -> impl Bundle { TextColor(tokens::TEXT_PRIMARY), ), ( - Text::new("Add Entity"), + LocalizedText::new("add-entity"), TextFont { font_size: tokens::TEXT_SIZE, weight: FontWeight::MEDIUM, @@ -663,7 +664,7 @@ pub fn hierarchy_content(icon_font: Handle) -> impl Bundle { ), ( crate::status_bar::SceneStatsText, - Text::new(""), + Text::default(), TextFont { font_size: tokens::FONT_SM, ..Default::default() @@ -850,7 +851,7 @@ fn editor_status_bar() -> impl Bundle { children![ ( status_bar::StatusBarLeft, - Text::new("Ready"), + LocalizedText::new("ready"), TextFont { font_size: tokens::FONT_SM, ..Default::default() @@ -859,7 +860,7 @@ fn editor_status_bar() -> impl Bundle { ), ( status_bar::StatusBarCenter, - Text::new(""), + Text::default(), TextFont { font_size: tokens::FONT_SM, ..Default::default() @@ -877,7 +878,7 @@ fn editor_status_bar() -> impl Bundle { children![ ( status_bar::StatusBarRight, - Text::new(""), + Text::default(), TextFont { font_size: tokens::FONT_SM, ..Default::default() @@ -959,7 +960,7 @@ pub fn inspector_components_content(icon_font: Handle) -> impl Bundle { TextColor(tokens::TEXT_PRIMARY), ), ( - Text::new("Add Component"), + LocalizedText::new("add-component"), TextFont { font_size: tokens::TEXT_SIZE, weight: FontWeight::MEDIUM, diff --git a/src/lib.rs b/src/lib.rs index c5c926cd..799b1c69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ pub mod keybinds; use std::{collections::BTreeMap, marker::PhantomData}; pub use inspector::{EditorCategory, EditorDescription, EditorHidden, SkipSerialization}; + pub mod core_extension; pub mod dock_ops; pub mod document_ops; @@ -257,23 +258,28 @@ impl Plugin for EditorCorePlugin { EditorFeathersPlugin, )); app.add_plugins(( - jackdaw_jsn::JsnPlugin { - runtime_mesh_rebuild: false, - }, - project_select::ProjectSelectPlugin, - inspector::InspectorPlugin, - hierarchy::HierarchyPlugin, - viewport::ViewportPlugin, - gizmos::TransformGizmosPlugin, - commands::CommandHistoryPlugin, - selection::SelectionPlugin, - entity_ops::EntityOpsPlugin, - scene_io::SceneIoPlugin, - scenes::ScenesPlugin, - workspace_dropdown::WorkspaceDropdownPlugin, - asset_browser::AssetBrowserPlugin, - viewport_select::ViewportSelectPlugin, - snapping::SnappingPlugin, + ( + jackdaw_jsn::JsnPlugin { + runtime_mesh_rebuild: false, + }, + project_select::ProjectSelectPlugin, + inspector::InspectorPlugin, + hierarchy::HierarchyPlugin, + viewport::ViewportPlugin, + gizmos::TransformGizmosPlugin, + commands::CommandHistoryPlugin, + ), + ( + selection::SelectionPlugin, + entity_ops::EntityOpsPlugin, + scene_io::SceneIoPlugin, + scenes::ScenesPlugin, + workspace_dropdown::WorkspaceDropdownPlugin, + asset_browser::AssetBrowserPlugin, + viewport_select::ViewportSelectPlugin, + snapping::SnappingPlugin, + jackdaw_localization::LocalizationPlugin, + ), )) .add_plugins(keybinds::KeybindsPlugin) .add_plugins(keybind_settings::KeybindSettingsPlugin) diff --git a/src/material_browser.rs b/src/material_browser.rs index 6cc537ea..fc74114d 100644 --- a/src/material_browser.rs +++ b/src/material_browser.rs @@ -1536,7 +1536,7 @@ pub fn material_browser_panel(icon_font: Handle) -> impl Bundle { margin: UiRect::vertical(Val::Px(tokens::SPACING_MD)), ..Default::default() }, - Text::new(""), + Text::default(), TextFont { font_size: tokens::FONT_SM, ..Default::default() diff --git a/src/measure_tool.rs b/src/measure_tool.rs index 0d111c17..446dcf68 100644 --- a/src/measure_tool.rs +++ b/src/measure_tool.rs @@ -270,7 +270,7 @@ fn ensure_measure_label( MeasureLabel, crate::EditorEntity, crate::NonSerializable, - Text::new(""), + Text::default(), TextFont { font_size: tokens::TEXT_SIZE, ..default() diff --git a/src/project_select.rs b/src/project_select.rs index 979542d3..ba147284 100644 --- a/src/project_select.rs +++ b/src/project_select.rs @@ -11,6 +11,7 @@ use jackdaw_feathers::{ text_edit::{TextEditProps, TextEditValue, text_edit}, tokens, }; +use jackdaw_localization::LocalizedText; use rfd::{AsyncFileDialog, FileHandle}; use crate::{ @@ -472,7 +473,7 @@ fn spawn_project_selector( )); sidebar.spawn(( - Text::new("Source checkout"), + LocalizedText::new("source-checkout"), TextFont { font: font.clone(), font_size: tokens::FONT_SM, @@ -1473,7 +1474,7 @@ pub fn open_project_progress_modal(world: &mut World, project_name: &str) { world.spawn(( NewProjectProgressCrateLabel, - Text::new("Preparing build...".to_string()), + LocalizedText::new("preparing-build"), TextFont { font: editor_font.clone(), font_size: tokens::FONT_SM, diff --git a/src/workspace_dropdown.rs b/src/workspace_dropdown.rs index a18e26e8..09be0536 100644 --- a/src/workspace_dropdown.rs +++ b/src/workspace_dropdown.rs @@ -19,6 +19,7 @@ use bevy::prelude::*; use bevy::ui::ui_transform::UiGlobalTransform; use jackdaw_feathers::icons::{EditorFont, Icon, IconFont}; use jackdaw_feathers::tokens; +use jackdaw_localization::LocalizedText; use jackdaw_panels::workspace::{WorkspaceChanged, WorkspaceRegistry, WorkspaceTab}; use jackdaw_panels::workspace_tabs::{AddWorkspaceButton, WorkspaceTabLabel}; @@ -84,7 +85,7 @@ pub fn workspace_dropdown_trigger( children![ ( WorkspaceDropdownTriggerLabel, - Text::new(""), + Text::default(), TextFont { font: editor_font, font_size: tokens::FONT_SM, @@ -377,7 +378,7 @@ fn spawn_popover_add_row( label_font.font = handle; } world.spawn(( - Text::new("New Workspace".to_string()), + LocalizedText::new("new-workspace"), label_font, TextColor(tokens::DOC_TAB_INACTIVE_LABEL), Pickable::IGNORE,