use std::{
collections::HashMap,
fs
};
use serde_json::Value;
use crate::base::{
BASE_DIR,
JEXT,
PrependErrorString
};
use crate::sys::System;
const LINGUA_DIR: &str = "lingua";
pub struct Lingua {
lang: String,
lingua_map: HashMap<String, Vec<String>>, prefix: String
}
impl Lingua {
pub fn new(sys: &System) -> Self {
let lang = sys.lang();
let lingua_map = HashMap::<String, Vec<String>>::new();
let prefix = String::new();
Self{lang, lingua_map, prefix}
}
pub fn load(&mut self, lingua_filepaths_noext: &[impl ToString]) -> Result<(), String> {
for lingua_filepath_noext in lingua_filepaths_noext {
let filepath = format!("{}/{}/{}/{}.{}", BASE_DIR, LINGUA_DIR, & self.lang, lingua_filepath_noext.to_string(), JEXT);
let b = fs::read(&filepath).pre_err(format!("cannot read '{}'", &filepath))?;
let v: Value = serde_json::from_slice(&b).pre_err(format!("cannot parse '{}'", &filepath))?;
match v.as_object() {
Some(objmap) => {
for (id, val) in objmap {
let id = id.clone();
let texts = if val.is_string() {
vec![val.as_str().unwrap().to_string()]
} else if val.is_array() {
let texts_values = val.as_array().unwrap();
let mut texts = Vec::<String>::new();
for sv in texts_values {
match sv.as_str() {
Some(text) => {
texts.push(text.to_string());
},
None => {
return Err(format!("cannot load '{}': array-value of id-key '{}' contains not only strings, ({:?})", &filepath, &id, sv))
}
}
}
texts
} else {
return Err(format!("cannot load '{}': value of id-key '{}' is neither a string, nor an array of strings", &filepath, &id));
};
let prefixed_id = format!("{}:{}", lingua_filepath_noext.to_string(), &id);
match self.lingua_map.insert(prefixed_id.clone(), texts) {
Some(..) => return Err(format!("cannot load '{}': id-key '{}' exists already", &filepath, &prefixed_id)),
None => {}
};
}
},
None => return Err(format!("cannot load '{}': content is not a json object", &filepath))
}
}
Ok(())
}
pub fn set_prefix(&mut self, prefix: impl ToString) {
self.prefix = format!("{}:", prefix.to_string());
}
pub fn clear_prefix(&mut self) {
self.prefix.clear();
}
#[allow(dead_code)]
pub fn get1(&self, id: impl ToString) -> Option<String> {
let id = format!("{}{}", &self.prefix, id.to_string());
self.lingua_map.get(&id).map(|texts| texts[0].clone())
}
#[allow(dead_code)]
pub fn get1_or_echo(&self, id: impl ToString) -> String {
let prefixed_id = format!("{}{}", &self.prefix, id.to_string());
self.get1(id).unwrap_or_else(|| format!("{{{}}}", &prefixed_id)) }
#[allow(dead_code)]
pub fn get(&self, id: impl ToString) -> Option<Vec<String>> {
let id = format!("{}{}", &self.prefix, id.to_string());
self.lingua_map.get(&id).map(|texts| texts.clone())
}
#[allow(dead_code)]
pub fn get_or_echo(&self, id: impl ToString) -> Vec<String> {
let prefixed_id = format!("{}{}", &self.prefix, id.to_string());
self.get(id).unwrap_or_else(|| vec![format!("{{{} 0}}", &prefixed_id)]) }
}