Implement most of the fluent localisation system
This commit is contained in:
parent
0370de40a1
commit
475f9bc55e
|
@ -40,6 +40,18 @@ pub enum Value {
|
|||
Reflective(Box<dyn Reflect>),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn get_type_name(&self) -> String {
|
||||
String::from(match self {
|
||||
Value::Str(_) => "Str",
|
||||
Value::Int(_) => "Int",
|
||||
Value::Bool(_) => "Bool",
|
||||
Value::List(_) => "List",
|
||||
Value::Reflective(reflective) => reflective.type_name(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref U8_TYPEID: TypeId = TypeId::of::<u8>();
|
||||
static ref U16_TYPEID: TypeId = TypeId::of::<u16>();
|
||||
|
|
|
@ -4,19 +4,81 @@
|
|||
|
||||
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;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
pub struct FluentLocalisationSystem {}
|
||||
use thiserror::Error;
|
||||
|
||||
fn interpreter_value_to_fluent_value(v: &Value) -> Option<FluentValue> {
|
||||
match v {
|
||||
Value::Str(str) => Some(FluentValue::String(Cow::Borrowed(&str))),
|
||||
Value::Int(int) => {
|
||||
// This is an unstyled number
|
||||
// TODO Support fancier numbers
|
||||
Some(FluentValue::Number(FluentNumber::from(int)))
|
||||
}
|
||||
Value::Bool(_) => {
|
||||
// TODO I can't believe there's no way to expose this to fluent!
|
||||
None
|
||||
}
|
||||
Value::List(_) => None,
|
||||
Value::Reflective(_) => None,
|
||||
}
|
||||
// TODO It might be good to support a `struct` type here with fancier numbers
|
||||
// or to support FluentNumber types directly, then expose functions to Hornbeam
|
||||
// templates to create them?
|
||||
}
|
||||
|
||||
pub struct FluentLocalisationSystem {
|
||||
pub fluent: ArcLoader,
|
||||
}
|
||||
|
||||
impl FluentLocalisationSystem {}
|
||||
|
||||
#[derive(Error, Clone, Debug)]
|
||||
pub enum FluentLocalisationError {
|
||||
#[error("no translation found for {trans_key} in {lang_id}")]
|
||||
NoTranslation { trans_key: String, lang_id: String },
|
||||
|
||||
#[error("can't convert param {param_name} of type {param_type} to a fluent type")]
|
||||
IncompatibleValue {
|
||||
param_name: String,
|
||||
param_type: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl LocalisationSystem for FluentLocalisationSystem {
|
||||
type Error = ();
|
||||
type Error = FluentLocalisationError;
|
||||
|
||||
fn lookup(
|
||||
&self,
|
||||
trans_key: &str,
|
||||
params: &BTreeMap<&str, Value>,
|
||||
) -> Result<Cow<str>, Self::Error> {
|
||||
todo!()
|
||||
let li: LanguageIdentifier = langid!("en-GB"); // TODO get the language tag from somewhere
|
||||
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) {
|
||||
mapped_params.insert(k, mapped_val);
|
||||
} else {
|
||||
return Err(FluentLocalisationError::IncompatibleValue {
|
||||
param_name: String::from(k),
|
||||
param_type: v.get_type_name(),
|
||||
});
|
||||
}
|
||||
}
|
||||
match self.fluent.lookup_with_args(&li, trans_key, &mapped_params) {
|
||||
Some(val) => Ok(Cow::Owned(val)),
|
||||
None => {
|
||||
return Err(FluentLocalisationError::NoTranslation {
|
||||
trans_key: String::from(trans_key),
|
||||
lang_id: li.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue