From 0942c67fa28bb255321f5c471e3013a33d9bf126 Mon Sep 17 00:00:00 2001 From: wiiznokes <78230769+wiiznokes@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:49:23 +0200 Subject: [PATCH] feat: add localization for internal widget --- Cargo.toml | 16 ++++++++-- i18n.toml | 4 +++ i18n/en/libcosmic.ftl | 1 + i18n/fr/libcosmic.ftl | 1 + src/app/mod.rs | 3 ++ src/lib.rs | 4 +++ src/localize.rs | 46 +++++++++++++++++++++++++++++ src/widget/context_drawer/widget.rs | 23 +++++++++------ 8 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 i18n.toml create mode 100644 i18n/en/libcosmic.ftl create mode 100644 i18n/fr/libcosmic.ftl create mode 100644 src/localize.rs diff --git a/Cargo.toml b/Cargo.toml index 15914327..167c8761 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ rust-version = "1.71" name = "cosmic" [features] -default = ["clipboard"] +default = ["clipboard", "localization"] # Accessibility support a11y = ["iced/a11y", "iced_accessibility"] # Builds support for animated images @@ -70,6 +70,7 @@ winit_tokio = ["winit", "tokio"] winit_wgpu = ["winit", "wgpu"] # Enables XDG portal integrations xdg-portal = ["ashpd"] +localization = ["i18n-embed", "rust-embed", "i18n-embed-fl"] [dependencies] apply = "0.3.0" @@ -84,11 +85,14 @@ derive_setters = "0.1.5" fraction = "0.15.3" image = { version = "0.25.1", optional = true } lazy_static = "1.4.0" -libc = { version = "0.2.155", optional = true } +libc = { version = "0.2.155", optional = true } mime = { version = "0.3.17", optional = true } palette = "0.7.3" rfd = { version = "0.14.0", optional = true } -rustix = { version = "0.38.34", features = ["pipe", "process"], optional = true } +rustix = { version = "0.38.34", features = [ + "pipe", + "process", +], optional = true } serde = { version = "1.0.180", features = ["derive"] } slotmap = "1.0.6" smol = { version = "2.0.0", optional = true } @@ -99,6 +103,12 @@ tracing = "0.1" unicode-segmentation = "1.6" url = "2.4.0" zbus = { version = "4.2.1", default-features = false, optional = true } +i18n-embed = { version = "0.14", features = [ + "fluent-system", + "desktop-requester", +], optional = true } +rust-embed = { version = "8.0", optional = true } +i18n-embed-fl = { version = "0.8", optional = true } [target.'cfg(unix)'.dependencies] freedesktop-icons = "0.2.5" diff --git a/i18n.toml b/i18n.toml new file mode 100644 index 00000000..ae96677d --- /dev/null +++ b/i18n.toml @@ -0,0 +1,4 @@ +fallback_language = "en" + +[fluent] +assets_dir = "./i18n" \ No newline at end of file diff --git a/i18n/en/libcosmic.ftl b/i18n/en/libcosmic.ftl new file mode 100644 index 00000000..95d90df4 --- /dev/null +++ b/i18n/en/libcosmic.ftl @@ -0,0 +1 @@ +close = Close \ No newline at end of file diff --git a/i18n/fr/libcosmic.ftl b/i18n/fr/libcosmic.ftl new file mode 100644 index 00000000..7debc1eb --- /dev/null +++ b/i18n/fr/libcosmic.ftl @@ -0,0 +1 @@ +close = Fermer \ No newline at end of file diff --git a/src/app/mod.rs b/src/app/mod.rs index bcacd3b3..0da00b37 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -161,6 +161,9 @@ pub(crate) fn iced_settings( pub fn run(settings: Settings, flags: App::Flags) -> iced::Result { let settings = iced_settings::(settings, flags); + #[cfg(feature = "localization")] + crate::localize::localize(); + cosmic::Cosmic::::run(settings) } diff --git a/src/lib.rs b/src/lib.rs index 60e3cf19..c92d4e6e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,10 @@ pub use cctk; pub mod theme; +#[cfg(feature = "localization")] +#[macro_use] +pub mod localize; + #[doc(inline)] pub use theme::{style, Theme}; diff --git a/src/localize.rs b/src/localize.rs new file mode 100644 index 00000000..eff8a72b --- /dev/null +++ b/src/localize.rs @@ -0,0 +1,46 @@ +use i18n_embed::{ + fluent::{fluent_language_loader, FluentLanguageLoader}, + DefaultLocalizer, LanguageLoader, Localizer, +}; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "./i18n/"] +struct Localizations; + +lazy_static::lazy_static! { + pub static ref LANGUAGE_LOADER: FluentLanguageLoader = { + let loader: FluentLanguageLoader = fluent_language_loader!(); + + loader + .load_fallback_language(&Localizations) + .expect("Error while loading fallback language"); + + loader + }; +} + +#[macro_export] +macro_rules! fl { + ($message_id:literal) => {{ + i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id) + }}; + + ($message_id:literal, $($args:expr),*) => {{ + i18n_embed_fl::fl!($crate::localize::LANGUAGE_LOADER, $message_id, $($args), *) + }}; +} + +// Get the `Localizer` to be used for localizing this library. +fn localizer() -> Box { + Box::from(DefaultLocalizer::new(&*LANGUAGE_LOADER, &Localizations)) +} + +pub fn localize() { + let localizer = localizer(); + let requested_languages = i18n_embed::DesktopLanguageRequester::requested_languages(); + + if let Err(error) = localizer.select(&requested_languages) { + eprintln!("Error while loading language {}", error); + } +} diff --git a/src/widget/context_drawer/widget.rs b/src/widget/context_drawer/widget.rs index 7aba4b69..4fa4fc2e 100644 --- a/src/widget/context_drawer/widget.rs +++ b/src/widget/context_drawer/widget.rs @@ -54,15 +54,20 @@ impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> { .vertical_alignment(alignment::Vertical::Center), ) .push( - button::text("Close") - .trailing_icon(icon::from_name("go-next-symbolic")) - .on_press(on_close) - .style(crate::theme::Button::Link) - .apply(container) - .width(Length::FillPortion(1)) - .height(Length::Fill) - .align_x(alignment::Horizontal::Right) - .center_y(), + button::text( + #[cfg(feature = "localization")] + fl!("close"), + #[cfg(not(feature = "localization"))] + "Close", + ) + .trailing_icon(icon::from_name("go-next-symbolic")) + .on_press(on_close) + .style(crate::theme::Button::Link) + .apply(container) + .width(Length::FillPortion(1)) + .height(Length::Fill) + .align_x(alignment::Horizontal::Right) + .center_y(), ) // XXX must be done after pushing elements or it may be overwritten by size hints from contents .height(Length::Fixed(80.0))