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>), |     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! { | lazy_static! { | ||||||
|     static ref U8_TYPEID: TypeId = TypeId::of::<u8>(); |     static ref U8_TYPEID: TypeId = TypeId::of::<u8>(); | ||||||
|     static ref U16_TYPEID: TypeId = TypeId::of::<u16>(); |     static ref U16_TYPEID: TypeId = TypeId::of::<u16>(); | ||||||
|  | |||||||
| @ -4,19 +4,81 @@ | |||||||
| 
 | 
 | ||||||
| use crate::engine::Value; | use crate::engine::Value; | ||||||
| use crate::interface::LocalisationSystem; | 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::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 { | impl LocalisationSystem for FluentLocalisationSystem { | ||||||
|     type Error = (); |     type Error = FluentLocalisationError; | ||||||
| 
 | 
 | ||||||
|     fn lookup( |     fn lookup( | ||||||
|         &self, |         &self, | ||||||
|         trans_key: &str, |         trans_key: &str, | ||||||
|         params: &BTreeMap<&str, Value>, |         params: &BTreeMap<&str, Value>, | ||||||
|     ) -> Result<Cow<str>, Self::Error> { |     ) -> 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user