Skip to content

Commit c91d9f4

Browse files
authored
Resolve function instead in impl ResolveValue (#262)
* Resolve function instead in impl ResolveValue Before this change we were using version from WriteValue, which basically ignored type of function and always converting it to string, which made NUMBER function useless when used on strings or even wrong when used on numbers. * Added test for resolving function
1 parent 7e53726 commit c91d9f4

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

fluent-bundle/src/resolver/inline_expression.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,19 @@ impl<'p> ResolveValue for ast::InlineExpression<&'p str> {
171171
FluentValue::Error
172172
}
173173
}
174+
Self::FunctionReference { id, arguments } => {
175+
let (resolved_positional_args, resolved_named_args) =
176+
scope.get_arguments(Some(arguments));
177+
178+
let func = scope.bundle.get_entry_function(id.name);
179+
180+
if let Some(func) = func {
181+
let result = func(resolved_positional_args.as_slice(), &resolved_named_args);
182+
result
183+
} else {
184+
FluentValue::Error
185+
}
186+
}
174187
_ => {
175188
let mut result = String::new();
176189
self.write(&mut result, scope).expect("Failed to write");

fluent-bundle/tests/function.rs

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
use fluent_bundle::types::FluentNumber;
2+
use fluent_bundle::{FluentArgs, FluentBundle, FluentResource, FluentValue};
3+
4+
#[test]
5+
fn test_function_resolve() {
6+
// 1. Create bundle
7+
let ftl_string = String::from(
8+
"
9+
liked-count = { $num ->
10+
[0] No likes yet.
11+
[one] One person liked your message
12+
*[other] { $num } people liked your message
13+
}
14+
15+
liked-count2 = { NUMBER($num) ->
16+
[0] No likes yet.
17+
[one] One person liked your message
18+
*[other] { $num } people liked your message
19+
}
20+
",
21+
);
22+
23+
let res = FluentResource::try_new(ftl_string).expect("Could not parse an FTL string.");
24+
let mut bundle = FluentBundle::default();
25+
26+
bundle
27+
.add_function("NUMBER", |positional, named| match positional.get(0) {
28+
Some(FluentValue::Number(n)) => {
29+
let mut num = n.clone();
30+
num.options.merge(named);
31+
32+
FluentValue::Number(num)
33+
}
34+
Some(FluentValue::String(s)) => {
35+
let num: f64 = if let Ok(n) = s.to_owned().parse() {
36+
n
37+
} else {
38+
return FluentValue::Error;
39+
};
40+
let mut num = FluentNumber {
41+
value: num,
42+
options: Default::default(),
43+
};
44+
num.options.merge(named);
45+
46+
FluentValue::Number(num)
47+
}
48+
_ => FluentValue::Error,
49+
})
50+
.expect("Failed to add a function.");
51+
52+
bundle
53+
.add_resource(res)
54+
.expect("Failed to add FTL resources to the bundle.");
55+
56+
// 2. Example without NUMBER call
57+
let msg = bundle
58+
.get_message("liked-count")
59+
.expect("Message doesn't exist.");
60+
61+
let mut args = FluentArgs::new();
62+
args.set("num", FluentValue::from("1"));
63+
64+
let mut errors = vec![];
65+
let pattern = msg.value().expect("Message has no value.");
66+
let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
67+
assert_eq!("\u{2068}1\u{2069} people liked your message", &value);
68+
69+
// 3. Example with passing number, but without NUMBER call
70+
let mut args = FluentArgs::new();
71+
args.set("num", FluentValue::from(1));
72+
73+
let msg = bundle
74+
.get_message("liked-count")
75+
.expect("Message doesn't exist.");
76+
let mut errors = vec![];
77+
let pattern = msg.value().expect("Message has no value.");
78+
let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
79+
assert_eq!("One person liked your message", &value);
80+
81+
// 4. Example with NUMBER call
82+
let mut args = FluentArgs::new();
83+
args.set("num", FluentValue::from("1"));
84+
85+
let msg = bundle
86+
.get_message("liked-count2")
87+
.expect("Message doesn't exist.");
88+
let mut errors = vec![];
89+
let pattern = msg.value().expect("Message has no value.");
90+
let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
91+
assert_eq!("One person liked your message", &value);
92+
93+
// 5. Example with NUMBER call from number
94+
let mut args = FluentArgs::new();
95+
args.set("num", FluentValue::from(1));
96+
97+
let msg = bundle
98+
.get_message("liked-count2")
99+
.expect("Message doesn't exist.");
100+
let mut errors = vec![];
101+
let pattern = msg.value().expect("Message has no value.");
102+
let value = bundle.format_pattern(&pattern, Some(&args), &mut errors);
103+
assert_eq!("One person liked your message", &value);
104+
}

0 commit comments

Comments
 (0)