Skip to content

Commit 0d14185

Browse files
committed
Special case English fallback, improve lifetimes
1 parent bd690c2 commit 0d14185

File tree

1 file changed

+51
-38
lines changed

1 file changed

+51
-38
lines changed

src/i18n.rs

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -22,46 +22,44 @@ lazy_static! {
2222
read_from_file("./locales/core.ftl").expect("cannot find core.ftl");
2323
static ref RESOURCES: HashMap<String, Vec<FluentResource>> = build_resources();
2424
static ref BUNDLES: HashMap<String, FluentBundle<'static>> = build_bundles();
25-
static ref LOCALES: Vec<String> = build_locale_list();
25+
static ref LOCALES: Vec<&'static str> = RESOURCES.iter().map(|(l, _)| &**l).collect();
26+
static ref FALLBACKS: HashMap<String, Vec<String>> = build_fallbacks();
2627
}
2728

28-
pub struct Fallback<'res> {
29-
default: Option<&'res str>,
30-
availables: &'res Vec<String>,
31-
}
32-
33-
impl<'res> Fallback<'res> {
34-
pub fn new(available_locales: &'res Vec<String>) -> Self {
35-
Self {
36-
default: Some("en-US"),
37-
availables: available_locales,
38-
}
39-
}
40-
41-
pub fn order<'t, T: AsRef<str>>(&'t self, targets: &'t [T]) -> Vec<&'t str> {
42-
negotiate_languages(
43-
targets,
44-
&self.availables,
45-
self.default,
46-
&fluent_locale::NegotiationStrategy::Filtering,
47-
)
48-
}
29+
pub fn build_fallbacks() -> HashMap<String, Vec<String>> {
30+
LOCALES
31+
.iter()
32+
.map(|locale| {
33+
(
34+
locale.to_string(),
35+
negotiate_languages(
36+
&[locale],
37+
&LOCALES,
38+
None,
39+
&fluent_locale::NegotiationStrategy::Filtering,
40+
)
41+
.into_iter()
42+
.map(|x| x.to_string())
43+
.collect(),
44+
)
45+
})
46+
.collect()
4947
}
5048

5149
pub struct I18NHelper {
5250
bundles: &'static HashMap<String, FluentBundle<'static>>,
53-
fallback: Fallback<'static>,
51+
fallbacks: &'static HashMap<String, Vec<String>>,
5452
}
5553

5654
impl I18NHelper {
5755
pub fn new() -> Self {
5856
Self {
5957
bundles: &*BUNDLES,
60-
fallback: Fallback::new(&*LOCALES),
58+
fallbacks: &*FALLBACKS,
6159
}
6260
}
6361

64-
pub fn lookup(
62+
pub fn lookup_single_language(
6563
&self,
6664
lang: &str,
6765
text_id: &str,
@@ -83,19 +81,42 @@ impl I18NHelper {
8381
panic!("Unknown language {}", lang)
8482
}
8583
}
86-
pub fn lookup_with_fallback(
84+
85+
// Traverse the fallback chain,
86+
pub fn lookup(
8787
&self,
8888
lang: &str,
8989
text_id: &str,
9090
args: Option<&HashMap<&str, FluentValue>>,
9191
) -> String {
92-
for l in self.fallback.order(&[lang]) {
93-
if let Some(val) = self.lookup(l, text_id, args) {
92+
for l in self.fallbacks.get(lang).expect("language not found") {
93+
if let Some(val) = self.lookup_single_language(l, text_id, args) {
94+
return val;
95+
}
96+
}
97+
if lang != "en-US" {
98+
if let Some(val) = self.lookup_single_language("en-US", text_id, args) {
9499
return val;
95100
}
96101
}
97102
format!("Unknown localization {}", text_id)
98103
}
104+
105+
// Don't fall back to English
106+
pub fn lookup_no_english(
107+
&self,
108+
lang: &str,
109+
text_id: &str,
110+
args: Option<&HashMap<&str, FluentValue>>,
111+
) -> Option<String> {
112+
for l in self.fallbacks.get(lang).expect("language not found") {
113+
if let Some(val) = self.lookup_single_language(l, text_id, args) {
114+
return Some(val);
115+
}
116+
}
117+
118+
None
119+
}
99120
}
100121

101122
#[derive(Default)]
@@ -197,7 +218,7 @@ impl HelperDef for I18NHelper {
197218
.as_bool()
198219
.expect("Pontoon must be boolean");
199220

200-
let response = self.lookup_with_fallback(lang, &id, args.as_ref());
221+
let response = self.lookup(lang, &id, args.as_ref());
201222
if pontoon {
202223
out.write(&format!("<span data-l10n-id='{}'>", id))
203224
.map_err(RenderError::with)?;
@@ -288,7 +309,7 @@ impl HelperDef for TeamHelper {
288309
if lang == "en-US" {
289310
let english = team["website_data"][id].as_str().unwrap();
290311
out.write(&english).map_err(RenderError::with)?;
291-
} else if let Some(value) = self.i18n.lookup(lang, &fluent_id, None) {
312+
} else if let Some(value) = self.i18n.lookup_no_english(lang, &fluent_id, None) {
292313
out.write(&value).map_err(RenderError::with)?;
293314
} else {
294315
let english = team["website_data"][id].as_str().unwrap();
@@ -334,14 +355,6 @@ pub fn create_bundle(lang: &str, resources: &'static Vec<FluentResource>) -> Flu
334355
bundle
335356
}
336357

337-
fn build_locale_list() -> Vec<String> {
338-
let mut locale_list = Vec::new();
339-
for key in RESOURCES.keys() {
340-
locale_list.push(key.clone());
341-
}
342-
locale_list
343-
}
344-
345358
fn build_resources() -> HashMap<String, Vec<FluentResource>> {
346359
let mut all_resources = HashMap::new();
347360
let entries = read_dir("./locales").unwrap();

0 commit comments

Comments
 (0)