Skip to content

Commit a49912e

Browse files
authored
Merge pull request #829 from Manishearth/fallback
Support language fallback
2 parents 52145c4 + 0d14185 commit a49912e

File tree

3 files changed

+61
-14
lines changed

3 files changed

+61
-14
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: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,51 @@ 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 CORE_RESOURCE: FluentResource =
2122
read_from_file("./locales/core.ftl").expect("cannot find core.ftl");
2223
static ref RESOURCES: HashMap<String, Vec<FluentResource>> = build_resources();
2324
static ref BUNDLES: HashMap<String, FluentBundle<'static>> = build_bundles();
25+
static ref LOCALES: Vec<&'static str> = RESOURCES.iter().map(|(l, _)| &**l).collect();
26+
static ref FALLBACKS: HashMap<String, Vec<String>> = build_fallbacks();
27+
}
28+
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()
2447
}
2548

2649
pub struct I18NHelper {
2750
bundles: &'static HashMap<String, FluentBundle<'static>>,
51+
fallbacks: &'static HashMap<String, Vec<String>>,
2852
}
2953

3054
impl I18NHelper {
3155
pub fn new() -> Self {
32-
Self { bundles: &*BUNDLES }
56+
Self {
57+
bundles: &*BUNDLES,
58+
fallbacks: &*FALLBACKS,
59+
}
3360
}
3461

35-
pub fn lookup(
62+
pub fn lookup_single_language(
3663
&self,
3764
lang: &str,
3865
text_id: &str,
@@ -54,23 +81,41 @@ impl I18NHelper {
5481
panic!("Unknown language {}", lang)
5582
}
5683
}
57-
pub fn lookup_with_fallback(
84+
85+
// Traverse the fallback chain,
86+
pub fn lookup(
5887
&self,
5988
lang: &str,
6089
text_id: &str,
6190
args: Option<&HashMap<&str, FluentValue>>,
6291
) -> String {
63-
if let Some(val) = self.lookup(lang, text_id, args) {
64-
val
65-
} else if lang != "en-US" {
66-
if let Some(val) = self.lookup("en-US", text_id, args) {
67-
val
68-
} else {
69-
format!("Unknown localization {}", text_id)
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) {
99+
return val;
70100
}
71-
} else {
72-
format!("Unknown localization {}", text_id)
73101
}
102+
format!("Unknown localization {}", text_id)
103+
}
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
74119
}
75120
}
76121

@@ -173,7 +218,7 @@ impl HelperDef for I18NHelper {
173218
.as_bool()
174219
.expect("Pontoon must be boolean");
175220

176-
let response = self.lookup_with_fallback(lang, &id, args.as_ref());
221+
let response = self.lookup(lang, &id, args.as_ref());
177222
if pontoon {
178223
out.write(&format!("<span data-l10n-id='{}'>", id))
179224
.map_err(RenderError::with)?;
@@ -264,7 +309,7 @@ impl HelperDef for TeamHelper {
264309
if lang == "en-US" {
265310
let english = team["website_data"][id].as_str().unwrap();
266311
out.write(&english).map_err(RenderError::with)?;
267-
} 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) {
268313
out.write(&value).map_err(RenderError::with)?;
269314
} else {
270315
let english = team["website_data"][id].as_str().unwrap();

0 commit comments

Comments
 (0)