Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ serde_json = "1.0"
thiserror = "1.0"
tokio = "1.0"
unic-langid = "0.9"
icu_locid = "1.4"
icu_provider = "1.4"
icu_decimal = "1.4"
fixed_decimal = "0.5"

fluent-bundle = { version = "0.15.3", path = "fluent-bundle" }
fluent-fallback = { version = "0.7.1", path = "fluent-fallback" }
Expand Down
5 changes: 5 additions & 0 deletions fluent-bundle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ include = [
]

[dependencies]
fixed_decimal = { workspace = true, features = ["ryu"] }
fluent-langneg.workspace = true
fluent-syntax.workspace = true
icu_decimal.workspace = true
icu_locid.workspace = true
icu_provider = { workspace = true, features = ["sync"] }
intl_pluralrules.workspace = true
rustc-hash.workspace = true
unic-langid.workspace = true
Expand All @@ -36,6 +40,7 @@ smallvec = "1.13"
[dev-dependencies]
criterion.workspace = true
iai.workspace = true
icu_testdata = "1.4"
serde = { workspace = true, features = ["derive"] }
unic-langid = { workspace = true, features = ["macros"] }
rand = "0.8"
Expand Down
10 changes: 8 additions & 2 deletions fluent-bundle/examples/custom_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl FluentType for DateTime {
}
fn as_string(&self, intls: &intl_memoizer::IntlLangMemoizer) -> std::borrow::Cow<'static, str> {
intls
.with_try_get::<DateTimeFormatter, _, _>((self.options.clone(),), |dtf| {
.with_try_get::<DateTimeFormatter, _, _>((self.options.clone(),), &(), |dtf| {
dtf.format(self.epoch).into()
})
.expect("Failed to format a date.")
Expand Down Expand Up @@ -138,7 +138,13 @@ impl DateTimeFormatter {
impl Memoizable for DateTimeFormatter {
type Args = (DateTimeOptions,);
type Error = ();
fn construct(lang: LanguageIdentifier, args: Self::Args) -> Result<Self, Self::Error> {
type DataProvider = ();

fn construct(
lang: LanguageIdentifier,
args: Self::Args,
_: &Self::DataProvider,
) -> Result<Self, Self::Error> {
Self::new(lang, args.0)
}
}
Expand Down
18 changes: 16 additions & 2 deletions fluent-bundle/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! internationalization formatters, functions, scopeironmental variables and are expected to be used
//! together.

use icu_provider::AnyProvider;
use rustc_hash::FxHashMap;
use std::borrow::Borrow;
use std::borrow::Cow;
Expand All @@ -25,6 +26,8 @@ use crate::resolver::{ResolveValue, Scope, WriteValue};
use crate::resource::FluentResource;
use crate::types::FluentValue;

pub type IcuDataProvider = Box<dyn AnyProvider>;

/// A collection of localization messages for a single locale, which are meant
/// to be used together in a single view, widget or any other UI abstraction.
///
Expand Down Expand Up @@ -141,6 +144,7 @@ pub struct FluentBundle<R, M> {
pub(crate) use_isolating: bool,
pub(crate) transform: Option<fn(&str) -> Cow<str>>,
pub(crate) formatter: Option<fn(&FluentValue, &M) -> Option<String>>,
pub(crate) icu_data_provider: Option<IcuDataProvider>,
}

impl<R, M> FluentBundle<R, M> {
Expand Down Expand Up @@ -548,6 +552,10 @@ impl<R, M> FluentBundle<R, M> {
}
}

pub fn set_icu_data_provider(&mut self, provider: IcuDataProvider) {
self.icu_data_provider = Some(provider);
}

/// Adds the builtin functions described in the [FTL syntax guide] to the bundle, making them
/// available in messages.
///
Expand Down Expand Up @@ -641,6 +649,7 @@ impl<R> FluentBundle<R, IntlLangMemoizer> {
use_isolating: true,
transform: None,
formatter: None,
icu_data_provider: None,
}
}
}
Expand All @@ -653,14 +662,19 @@ impl crate::memoizer::MemoizerKind for IntlLangMemoizer {
Self::new(lang)
}

fn with_try_get_threadsafe<I, R, U>(&self, args: I::Args, cb: U) -> Result<R, I::Error>
fn with_try_get_threadsafe<I, R, U>(
&self,
args: I::Args,
data_provider: &I::DataProvider,
cb: U,
) -> Result<R, I::Error>
where
Self: Sized,
I: intl_memoizer::Memoizable + Send + Sync + 'static,
I::Args: Send + Sync + 'static,
U: FnOnce(&I) -> R,
{
self.with_try_get(args, cb)
self.with_try_get(args, data_provider, cb)
}

fn stringify_value(
Expand Down
10 changes: 8 additions & 2 deletions fluent-bundle/src/concurrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ impl<R> FluentBundle<R> {
use_isolating: true,
transform: None,
formatter: None,
icu_data_provider: None,
}
}
}
Expand All @@ -51,14 +52,19 @@ impl MemoizerKind for IntlLangMemoizer {
Self::new(lang)
}

fn with_try_get_threadsafe<I, R, U>(&self, args: I::Args, cb: U) -> Result<R, I::Error>
fn with_try_get_threadsafe<I, R, U>(
&self,
args: I::Args,
data_provider: &I::DataProvider,
cb: U,
) -> Result<R, I::Error>
where
Self: Sized,
I: Memoizable + Send + Sync + 'static,
I::Args: Send + Sync + 'static,
U: FnOnce(&I) -> R,
{
self.with_try_get(args, cb)
self.with_try_get(args, data_provider, cb)
}

fn stringify_value(&self, value: &dyn FluentType) -> std::borrow::Cow<'static, str> {
Expand Down
7 changes: 6 additions & 1 deletion fluent-bundle/src/memoizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ pub trait MemoizerKind: 'static {
///
/// `U` - The callback that accepts the instance of the intl formatter, and generates
/// some kind of results `R`.
fn with_try_get_threadsafe<I, R, U>(&self, args: I::Args, callback: U) -> Result<R, I::Error>
fn with_try_get_threadsafe<I, R, U>(
&self,
args: I::Args,
data_provider: &I::DataProvider,
callback: U,
) -> Result<R, I::Error>
where
Self: Sized,
I: Memoizable + Send + Sync + 'static,
Expand Down
8 changes: 4 additions & 4 deletions fluent-bundle/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl<'source> FluentValue<'source> {
scope
.bundle
.intls
.with_try_get_threadsafe::<PluralRules, _, _>((r#type,), |pr| {
.with_try_get_threadsafe::<PluralRules, _, _>((r#type,), &(), |pr| {
pr.0.select(b) == Ok(cat)
})
.unwrap()
Expand All @@ -229,7 +229,7 @@ impl<'source> FluentValue<'source> {
}
match self {
FluentValue::String(s) => w.write_str(s),
FluentValue::Number(n) => w.write_str(&n.as_string()),
FluentValue::Number(n) => w.write_str(&n.as_string(scope.bundle)),
FluentValue::Custom(s) => w.write_str(&scope.bundle.intls.stringify_value(&**s)),
FluentValue::Error => Ok(()),
FluentValue::None => Ok(()),
Expand All @@ -251,7 +251,7 @@ impl<'source> FluentValue<'source> {
}
match self {
FluentValue::String(s) => s.clone(),
FluentValue::Number(n) => n.as_string(),
FluentValue::Number(n) => n.as_string(scope.bundle),
FluentValue::Custom(s) => scope.bundle.intls.stringify_value(&**s),
FluentValue::Error => "".into(),
FluentValue::None => "".into(),
Expand All @@ -273,7 +273,7 @@ impl<'source> FluentValue<'source> {
}
match self {
FluentValue::String(s) => s,
FluentValue::Number(n) => n.as_string(),
FluentValue::Number(n) => n.as_string(scope.bundle),
FluentValue::Custom(s) => scope.bundle.intls.stringify_value(s.as_ref()),
FluentValue::Error => "".into(),
FluentValue::None => "".into(),
Expand Down
Loading