diff --git a/demo_hornbeam_project/src/main.rs b/demo_hornbeam_project/src/main.rs index 19bb9fb..9884a74 100644 --- a/demo_hornbeam_project/src/main.rs +++ b/demo_hornbeam_project/src/main.rs @@ -38,16 +38,10 @@ async fn main() -> eyre::Result<()> { Ok(()) } -async fn say_hello(Path((_lang, name)): Path<(String, String)>) -> impl IntoResponse { - // TODO This should be translated with Fluent! - - //let template = templates.prepare("say_hello", None, Params::default().set("name", name)); - - Rendered(render_template_string!(TEMPLATING, say_hello, "en-GB", { +async fn say_hello(Path((lang, name)): Path<(String, String)>) -> impl IntoResponse { + Rendered(render_template_string!(TEMPLATING, say_hello, lang, { name: name })) - - // HtmlTemplate(template) } struct Rendered(Result); diff --git a/demo_hornbeam_project/translations/fr-FR/say_hello.ftl b/demo_hornbeam_project/translations/fr-FR/say_hello.ftl new file mode 100644 index 0000000..f528eb6 --- /dev/null +++ b/demo_hornbeam_project/translations/fr-FR/say_hello.ftl @@ -0,0 +1 @@ +hello = Bonjour { $name } ! diff --git a/hornbeam/src/interpreted.rs b/hornbeam/src/interpreted.rs index f75c640..97f2ee7 100644 --- a/hornbeam/src/interpreted.rs +++ b/hornbeam/src/interpreted.rs @@ -10,7 +10,6 @@ use hornbeam_interpreter::localisation::fluent::{ FluentLocalisationError, FluentLocalisationSystem, }; use hornbeam_interpreter::{InterpreterError, LoadedTemplates}; -use notify::Watcher; use std::convert::Infallible; use std::path::{Path, PathBuf}; @@ -23,7 +22,6 @@ pub use hornbeam_interpreter::Params; use crate::interpreted::hot_reload::start_hot_reloader; pub use lazy_static::lazy_static; -use tokio::io; #[cfg(feature = "hot_reload")] pub mod hot_reload; @@ -174,7 +172,7 @@ macro_rules! render_template_string { // TODO LOCALE { let manager = $manager.load(); - let prepared = manager.prepare(stringify!($template_name), None, $crate::interpreter_params!{ $($params)* }); + let prepared = manager.prepare(stringify!($template_name), None, $crate::interpreter_params!{ $($params)* }, $locale); let finished_string = prepared.render_to_string(); if $crate::is_hot_reload_enabled() { // Hacky, but inject the auto-hot-reloader into the page :P diff --git a/hornbeam_interpreter/src/engine.rs b/hornbeam_interpreter/src/engine.rs index b640246..28c2928 100644 --- a/hornbeam_interpreter/src/engine.rs +++ b/hornbeam_interpreter/src/engine.rs @@ -28,6 +28,7 @@ pub(crate) struct Interpreter<'a, O, LS> { pub(crate) program: &'a BTreeMap>>, pub(crate) output: O, pub(crate) localisation: Arc, + pub(crate) locale: String, pub(crate) scopes: Vec>, } @@ -577,7 +578,7 @@ impl<'a, O: OutputSystem + Send, LS: LocalisationSystem + Sync + Send> Interpret let localised_text = self .localisation - .lookup(trans_key, ¶meters_evaluated) + .lookup(trans_key, ¶meters_evaluated, &self.locale) .map_err(|underlying| InterpreterError::Localisation { underlying, trans_key: (trans_key as &str).to_owned(), diff --git a/hornbeam_interpreter/src/interface.rs b/hornbeam_interpreter/src/interface.rs index e87bbc3..92b0e3f 100644 --- a/hornbeam_interpreter/src/interface.rs +++ b/hornbeam_interpreter/src/interface.rs @@ -24,6 +24,7 @@ pub trait LocalisationSystem { &self, trans_key: &str, params: &BTreeMap<&str, Value>, + locale: &str, ) -> Result, Self::Error>; } @@ -148,6 +149,7 @@ impl<'a, LS> LoadedTemplates { template_name: &str, fragment_name: Option<&str>, params: Params, + locale: String, ) -> PreparedTemplate { PreparedTemplate { all_instructions: Arc::new(self.template_functions.clone()), @@ -158,6 +160,7 @@ impl<'a, LS> LoadedTemplates { }, variables: params, localisation: self.localisation.clone(), + locale, } } } @@ -167,6 +170,7 @@ pub struct PreparedTemplate { pub(crate) entrypoint: String, pub(crate) variables: Params, pub(crate) localisation: Arc, + pub(crate) locale: String, } impl PreparedTemplate { @@ -179,6 +183,7 @@ impl PreparedTemplate { program: &self.all_instructions, output, localisation: self.localisation, + locale: self.locale, scopes: vec![Scope { variables: self.variables.params, slots: Default::default(), diff --git a/hornbeam_interpreter/src/localisation.rs b/hornbeam_interpreter/src/localisation.rs index e15ea48..b2324c9 100644 --- a/hornbeam_interpreter/src/localisation.rs +++ b/hornbeam_interpreter/src/localisation.rs @@ -18,6 +18,7 @@ impl LocalisationSystem for NoLocalisation { &self, _trans_key: &str, _params: &BTreeMap<&str, Value>, + _locale: &str, ) -> Result, Self::Error> { Err("No localisation support available.") } @@ -34,6 +35,7 @@ impl LocalisationSystem for DebugLocalisationSystem { &self, trans_key: &str, params: &BTreeMap<&str, Value>, + _locale: &str, ) -> Result, Self::Error> { Ok(Cow::from(format!("@{trans_key}{{{params:?}}}"))) } diff --git a/hornbeam_interpreter/src/localisation/fluent.rs b/hornbeam_interpreter/src/localisation/fluent.rs index 73343b1..1649289 100644 --- a/hornbeam_interpreter/src/localisation/fluent.rs +++ b/hornbeam_interpreter/src/localisation/fluent.rs @@ -6,7 +6,6 @@ use crate::engine::Value; use crate::interface::LocalisationSystem; use fluent_templates::fluent_bundle::types::FluentNumber; use fluent_templates::fluent_bundle::FluentValue; -use fluent_templates::loader::langid; use fluent_templates::{ArcLoader, LanguageIdentifier, Loader}; use std::borrow::Cow; use std::collections::{BTreeMap, HashMap}; @@ -60,6 +59,9 @@ pub enum FluentLocalisationError { #[error("no translation found for {trans_key} in {lang_id}")] NoTranslation { trans_key: String, lang_id: String }, + #[error("bad language ID {lang_id:?}")] + BadLocale { lang_id: String }, + #[error("can't convert param {param_name} of type {param_type} to a fluent type")] IncompatibleValue { param_name: String, @@ -74,8 +76,14 @@ impl LocalisationSystem for FluentLocalisationSystem { &self, trans_key: &str, params: &BTreeMap<&str, Value>, + locale: &str, ) -> Result, Self::Error> { - let li: LanguageIdentifier = langid!("en-GB"); // TODO get the language tag from somewhere + let li: LanguageIdentifier = + LanguageIdentifier::from_bytes(locale.as_bytes()).map_err(|_| { + FluentLocalisationError::BadLocale { + lang_id: locale.to_owned(), + } + })?; let mut mapped_params = HashMap::with_capacity(params.len()); for (&k, v) in params { if let Some(mapped_val) = interpreter_value_to_fluent_value(v) {