diff --git a/Cargo.lock b/Cargo.lock index 3d2918630..33e9389ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2087,6 +2087,7 @@ version = "0.1.0" dependencies = [ "fluent 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "fluent-bundle 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fluent-locale 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "fluent-syntax 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index c000f38d3..3ba236b8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ lazy_static = "1.2.0" fluent = "0.5" fluent-bundle = "0.6.0" fluent-syntax = "0.9.0" +fluent-locale = "0.4.1" rand = "0.6" regex = "1" rocket = "0.4.1" diff --git a/src/i18n.rs b/src/i18n.rs index 30b021d5c..3ca2ebaf0 100644 --- a/src/i18n.rs +++ b/src/i18n.rs @@ -15,19 +15,48 @@ use std::io::prelude::*; use std::path::Path; use fluent_bundle::{FluentBundle, FluentResource, FluentValue}; +use fluent_locale::negotiate_languages; lazy_static! { static ref RESOURCES: HashMap> = build_resources(); static ref BUNDLES: HashMap> = build_bundles(); + static ref LOCALES: Vec = build_locale_list(); +} + +pub struct Fallback<'res> { + default: Option<&'res str>, + availables: &'res Vec, +} + +impl<'res> Fallback<'res> { + pub fn new(available_locales: &'res Vec) -> Self { + Self { + default: Some("en-US"), + availables: available_locales, + } + } + + pub fn order<'t, T: AsRef>(&'t self, targets: &'t [T]) -> Vec<&'t str> { + negotiate_languages( + targets, + &self.availables, + self.default, + &fluent_locale::NegotiationStrategy::Filtering, + ) + } } pub struct I18NHelper { bundles: &'static HashMap>, + fallback: Fallback<'static>, } impl I18NHelper { pub fn new() -> Self { - Self { bundles: &*BUNDLES } + Self { + bundles: &*BUNDLES, + fallback: Fallback::new(&*LOCALES), + } } pub fn lookup( @@ -58,17 +87,12 @@ impl I18NHelper { text_id: &str, args: Option<&HashMap<&str, FluentValue>>, ) -> String { - if let Some(val) = self.lookup(lang, text_id, args) { - val - } else if lang != "en-US" { - if let Some(val) = self.lookup("en-US", text_id, args) { - val - } else { - format!("Unknown localization {}", text_id) + for l in self.fallback.order(&[lang]) { + if let Some(val) = self.lookup(l, text_id, args) { + return val; } - } else { - format!("Unknown localization {}", text_id) } + format!("Unknown localization {}", text_id) } } @@ -284,6 +308,14 @@ pub fn create_bundle(lang: &str, resources: &'static Vec) -> Flu bundle } +fn build_locale_list() -> Vec { + let mut locale_list = Vec::new(); + for key in RESOURCES.keys() { + locale_list.push(key.clone()); + } + locale_list +} + fn build_resources() -> HashMap> { let mut all_resources = HashMap::new(); let entries = read_dir("./templates/fluent-resource").unwrap();