Skip to content

Commit

Permalink
Merge 67a5f46 into 1834376
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiretza committed Apr 26, 2024
2 parents 1834376 + 67a5f46 commit 01bdccb
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 4 deletions.
14 changes: 14 additions & 0 deletions fluent-bundle/src/builtins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::{FluentArgs, FluentValue};

#[allow(non_snake_case)]
pub fn NUMBER<'a>(positional: &[FluentValue<'a>], named: &FluentArgs) -> FluentValue<'a> {
let Some(FluentValue::Number(n)) = positional.first() else {
return FluentValue::Error;
};

let mut n = n.clone();
n.options.merge(named);
println!("{named:?} => {n:?}");

FluentValue::Number(n)
}
55 changes: 55 additions & 0 deletions fluent-bundle/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,61 @@ impl<R, M> FluentBundle<R, M> {
}),
}
}

/// Adds the builtin functions described in the [FTL syntax guide] to the bundle, making them
/// available in messages.
///
/// # Examples
///
/// ```
/// use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
/// use unic_langid::langid;
///
/// let ftl_string = String::from(r#"rank = { NUMBER($n, type: "ordinal") ->
/// [1] first
/// [2] second
/// [3] third
/// [one] {$n}st
/// [two] {$n}nd
/// [few] {$n}rd
/// *[other] {$n}th
/// }"#);
/// let resource = FluentResource::try_new(ftl_string)
/// .expect("Could not parse an FTL string.");
/// let langid_en = langid!("en-US");
/// let mut bundle = FluentBundle::new(vec![langid_en]);
/// bundle.add_resource(&resource)
/// .expect("Failed to add FTL resources to the bundle.");
///
/// // Register the builtin functions (including NUMBER())
/// bundle.add_builtins().expect("Failed to add builtins to the bundle.");
///
/// let msg = bundle.get_message("rank").expect("Message doesn't exist.");
/// let mut errors = vec![];
/// let pattern = msg.value().expect("Message has no value.");
///
/// let mut args = FluentArgs::new();
///
/// args.set("n", 5);
/// let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
/// assert_eq!(&value, "\u{2068}5\u{2069}th");
///
/// args.set("n", 12);
/// let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
/// assert_eq!(&value, "\u{2068}12\u{2069}th");
///
/// args.set("n", 22);
/// let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
/// assert_eq!(&value, "\u{2068}22\u{2069}nd");
/// ```
///
/// [FTL syntax guide]: https://projectfluent.org/fluent/guide/functions.html
pub fn add_builtins(&mut self) -> Result<(), FluentError> {
self.add_function("NUMBER", crate::builtins::NUMBER)?;
// TODO: DATETIME()

Ok(())
}
}

impl<R> Default for FluentBundle<R, IntlLangMemoizer> {
Expand Down
1 change: 1 addition & 0 deletions fluent-bundle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ mod message;
pub mod resolver;
mod resource;
pub mod types;
pub mod builtins;

pub use args::FluentArgs;
/// Specialized [`FluentBundle`](crate::bundle::FluentBundle) over
Expand Down
11 changes: 7 additions & 4 deletions fluent-bundle/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,16 @@ impl<'source> FluentValue<'source> {
};
// This string matches a plural rule keyword. Check if the number
// matches the plural rule category.
let r#type = match b.options.r#type {
FluentNumberType::Cardinal => PluralRuleType::CARDINAL,
FluentNumberType::Ordinal => PluralRuleType::ORDINAL,
};
scope
.bundle
.intls
.with_try_get_threadsafe::<PluralRules, _, _>(
(PluralRuleType::CARDINAL,),
|pr| pr.0.select(b) == Ok(cat),
)
.with_try_get_threadsafe::<PluralRules, _, _>((r#type,), |pr| {
pr.0.select(b) == Ok(cat)
})
.unwrap()
}
_ => false,
Expand Down
27 changes: 27 additions & 0 deletions fluent-bundle/src/types/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@ use intl_pluralrules::operands::PluralOperands;
use crate::args::FluentArgs;
use crate::types::FluentValue;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum FluentNumberType {
Cardinal,
Ordinal,
}

impl std::default::Default for FluentNumberType {
fn default() -> Self {
Self::Cardinal
}
}

impl From<&str> for FluentNumberType {
fn from(input: &str) -> Self {
match input {
"cardinal" => Self::Cardinal,
"ordinal" => Self::Ordinal,
_ => Self::default(),
}
}
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum FluentNumberStyle {
Decimal,
Expand Down Expand Up @@ -58,6 +80,7 @@ impl From<&str> for FluentNumberCurrencyDisplayStyle {

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct FluentNumberOptions {
pub r#type: FluentNumberType,
pub style: FluentNumberStyle,
pub currency: Option<String>,
pub currency_display: FluentNumberCurrencyDisplayStyle,
Expand All @@ -72,6 +95,7 @@ pub struct FluentNumberOptions {
impl Default for FluentNumberOptions {
fn default() -> Self {
Self {
r#type: Default::default(),
style: Default::default(),
currency: None,
currency_display: Default::default(),
Expand All @@ -89,6 +113,9 @@ impl FluentNumberOptions {
pub fn merge(&mut self, opts: &FluentArgs) {
for (key, value) in opts.iter() {
match (key, value) {
("type", FluentValue::String(n)) => {
self.r#type = n.as_ref().into();
}
("style", FluentValue::String(n)) => {
self.style = n.as_ref().into();
}
Expand Down

0 comments on commit 01bdccb

Please sign in to comment.