Start setting up a stack of fluent bundles and dynamic file loading
This commit is contained in:
parent
034bda502a
commit
5c7f7766de
|
@ -2734,9 +2734,11 @@ dependencies = [
|
|||
"icu",
|
||||
"icu_locid",
|
||||
"icu_provider",
|
||||
"intl-memoizer",
|
||||
"serde 1.0.193",
|
||||
"serde_yaml",
|
||||
"sys-locale",
|
||||
"thiserror",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
|
|
|
@ -15,9 +15,11 @@ fluent = { version = "0.16" }
|
|||
icu_locid = { version = "1" }
|
||||
icu_provider = { version = "1" }
|
||||
icu = { version = "1" }
|
||||
intl-memoizer = { version = "*" }
|
||||
serde = { version = "1", features = [ "derive" ] }
|
||||
serde_yaml = { version = "0.9" }
|
||||
sys-locale = { version = "0.3" }
|
||||
thiserror = { version = "1" }
|
||||
unic-langid = { version = "*" }
|
||||
|
||||
[[bin]]
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use chrono::{Datelike, NaiveDate, Timelike};
|
||||
use chrono_tz::Tz;
|
||||
use fixed_decimal::FixedDecimal;
|
||||
use fluent::{FluentBundle, FluentResource};
|
||||
use fluent_ergonomics::FluentErgo;
|
||||
use fluent::{bundle::FluentBundle, FluentResource};
|
||||
use icu::{datetime::options::length, decimal::FixedDecimalFormatter, locid::Locale};
|
||||
use icu_provider::DataLocale;
|
||||
use std::{collections::HashMap, ops::Deref, path::Path};
|
||||
use std::{fs::File, io::Read, ops::Deref};
|
||||
use sys_locale::get_locale;
|
||||
use thiserror::Error;
|
||||
use unic_langid::LanguageIdentifierError;
|
||||
|
||||
// Re-exports. I'm doing these so that clients of this library don't have to go tracking down
|
||||
// additional structures
|
||||
|
@ -46,7 +47,9 @@ impl<A> Deref for NonEmptyList<A> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum L10NError {
|
||||
#[error("Unparsable Locale")]
|
||||
UnparsableLocale,
|
||||
}
|
||||
|
||||
|
@ -56,6 +59,33 @@ impl From<icu::locid::Error> for L10NError {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FileLoadError {
|
||||
#[error("Unparsable Locale")]
|
||||
UnparsableLocale,
|
||||
|
||||
#[error("Source string file not found")]
|
||||
FileNotFound,
|
||||
|
||||
#[error("The Fluent file is malformed")]
|
||||
FluentParseError,
|
||||
|
||||
#[error("An unknown IO error was found")]
|
||||
IOError(std::io::Error),
|
||||
}
|
||||
|
||||
impl From<LanguageIdentifierError> for FileLoadError {
|
||||
fn from(_: LanguageIdentifierError) -> Self {
|
||||
Self::UnparsableLocale
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for FileLoadError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
Self::IOError(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Potential Message structure.
|
||||
//
|
||||
// Let's assume the application has an enumeration that implements Message. For each element of the
|
||||
|
@ -74,7 +104,7 @@ pub trait Message {
|
|||
|
||||
pub struct L10N {
|
||||
messages_root: std::path::PathBuf,
|
||||
message_bundles: Vec<FluentBundle<FluentResource>>,
|
||||
message_bundles: Vec<FluentBundle<FluentResource, intl_memoizer::concurrent::IntlLangMemoizer>>,
|
||||
|
||||
locales: NonEmptyList<Locale>,
|
||||
zone: chrono_tz::Tz,
|
||||
|
@ -95,34 +125,39 @@ impl L10N {
|
|||
let english_phrases = FluentResource::try_new
|
||||
*/
|
||||
|
||||
let message_bundles = {
|
||||
/*
|
||||
let mut english_messages = messages_root.clone();
|
||||
english_messages.push("en-US.ftl");
|
||||
|
||||
let langid: unic_langid::LanguageIdentifier = english.to_string().parse().unwrap();
|
||||
let mut messages = FluentErgo::new(&[langid.clone()]);
|
||||
let _ = messages.add_from_file(langid, &english_messages);
|
||||
|
||||
vec![messages]
|
||||
*/
|
||||
vec![]
|
||||
};
|
||||
|
||||
Self {
|
||||
let mut s = Self {
|
||||
messages_root,
|
||||
message_bundles,
|
||||
message_bundles: vec![],
|
||||
locales,
|
||||
zone,
|
||||
}
|
||||
};
|
||||
|
||||
s.load_messages_from_file("en-US".to_owned()).unwrap();
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
pub fn load_messages_from_file(
|
||||
&mut self,
|
||||
locale: String,
|
||||
path: &Path,
|
||||
) -> Result<(), L10NError> {
|
||||
unimplemented!()
|
||||
fn load_messages_from_file(&mut self, locale: String) -> Result<(), FileLoadError> {
|
||||
let langid: unic_langid::LanguageIdentifier = locale.parse()?;
|
||||
|
||||
let mut path = self.messages_root.clone();
|
||||
path.push(locale);
|
||||
path.set_extension("ftl");
|
||||
println!("{:?}", path);
|
||||
|
||||
let mut buffer = Vec::new();
|
||||
let mut f = File::open(path)?;
|
||||
f.read_to_end(&mut buffer)?;
|
||||
let text = String::from_utf8(buffer).unwrap();
|
||||
match FluentResource::try_new(text) {
|
||||
Ok(resource) => {
|
||||
let mut bundle = FluentBundle::new_concurrent(vec![langid]);
|
||||
let _ = bundle.add_resource(resource);
|
||||
self.message_bundles.push(bundle);
|
||||
Ok(())
|
||||
}
|
||||
Err((_, _error)) => Err(FileLoadError::FluentParseError),
|
||||
}
|
||||
}
|
||||
|
||||
// Now, whenever the user changes the locales, the list of messages has to change. How do we
|
||||
|
@ -165,9 +200,15 @@ impl L10N {
|
|||
// }
|
||||
|
||||
pub fn tr(&self, message: impl Message) -> String {
|
||||
let msg = self.message_bundles[0].get_message(message.msgid()).and_then(|msg| msg.value()).unwrap();
|
||||
println!("message: {}", message.msgid());
|
||||
let msg = self.message_bundles[0]
|
||||
.get_message(message.msgid())
|
||||
.and_then(|msg| msg.value())
|
||||
.unwrap();
|
||||
let mut errors = vec![];
|
||||
self.message_bundles[0].format_pattern(msg, message.args().as_ref(), &mut errors).to_string()
|
||||
self.message_bundles[0]
|
||||
.format_pattern(msg, message.args().as_ref(), &mut errors)
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn format_date_time_utc(
|
||||
|
|
Loading…
Reference in New Issue