diff --git a/docs/book/src/usage/05_td_macro.md b/docs/book/src/usage/05_td_macro.md index 13f9f38e..cc4745ba 100644 --- a/docs/book/src/usage/05_td_macro.md +++ b/docs/book/src/usage/05_td_macro.md @@ -18,11 +18,11 @@ pub fn Foo() -> impl IntoView { view! { - {td!(locale, set_locale)} + each = Locale::get_all + key = |locale| **locale + children = move |locale| view! { + } /> diff --git a/docs/book/src/usage/06_td_string_macro.md b/docs/book/src/usage/06_td_string_macro.md index f1ebfb8c..9d5fd67e 100644 --- a/docs/book/src/usage/06_td_string_macro.md +++ b/docs/book/src/usage/06_td_string_macro.md @@ -1,8 +1,9 @@ # The `td_string!` Macro -The `td_string!` macro is to use interpolations outside the context of rendering views, it let you give a different kind of values and return a `Cow<'static, str>`. +The `td_string!` macro is to use interpolations outside the context of rendering views, it let you give a different kind of values and return a `&'static str` or a `String` depending on the value of the key. +If the value is a plain string or a boolean it returns a `&'static str`, if it's an interpolations or a number it returns a `String`. -This requires the `interpolate_display` feature to be enabled. +This requires the `interpolate_display` feature to be enabled to work with interpolations. It enable you to do this: @@ -87,3 +88,7 @@ assert_eq!(format!("before {t} after"), "before You clicked 10 times after"); let t_str = t.to_string(); // can call `to_string` as the value impl `Display` assert_eq!(t_str, "You clicked 10 times"); ``` + +# `t_string` and `t_display` + +They also exist, `td_string` was used here for easier demonstration. Remember that `t_string` access a signal reactively. diff --git a/examples/ssr/axum_island/Cargo.toml b/examples/ssr/axum_island/Cargo.toml index 58fdc51c..b4ba1f1d 100644 --- a/examples/ssr/axum_island/Cargo.toml +++ b/examples/ssr/axum_island/Cargo.toml @@ -25,7 +25,7 @@ wasm-bindgen = { version = "0.2", optional = true } simple_logger = "4" tokio = { version = "1.35", features = ["rt-multi-thread"], optional = true } log = "0.4" -tower = { version = "0.4.13", optional = true } +tower = { version = "0.4.13", optional = true, features = ["util"] } tower-http = { version = "0.5", features = ["fs"], optional = true } [features] diff --git a/examples/ssr/hello_world_axum/Cargo.toml b/examples/ssr/hello_world_axum/Cargo.toml index 39b50542..e93cfc61 100644 --- a/examples/ssr/hello_world_axum/Cargo.toml +++ b/examples/ssr/hello_world_axum/Cargo.toml @@ -22,7 +22,7 @@ wasm-bindgen = { version = "0.2", optional = true } simple_logger = "4" tokio = { version = "1.35", features = ["rt-multi-thread"], optional = true } log = "0.4" -tower = { version = "0.4.13", optional = true } +tower = { version = "0.4.13", optional = true, features = ["util"] } tower-http = { version = "0.5", features = ["fs"], optional = true } [features] diff --git a/examples/ssr/routing_ssr/Cargo.toml b/examples/ssr/routing_ssr/Cargo.toml index dc9b0cca..e495911d 100644 --- a/examples/ssr/routing_ssr/Cargo.toml +++ b/examples/ssr/routing_ssr/Cargo.toml @@ -22,7 +22,7 @@ wasm-bindgen = { version = "0.2", optional = true } simple_logger = "4" tokio = { version = "1.35", features = ["rt-multi-thread"], optional = true } log = "0.4" -tower = { version = "0.4.13", optional = true } +tower = { version = "0.4.13", optional = true, features = ["util"] } tower-http = { version = "0.5", features = ["fs"], optional = true } leptos_router = "0.6" diff --git a/leptos_i18n/src/macro_helpers/mod.rs b/leptos_i18n/src/macro_helpers/mod.rs index 74214d25..c945c59f 100644 --- a/leptos_i18n/src/macro_helpers/mod.rs +++ b/leptos_i18n/src/macro_helpers/mod.rs @@ -1,5 +1,5 @@ use core::fmt; -use std::{borrow::Cow, marker::PhantomData}; +use std::{fmt::Display, marker::PhantomData}; pub mod formatting; mod interpol_args; @@ -12,12 +12,39 @@ pub use scope::*; use crate::Locale; #[doc(hidden)] -pub struct DisplayBuilder(Cow<'static, str>); +pub trait Lit { + type AsSTring: Display; -impl DisplayBuilder { + fn into_string(self) -> Self::AsSTring; +} + +#[doc(hidden)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct DisplayBuilder(T); + +impl DisplayBuilder { #[inline] - pub fn build_display(self) -> Cow<'static, str> { - self.0 + pub fn build_display(self) -> T::AsSTring { + self.0.into_string() + } + + #[inline] + pub fn build_string(self) -> T::AsSTring { + self.0.into_string() + } +} + +#[doc(hidden)] +#[diagnostic::on_unimplemented( + message = "Interpolated values can't be used inside t_string/t_display without the \"interpolate_display\" feature enabled." +)] +pub trait InterpolationStringBuilder +where + Self: Sized, +{ + fn check(self) -> Self { + self } } @@ -40,7 +67,9 @@ pub trait BuildLit: Sized { self } - fn display_builder(self) -> DisplayBuilder; + fn display_builder(self) -> DisplayBuilder { + DisplayBuilder(self) + } #[inline] fn build(self) -> Self { @@ -53,28 +82,34 @@ pub trait BuildLit: Sized { } } -impl BuildLit for &'static str { - #[inline] - fn display_builder(self) -> DisplayBuilder { - DisplayBuilder(Cow::Borrowed(self)) +impl BuildLit for &'static str {} +impl BuildLit for bool {} + +impl Lit for &'static str { + type AsSTring = Self; + fn into_string(self) -> Self::AsSTring { + self } } -impl BuildLit for bool { - #[inline] - fn display_builder(self) -> DisplayBuilder { +impl Lit for bool { + type AsSTring = &'static str; + fn into_string(self) -> Self::AsSTring { match self { - true => DisplayBuilder(Cow::Borrowed("true")), - false => DisplayBuilder(Cow::Borrowed("false")), + true => "true", + false => "false", } } } macro_rules! impl_build_lit_nums { ($t:ty) => { - impl BuildLit for $t { - fn display_builder(self) -> DisplayBuilder { - DisplayBuilder(Cow::Owned(ToString::to_string(&self))) + impl BuildLit for $t {} + + impl Lit for $t { + type AsSTring = String; + fn into_string(self) -> Self::AsSTring { + ToString::to_string(&self) } } }; diff --git a/leptos_i18n_macro/src/load_locales/interpolate.rs b/leptos_i18n_macro/src/load_locales/interpolate.rs index ddae6779..f0284289 100644 --- a/leptos_i18n_macro/src/load_locales/interpolate.rs +++ b/leptos_i18n_macro/src/load_locales/interpolate.rs @@ -310,8 +310,8 @@ impl Interpolation { } #[inline] - pub fn build_string(self) -> std::borrow::Cow<'static, str> { - std::borrow::Cow::Owned(self.build().to_string()) + pub fn build_string(self) -> String { + self.build().to_string() } } } @@ -406,6 +406,14 @@ impl Interpolation { #into_view_field: core::marker::PhantomData<(#(#into_views,)*)> }; + let string_builder_trait_impl = if cfg!(feature = "interpolate_display") { + quote! { + impl l_i18n_crate::__private::InterpolationStringBuilder for #dummy_ident {} + } + } else { + quote!() + }; + quote! { #[allow(non_camel_case_types, non_snake_case)] #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] @@ -413,6 +421,8 @@ impl Interpolation { #locale_field: #enum_ident } + #string_builder_trait_impl + #[allow(non_camel_case_types, non_snake_case)] #[derive(l_i18n_crate::reexports::typed_builder::TypedBuilder)] #[builder(crate_module_path = l_i18n_crate::reexports::typed_builder)] diff --git a/leptos_i18n_macro/src/t_macro/mod.rs b/leptos_i18n_macro/src/t_macro/mod.rs index 38636677..ac64915f 100644 --- a/leptos_i18n_macro/src/t_macro/mod.rs +++ b/leptos_i18n_macro/src/t_macro/mod.rs @@ -53,6 +53,14 @@ pub fn t_macro_inner( let (#(#keys,)*) = (#(#values,)*); }; + let get_key = if matches!(output_type, OutputType::String | OutputType::Display) { + quote! { + leptos_i18n::__private::InterpolationStringBuilder::check(#get_key) + } + } else { + get_key + }; + let inner = quote! { { let _builder = #get_key.#builder_fn();