Skip to content

Commit 12cc561

Browse files
authored
Refactor of the code, 0.8 compatibility, zero-copy AST/parsing, Rust 2018 goodies (#76)
1 parent efc8813 commit 12cc561

File tree

154 files changed

+10041
-3322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

154 files changed

+10041
-3322
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/target/
2+
*/target/
23
**/*.rs.bk
34
Cargo.lock

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = [
3-
"fluent",
4-
"fluent-syntax"
3+
"fluent-syntax",
4+
"fluent-bundle",
5+
"fluent-cli"
56
]
File renamed without changes.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
[package]
2-
name = "fluent"
2+
name = "fluent-bundle"
33
description = """
4-
A localization library designed to unleash the entire expressive power of
4+
A localization system designed to unleash the entire expressive power of
55
natural language translations.
66
"""
77
version = "0.4.3"
8+
edition = "2018"
89
authors = [
910
"Zibi Braniecki <[email protected]>",
1011
"Staś Małolepszy <[email protected]>"
@@ -17,9 +18,9 @@ keywords = ["localization", "l10n", "i18n", "intl", "internationalization"]
1718
categories = ["localization", "internationalization"]
1819

1920
[dependencies]
20-
clap = "2.32"
2121
fluent-locale = "^0.4.1"
22-
fluent-syntax = "0.1.1"
23-
failure = "0.1"
24-
failure_derive = "0.1"
25-
intl_pluralrules = "1.0"
22+
fluent-syntax = { path = "../fluent-syntax" }
23+
failure = "^0.1"
24+
failure_derive = "^0.1"
25+
intl_pluralrules = "^1.0"
26+
rental = "^0.5.2"

fluent/README.md renamed to fluent-bundle/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Usage
2222
-----
2323

2424
```rust
25-
use fluent::bundle::FluentBundle;
25+
use fluent_bundle::FluentBundle;
2626

2727
fn main() {
2828
let mut bundle = FluentBundle::new(&["en-US"]);
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,70 @@
11
#![feature(test)]
22

3-
extern crate fluent;
4-
extern crate fluent_syntax;
53
extern crate test;
64

7-
use fluent::bundle::FluentBundle;
8-
use fluent_syntax::{ast, parser::parse};
5+
use fluent_bundle::bundle::FluentBundle;
6+
use fluent_bundle::resource::FluentResource;
7+
use fluent_syntax::ast;
98
use std::fs::File;
109
use std::io;
1110
use std::io::Read;
1211
use test::Bencher;
1312

1413
fn read_file(path: &str) -> Result<String, io::Error> {
15-
let mut f = try!(File::open(path));
14+
let mut f = File::open(path)?;
1615
let mut s = String::new();
17-
try!(f.read_to_string(&mut s));
16+
f.read_to_string(&mut s)?;
1817
Ok(s)
1918
}
2019

2120
#[bench]
2221
fn bench_simple_format(b: &mut Bencher) {
2322
let source = read_file("./benches/simple.ftl").expect("Couldn't load file");
24-
let resource = parse(&source).unwrap();
23+
let res = FluentResource::try_new(source).expect("Couldn't parse an FTL source");
2524

2625
let mut ids = Vec::new();
2726

28-
for entry in resource.body {
27+
for entry in &res.ast().body {
2928
match entry {
30-
ast::Entry::Message(ast::Message { id, .. }) => ids.push(id.name),
29+
ast::ResourceEntry::Entry(ast::Entry::Message(ast::Message { id, .. })) => {
30+
ids.push(id.name)
31+
}
3132
_ => continue,
3233
};
3334
}
3435

3536
let mut bundle = FluentBundle::new(&["x-testing"]);
36-
bundle.add_messages(&source).unwrap();
37+
bundle
38+
.add_resource(&res)
39+
.expect("Couldn't add FluentResource to the FluentBundle");
3740

3841
b.iter(|| {
3942
for id in &ids {
40-
bundle.format(id.as_str(), None);
43+
bundle.format(id, None);
4144
}
4245
});
4346
}
4447

4548
#[bench]
4649
fn bench_menubar_format(b: &mut Bencher) {
4750
let source = read_file("./benches/menubar.ftl").expect("Couldn't load file");
48-
let resource = parse(&source).unwrap();
51+
let res = FluentResource::try_new(source).expect("Couldn't parse an FTL source");
4952

5053
let mut ids = Vec::new();
5154

52-
for entry in resource.body {
55+
for entry in &res.ast().body {
5356
match entry {
54-
ast::Entry::Message(ast::Message { id, .. }) => ids.push(id.name),
57+
ast::ResourceEntry::Entry(ast::Entry::Message(ast::Message { id, .. })) => {
58+
ids.push(id.name)
59+
}
5560
_ => continue,
5661
};
5762
}
5863

5964
let mut bundle = FluentBundle::new(&["x-testing"]);
60-
bundle.add_messages(&source).unwrap();
65+
bundle
66+
.add_resource(&res)
67+
.expect("Couldn't add FluentResource to the FluentBundle");
6168

6269
b.iter(|| {
6370
for id in &ids {
@@ -66,7 +73,7 @@ fn bench_menubar_format(b: &mut Bencher) {
6673
// widgets may only expect attributes and they shouldn't be forced to display a value.
6774
// Here however it doesn't matter because we know for certain that the message for `id`
6875
// exists.
69-
bundle.format_message(id.as_str(), None);
76+
bundle.compound(id, None);
7077
}
7178
});
7279
}
File renamed without changes.
File renamed without changes.
File renamed without changes.

fluent/examples/external_arguments.rs renamed to fluent-bundle/examples/external_arguments.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
extern crate fluent;
2-
3-
use fluent::bundle::FluentBundle;
4-
use fluent::types::FluentValue;
1+
use fluent_bundle::bundle::FluentBundle;
2+
use fluent_bundle::resource::FluentResource;
3+
use fluent_bundle::types::FluentValue;
54
use std::collections::HashMap;
65

76
fn main() {
8-
let mut bundle = FluentBundle::new(&["en"]);
9-
bundle
10-
.add_messages(
11-
"
7+
let res = FluentResource::try_new(
8+
"
129
hello-world = Hello { $name }
1310
ref = The previous message says { hello-world }
1411
unread-emails =
1512
{ $emailCount ->
1613
[one] You have { $emailCount } unread email
1714
*[other] You have { $emailCount } unread emails
1815
}
19-
",
20-
)
21-
.unwrap();
16+
"
17+
.to_owned(),
18+
)
19+
.unwrap();
20+
let mut bundle = FluentBundle::new(&["en"]);
21+
bundle.add_resource(&res).unwrap();
2222

2323
let mut args = HashMap::new();
2424
args.insert("name", FluentValue::from("John"));

fluent/examples/functions.rs renamed to fluent-bundle/examples/functions.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
extern crate fluent;
2-
3-
use fluent::bundle::FluentBundle;
4-
use fluent::types::FluentValue;
1+
use fluent_bundle::bundle::FluentBundle;
2+
use fluent_bundle::resource::FluentResource;
3+
use fluent_bundle::types::FluentValue;
54

65
fn main() {
6+
// We define the resources here so that they outlive
7+
// the bundle.
8+
let res1 = FluentResource::try_new("hello-world = Hey there! { HELLO() }".to_owned()).unwrap();
9+
let res2 =
10+
FluentResource::try_new("meaning-of-life = { MEANING_OF_LIFE(42) }".to_owned()).unwrap();
11+
let res3 = FluentResource::try_new(
12+
"all-your-base = { BASE_OWNERSHIP(hello, ownership: \"us\") }".to_owned(),
13+
)
14+
.unwrap();
15+
716
let mut bundle = FluentBundle::new(&["en-US"]);
817

918
// Test for a simple function that returns a string
@@ -40,15 +49,9 @@ fn main() {
4049
})
4150
.unwrap();
4251

43-
bundle
44-
.add_messages("hello-world = Hey there! { HELLO() }")
45-
.unwrap();
46-
bundle
47-
.add_messages("meaning-of-life = { MEANING_OF_LIFE(42) }")
48-
.unwrap();
49-
bundle
50-
.add_messages("all-your-base = { BASE_OWNERSHIP(hello, ownership: \"us\") }")
51-
.unwrap();
52+
bundle.add_resource(&res1).unwrap();
53+
bundle.add_resource(&res2).unwrap();
54+
bundle.add_resource(&res3).unwrap();
5255

5356
let value = bundle.format("hello-world", None);
5457
assert_eq!(

fluent-bundle/examples/hello.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
use fluent_bundle::bundle::FluentBundle;
2+
use fluent_bundle::resource::FluentResource;
3+
4+
fn main() {
5+
let res = FluentResource::try_new("hello-world = Hello, world!".to_owned()).unwrap();
6+
let mut bundle = FluentBundle::new(&["en-US"]);
7+
bundle.add_resource(&res).unwrap();
8+
let (value, _) = bundle.format("hello-world", None).unwrap();
9+
assert_eq!(&value, "Hello, world!");
10+
}

fluent/examples/message_reference.rs renamed to fluent-bundle/examples/message_reference.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
extern crate fluent;
2-
3-
use fluent::bundle::FluentBundle;
1+
use fluent_bundle::bundle::FluentBundle;
2+
use fluent_bundle::resource::FluentResource;
43

54
fn main() {
6-
let mut bundle = FluentBundle::new(&["x-testing"]);
7-
bundle
8-
.add_messages(
9-
"
5+
let res = FluentResource::try_new(
6+
"
107
foo = Foo
118
foobar = { foo } Bar
129
bazbar = { baz } Bar
13-
",
14-
)
15-
.unwrap();
10+
"
11+
.to_owned(),
12+
)
13+
.unwrap();
14+
15+
let mut bundle = FluentBundle::new(&["x-testing"]);
16+
bundle.add_resource(&res).unwrap();
1617

1718
match bundle.format("foobar", None) {
1819
Some((value, _)) => println!("{}", value),

fluent/examples/selector.rs renamed to fluent-bundle/examples/selector.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
extern crate fluent;
2-
3-
use fluent::bundle::FluentBundle;
4-
use fluent::types::FluentValue;
1+
use fluent_bundle::bundle::FluentBundle;
2+
use fluent_bundle::resource::FluentResource;
3+
use fluent_bundle::types::FluentValue;
54
use std::collections::HashMap;
65

76
fn main() {
8-
let mut bundle = FluentBundle::new(&["x-testing"]);
9-
bundle
10-
.add_messages(
11-
"
7+
let res = FluentResource::try_new(
8+
"
129
hello-world = Hello {
1310
*[one] World
1411
[two] Moon
@@ -18,9 +15,12 @@ hello-world2 = Hello { $name ->
1815
*[world] World
1916
[moon] Moon
2017
}
21-
",
22-
)
23-
.unwrap();
18+
"
19+
.to_owned(),
20+
)
21+
.unwrap();
22+
let mut bundle = FluentBundle::new(&["x-testing"]);
23+
bundle.add_resource(&res).unwrap();
2424

2525
match bundle.format("hello-world", None) {
2626
Some((value, _)) => println!("{}", value),

fluent/examples/simple.rs renamed to fluent-bundle/examples/simple-app.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@
1717
//!
1818
//! If the second argument is omitted, `en-US` locale is used as the
1919
//! default one.
20-
extern crate fluent;
21-
extern crate fluent_locale;
22-
23-
use fluent::bundle::FluentBundle;
24-
use fluent::types::FluentValue;
20+
use fluent_bundle::bundle::FluentBundle;
21+
use fluent_bundle::resource::FluentResource;
22+
use fluent_bundle::types::FluentValue;
2523
use fluent_locale::{negotiate_languages, NegotiationStrategy};
2624
use std::collections::HashMap;
2725
use std::env;
@@ -37,9 +35,9 @@ use std::str::FromStr;
3735
/// The resource files are stored in
3836
/// `./examples/resources/{locale}` directory.
3937
fn read_file(path: &str) -> Result<String, io::Error> {
40-
let mut f = try!(File::open(path));
38+
let mut f = File::open(path)?;
4139
let mut s = String::new();
42-
try!(f.read_to_string(&mut s));
40+
f.read_to_string(&mut s)?;
4341
Ok(s)
4442
}
4543

@@ -95,7 +93,10 @@ fn main() {
9593
// 1. Get the command line arguments.
9694
let args: Vec<String> = env::args().collect();
9795

98-
// 2. If the argument length is more than 1,
96+
// 2. Allocate resources.
97+
let mut resources: Vec<FluentResource> = vec![];
98+
99+
// 3. If the argument length is more than 1,
99100
// take the second argument as a comma-separated
100101
// list of requested locales.
101102
//
@@ -104,38 +105,41 @@ fn main() {
104105
.get(2)
105106
.map_or(vec!["en-US"], |arg| arg.split(",").collect());
106107

107-
// 3. Negotiate it against the avialable ones
108+
// 4. Negotiate it against the avialable ones
108109
let locales = get_app_locales(&requested).expect("Failed to retrieve available locales");
109110

110-
// 4. Create a new Fluent FluentBundle using the
111+
// 5. Create a new Fluent FluentBundle using the
111112
// resolved locales.
112113
let mut bundle = FluentBundle::new(&locales);
113114

114-
// 5. Load the localization resource
115+
// 6. Load the localization resource
115116
for path in L10N_RESOURCES {
116117
let full_path = format!(
117118
"./examples/resources/{locale}/{path}",
118119
locale = locales[0],
119120
path = path
120121
);
121-
let res = read_file(&full_path).unwrap();
122-
// 5.1 Insert the loaded resource into the
123-
// Fluent FluentBundle.
124-
bundle.add_messages(&res).unwrap();
122+
let source = read_file(&full_path).unwrap();
123+
let resource = FluentResource::try_new(source).unwrap();
124+
resources.push(resource);
125+
}
126+
127+
for res in &resources {
128+
bundle.add_resource(res).unwrap();
125129
}
126130

127-
// 6. Check if the input is provided.
131+
// 7. Check if the input is provided.
128132
match args.get(1) {
129133
Some(input) => {
130-
// 6.1. Cast it to a number.
134+
// 7.1. Cast it to a number.
131135
match isize::from_str(&input) {
132136
Ok(i) => {
133-
// 6.2. Construct a map of arguments
137+
// 7.2. Construct a map of arguments
134138
// to format the message.
135139
let mut args = HashMap::new();
136140
args.insert("input", FluentValue::from(i));
137141
args.insert("value", FluentValue::from(collatz(i)));
138-
// 6.3. Format the message.
142+
// 7.3. Format the message.
139143
println!("{}", bundle.format("response-msg", Some(&args)).unwrap().0);
140144
}
141145
Err(err) => {

0 commit comments

Comments
 (0)