use derive_more::From; use rocket_dyn_templates::tera::{self, Value}; use std::{ collections::HashMap, fs::{self, File}, io::BufReader, process::Command, }; use gettext::Catalog; #[derive(From, Debug)] pub enum LoadCatalogsError { Io(std::io::Error), Parse(gettext::Error), MissingDefaultLanguage, } const DEFAULT: &str = "ja"; pub fn load_catalogs() -> Result, LoadCatalogsError> { let mut catalogs = HashMap::new(); for file in fs::read_dir("i18n")? { let file = file?; let path = file.path(); if !file.file_type()?.is_file() || !path .extension() .map(|extension| extension.eq("po")) .unwrap_or(false) { continue; } let language_code = path .file_stem() .expect("Invalid translation file name") .to_string_lossy() .to_string(); let po_file_path = path; let mo_file_path = format!("i18n/{}.mo", language_code); Command::new("msgfmt") .arg(&po_file_path) .arg("-o") .arg(&mo_file_path) .output()?; catalogs.insert( language_code, Catalog::parse(BufReader::new(File::open(mo_file_path)?))?, ); } if !catalogs.contains_key(DEFAULT) { return Err(LoadCatalogsError::MissingDefaultLanguage); } Ok(catalogs) } pub fn i18n_filter( value: &Value, _args: &HashMap, catalogs: &HashMap, ) -> tera::Result { let key = value .as_str() .ok_or_else(|| tera::Error::msg("The translation key must be a string"))?; let translation = catalogs.get(DEFAULT).expect("Missing catalog").gettext(key); Ok(Value::String(translation.to_owned())) }