Skip to content

Commit f7258c1

Browse files
committed
Add i18n fallback
1 parent a3918d4 commit f7258c1

File tree

3 files changed

+44
-10
lines changed

3 files changed

+44
-10
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ lazy_static = "1.2.0"
99
fluent = "0.5"
1010
fluent-bundle = "0.6.0"
1111
fluent-syntax = "0.9.0"
12+
fluent-locale = "0.4.1"
1213
rand = "0.6"
1314
regex = "1"
1415
rocket = "0.4.1"

src/i18n.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,48 @@ use std::io::prelude::*;
1515
use std::path::Path;
1616

1717
use fluent_bundle::{FluentBundle, FluentResource, FluentValue};
18+
use fluent_locale::negotiate_languages;
1819

1920
lazy_static! {
2021
static ref RESOURCES: HashMap<String, Vec<FluentResource>> = build_resources();
2122
static ref BUNDLES: HashMap<String, FluentBundle<'static>> = build_bundles();
23+
static ref LOCALES: Vec<String> = build_locale_list();
24+
}
25+
26+
pub struct Fallback<'res> {
27+
default: Option<&'res str>,
28+
availables: &'res Vec<String>,
29+
}
30+
31+
impl<'res> Fallback<'res> {
32+
pub fn new(available_locales: &'res Vec<String>) -> Self {
33+
Self {
34+
default: Some("en-US"),
35+
availables: available_locales,
36+
}
37+
}
38+
39+
pub fn order<'t, T: AsRef<str>>(&'t self, targets: &'t [T]) -> Vec<&'t str> {
40+
negotiate_languages(
41+
targets,
42+
&self.availables,
43+
self.default,
44+
&fluent_locale::NegotiationStrategy::Filtering,
45+
)
46+
}
2247
}
2348

2449
pub struct I18NHelper {
2550
bundles: &'static HashMap<String, FluentBundle<'static>>,
51+
fallback: Fallback<'static>,
2652
}
2753

2854
impl I18NHelper {
2955
pub fn new() -> Self {
30-
Self { bundles: &*BUNDLES }
56+
Self {
57+
bundles: &*BUNDLES,
58+
fallback: Fallback::new(&*LOCALES),
59+
}
3160
}
3261

3362
pub fn lookup(
@@ -58,17 +87,12 @@ impl I18NHelper {
5887
text_id: &str,
5988
args: Option<&HashMap<&str, FluentValue>>,
6089
) -> String {
61-
if let Some(val) = self.lookup(lang, text_id, args) {
62-
val
63-
} else if lang != "en-US" {
64-
if let Some(val) = self.lookup("en-US", text_id, args) {
65-
val
66-
} else {
67-
format!("Unknown localization {}", text_id)
90+
for l in self.fallback.order(&[lang]) {
91+
if let Some(val) = self.lookup(l, text_id, args) {
92+
return val;
6893
}
69-
} else {
70-
format!("Unknown localization {}", text_id)
7194
}
95+
format!("Unknown localization {}", text_id)
7296
}
7397
}
7498

@@ -284,6 +308,14 @@ pub fn create_bundle(lang: &str, resources: &'static Vec<FluentResource>) -> Flu
284308
bundle
285309
}
286310

311+
fn build_locale_list() -> Vec<String> {
312+
let mut locale_list = Vec::new();
313+
for key in RESOURCES.keys() {
314+
locale_list.push(key.clone());
315+
}
316+
locale_list
317+
}
318+
287319
fn build_resources() -> HashMap<String, Vec<FluentResource>> {
288320
let mut all_resources = HashMap::new();
289321
let entries = read_dir("./templates/fluent-resource").unwrap();

0 commit comments

Comments
 (0)