use std::collections::{HashMap, HashSet};
use serde::{Deserialize, Serialize};
use crate::language::{UnicodeLanguageIdentifier, variable_description::VariableDescription};
use crate::headers::AcceptLanguageHeader;
use crate::headers::AcceptLanguageHeaderLanguage;
use crate::templating::HumusFormatIdentifier;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LanguageManifest {
#[serde(rename = "language")]
pub languages: HashMap<UnicodeLanguageIdentifier, LanguageDescriptor>,
pub default_language: UnicodeLanguageIdentifier,
pub available_messages: HashSet<String>,
#[serde(rename = "message", default)]
pub message_descriptions: HashMap<String, MessageDescription>,
#[serde(rename = "format", default)]
pub formats: HashMap<HumusFormatIdentifier, FormatDescriptor>,
}
impl LanguageManifest {
pub fn new_empty() -> Self {
Self {
default_language: unic_langid::langid!("und").into(),
languages: [(
unic_langid::langid!("und").into(),
LanguageDescriptor {
name: "Undefined".to_string(),
abbreviation: "UND".to_string(),
is_hidden: false,
},
)]
.into_iter()
.collect(),
available_messages: Default::default(),
message_descriptions: Default::default(),
formats: Default::default(),
}
}
pub fn has_visible_language(&self, language: &UnicodeLanguageIdentifier) -> bool {
self.languages
.get(language)
.map(|desc| !desc.is_hidden)
.unwrap_or(false)
}
pub fn get_best_fitting_language(
&self,
header: &AcceptLanguageHeader,
) -> Option<UnicodeLanguageIdentifier> {
let mut best_fitting: Option<UnicodeLanguageIdentifier> = None;
for (l, _) in &header.languages {
match l {
AcceptLanguageHeaderLanguage::Wildcard => {
break;
}
AcceptLanguageHeaderLanguage::Code(code) => {
if let Ok(mut lang) = code.parse::<UnicodeLanguageIdentifier>() {
if self.has_visible_language(&lang) {
return Some(lang);
}
lang.script = None;
lang.region = None;
if self.has_visible_language(&lang) {
best_fitting = Some(lang);
}
}
}
}
}
best_fitting
}
pub fn get_safe_suffix_for_format(&self, format: HumusFormatIdentifier) -> Option<String> {
self.formats.get(&format)?.safe_suffix.clone()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LanguageDescriptor {
pub name: String,
pub abbreviation: String,
#[serde(default)]
pub is_hidden: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct MessageDescription {
#[serde(default, rename = "arg")]
pub arguments: HashMap<String, VariableDescription>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct FormatDescriptor {
#[serde(default)]
pub safe_suffix: Option<String>,
}