Return result from i18n
This commit is contained in:
parent
c48781c40f
commit
67ee20d0bb
83
src/i18n.rs
83
src/i18n.rs
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use fluent_bundle::FluentResource;
|
use fluent_bundle::{FluentError, FluentResource};
|
||||||
use fluent_bundle::concurrent::FluentBundle;
|
use fluent_bundle::concurrent::FluentBundle;
|
||||||
use unic_langid::LanguageIdentifier;
|
use unic_langid::LanguageIdentifier;
|
||||||
|
|
||||||
|
@ -8,19 +8,40 @@ pub struct I18n(HashMap<String, FluentBundle<FluentResource>>);
|
||||||
|
|
||||||
pub struct L10n<'a>(&'a FluentBundle<FluentResource>);
|
pub struct L10n<'a>(&'a FluentBundle<FluentResource>);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum I18nError {
|
||||||
|
// For `I18n::new`
|
||||||
|
InvalidLocale(String),
|
||||||
|
InvalidPath,
|
||||||
|
CantReadFile(String),
|
||||||
|
CantBuildResource(String),
|
||||||
|
CantAddResource(String),
|
||||||
|
|
||||||
|
// For `I18n.l10n`
|
||||||
|
NoSuchLocale(String),
|
||||||
|
|
||||||
|
// For `L10n.translate`
|
||||||
|
NoSuchTranslation(String),
|
||||||
|
InvalidTranslation(String),
|
||||||
|
FormattingFailed(Vec<FluentError>),
|
||||||
|
}
|
||||||
|
|
||||||
impl I18n {
|
impl I18n {
|
||||||
pub fn new(path: &str, locales: &[&str]) -> Result<Self, ()> {
|
pub fn new(path: &str, locales: &[&str]) -> Result<Self, I18nError> {
|
||||||
let lang_ids: Vec<Result<LanguageIdentifier, _>> =
|
let locales_and_lang_ids: Vec<(&str, Result<LanguageIdentifier, _>)> =
|
||||||
locales.iter().map(|locale| {
|
locales.iter().map(|locale| {
|
||||||
locale.parse::<LanguageIdentifier>()
|
(*locale, locale.parse::<LanguageIdentifier>())
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
if let Some(_) = lang_ids.iter().find(|lang_id| lang_id.is_err()) {
|
if let Some((locale, _)) =
|
||||||
return Err(());
|
locales_and_lang_ids.iter().find(|(_, lang_id)| lang_id.is_err())
|
||||||
|
{
|
||||||
|
return Err(I18nError::InvalidLocale(locale.to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let lang_ids: Vec<&LanguageIdentifier> =
|
let lang_ids: Vec<&LanguageIdentifier> = locales_and_lang_ids.iter()
|
||||||
lang_ids.iter().map(|lang_id| lang_id.as_ref().unwrap()).collect();
|
.map(|(_, lang_id)| lang_id.as_ref().unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
let mut hash_map = HashMap::new();
|
let mut hash_map = HashMap::new();
|
||||||
|
|
||||||
|
@ -31,20 +52,29 @@ impl I18n {
|
||||||
path_buf.push(&locale);
|
path_buf.push(&locale);
|
||||||
path_buf.set_extension("ftl");
|
path_buf.set_extension("ftl");
|
||||||
|
|
||||||
let data = match std::fs::read_to_string(path_buf) {
|
let path_str = match path_buf.to_str() {
|
||||||
|
Some(path_str) => path_str,
|
||||||
|
None => return Err(I18nError::InvalidPath),
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = match std::fs::read_to_string(path_str) {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(_) => return Err(()),
|
Err(_) => return Err(I18nError::CantReadFile(
|
||||||
|
path_str.to_string(),
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let resource = match FluentResource::try_new(data) {
|
let resource = match FluentResource::try_new(data) {
|
||||||
Ok(resource) => resource,
|
Ok(resource) => resource,
|
||||||
Err(_) => return Err(()),
|
Err(_) => return Err(I18nError::CantBuildResource(
|
||||||
|
path_str.to_string(),
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bundle = FluentBundle::default();
|
let mut bundle = FluentBundle::default();
|
||||||
|
|
||||||
if let Err(_) = bundle.add_resource(resource) {
|
if let Err(_) = bundle.add_resource(resource) {
|
||||||
return Err(());
|
return Err(I18nError::CantAddResource(path_str.to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
hash_map.insert(locale, bundle);
|
hash_map.insert(locale, bundle);
|
||||||
|
@ -53,19 +83,34 @@ impl I18n {
|
||||||
Ok(Self(hash_map))
|
Ok(Self(hash_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn l10n<'a>(&'a self, locale: &'a str) -> Option<L10n<'a>> {
|
pub fn l10n<'a>(&'a self, locale: &'a str) -> Result<L10n<'a>, I18nError> {
|
||||||
match self.0.get(locale) {
|
match self.0.get(locale) {
|
||||||
None => None,
|
None => Err(I18nError::NoSuchLocale(locale.to_string())),
|
||||||
Some(bundle) => Some(L10n(bundle)),
|
Some(bundle) => Ok(L10n(bundle)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl L10n<'_> {
|
impl L10n<'_> {
|
||||||
pub fn dummy_translate(&self, key: &str) -> String {
|
pub fn translate(&self, key: &str) -> Result<String, I18nError> {
|
||||||
let msg = self.0.get_message(key).unwrap();
|
let msg = match self.0.get_message(key) {
|
||||||
let val = msg.value.unwrap();
|
None => return Err(I18nError::NoSuchTranslation(key.to_string())),
|
||||||
|
Some(msg) => msg,
|
||||||
|
};
|
||||||
|
|
||||||
|
let val = match msg.value {
|
||||||
|
None => return Err(I18nError::InvalidTranslation(key.to_string())),
|
||||||
|
Some(val) => val,
|
||||||
|
};
|
||||||
|
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
self.0.format_pattern(val, None, &mut errors).to_string()
|
|
||||||
|
let out = self.0.format_pattern(val, None, &mut errors).to_string();
|
||||||
|
|
||||||
|
if !errors.is_empty() {
|
||||||
|
return Err(I18nError::FormattingFailed(errors));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ pub fn index(
|
||||||
let l10n = i18n.l10n("en").unwrap();
|
let l10n = i18n.l10n("en").unwrap();
|
||||||
|
|
||||||
let page_context = views::home::Index {
|
let page_context = views::home::Index {
|
||||||
i18n_fedihub: l10n.dummy_translate("fedihub"),
|
i18n_fedihub: l10n.translate("fedihub").unwrap(),
|
||||||
i18n_federated_services_without_censorship: l10n.dummy_translate("federated-services-without-censorship"),
|
i18n_federated_services_without_censorship: l10n.translate("federated-services-without-censorship").unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let context = views::Site {
|
let context = views::Site {
|
||||||
|
|
|
@ -12,7 +12,10 @@ pub fn rocket(config: &config::Config) -> Result<rocket::Rocket, ()> {
|
||||||
let public_path = config.public_path()?;
|
let public_path = config.public_path()?;
|
||||||
let locales_path = config.locales_path()?;
|
let locales_path = config.locales_path()?;
|
||||||
|
|
||||||
let i18n = I18n::new(&locales_path, &["en", "ru"])?;
|
let i18n = match I18n::new(&locales_path, &["en", "ru"]) {
|
||||||
|
Err(_) => return Err(()),
|
||||||
|
Ok(i18n) => i18n,
|
||||||
|
};
|
||||||
|
|
||||||
let result = rocket::custom(rocket_config)
|
let result = rocket::custom(rocket_config)
|
||||||
.manage(i18n)
|
.manage(i18n)
|
||||||
|
|
Reference in New Issue