lib_humus/language/
manifest.rs1use std::collections::{HashMap, HashSet};
6
7use serde::{Deserialize, Serialize};
8
9use crate::language::{UnicodeLanguageIdentifier, variable_description::VariableDescription};
10
11use crate::headers::AcceptLanguageHeader;
12use crate::headers::AcceptLanguageHeaderLanguage;
13use crate::templating::HumusFormatIdentifier;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
19#[serde(deny_unknown_fields)]
20pub struct LanguageManifest {
21 #[serde(rename = "language")]
23 pub languages: HashMap<UnicodeLanguageIdentifier, LanguageDescriptor>,
24 pub default_language: UnicodeLanguageIdentifier,
26 pub available_messages: HashSet<String>,
28 #[serde(rename = "message", default)]
30 pub message_descriptions: HashMap<String, MessageDescription>,
31 #[serde(rename = "format", default)]
33 pub formats: HashMap<HumusFormatIdentifier, FormatDescriptor>,
34}
35
36impl LanguageManifest {
37 pub fn new_empty() -> Self {
39 Self {
40 default_language: unic_langid::langid!("und").into(),
41 languages: [(
42 unic_langid::langid!("und").into(),
43 LanguageDescriptor {
44 name: "Undefined".to_string(),
45 abbreviation: "UND".to_string(),
46 is_hidden: false,
47 },
48 )]
49 .into_iter()
50 .collect(),
51 available_messages: Default::default(),
52 message_descriptions: Default::default(),
53 formats: Default::default(),
54 }
55 }
56
57 pub fn has_visible_language(&self, language: &UnicodeLanguageIdentifier) -> bool {
59 self.languages
60 .get(language)
61 .map(|desc| !desc.is_hidden)
62 .unwrap_or(false)
63 }
64
65 pub fn get_best_fitting_language(
69 &self,
70 header: &AcceptLanguageHeader,
71 ) -> Option<UnicodeLanguageIdentifier> {
72 let mut best_fitting: Option<UnicodeLanguageIdentifier> = None;
73 for (l, _) in &header.languages {
74 match l {
75 AcceptLanguageHeaderLanguage::Wildcard => {
76 break;
78 }
79 AcceptLanguageHeaderLanguage::Code(code) => {
80 if let Ok(mut lang) = code.parse::<UnicodeLanguageIdentifier>() {
81 if self.has_visible_language(&lang) {
82 return Some(lang);
83 }
84 lang.script = None;
85 lang.region = None;
86 if self.has_visible_language(&lang) {
87 best_fitting = Some(lang);
88 }
89 }
90 }
91 }
92 }
93 best_fitting
94 }
95
96 pub fn get_safe_suffix_for_format(&self, format: HumusFormatIdentifier) -> Option<String> {
98 self.formats.get(&format)?.safe_suffix.clone()
99 }
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104#[serde(deny_unknown_fields)]
105pub struct LanguageDescriptor {
106 pub name: String,
112
113 pub abbreviation: String,
115
116 #[serde(default)]
122 pub is_hidden: bool,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
126#[serde(deny_unknown_fields)]
127pub struct MessageDescription {
128 #[serde(default, rename = "arg")]
129 pub arguments: HashMap<String, VariableDescription>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
134#[serde(deny_unknown_fields)]
135pub struct FormatDescriptor {
136 #[serde(default)]
138 pub safe_suffix: Option<String>,
139}