1use std::{collections::HashMap, path::Path};
6
7use super::{LocalizationBundle, NLSConfig};
8
9pub struct NLSBundle {
11 _config:NLSConfig,
12 bundles:HashMap<String, LocalizationBundle>,
14}
15
16impl NLSBundle {
17 pub fn new(config:NLSConfig) -> Self {
18 let mut bundles = HashMap::new();
19
20 for lang in &config.languages {
22 bundles.insert(lang.clone(), LocalizationBundle::new(lang));
23 }
24
25 Self { _config:config, bundles }
26 }
27
28 pub fn add_entry(&mut self, language:&str, key:impl Into<String>, value:impl Into<String>) {
30 if let Some(bundle) = self.bundles.get_mut(language) {
31 bundle.add_entry(key, value);
32 }
33 }
34
35 pub fn add_entries(&mut self, language:&str, entries:&HashMap<String, String>) {
37 if let Some(bundle) = self.bundles.get_mut(language) {
38 for (key, value) in entries {
39 bundle.add_entry(key.clone(), value.clone());
40 }
41 bundle.compute_hash();
42 }
43 }
44
45 pub fn generate(&self, output_dir:&Path) -> std::io::Result<()> {
47 use std::fs;
48
49 fs::create_dir_all(output_dir)?;
51
52 for (lang, bundle) in &self.bundles {
53 let filename = format!("{}.json", lang);
54 let path = output_dir.join(&filename);
55
56 let json =
57 serde_json::to_string_pretty(bundle).map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
58
59 fs::write(path, json)?;
60 }
61
62 Ok(())
63 }
64
65 pub fn get_bundle(&self, language:&str) -> Option<&LocalizationBundle> { self.bundles.get(language) }
67
68 pub fn all_bundles(&self) -> &HashMap<String, LocalizationBundle> { &self.bundles }
70
71 pub fn load_bundle(language:&str, path:&Path) -> std::io::Result<LocalizationBundle> {
73 let content = std::fs::read_to_string(path)?;
74 let bundle:LocalizationBundle =
75 serde_json::from_str(&content).map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
76
77 if bundle.language != language {
79 return Err(std::io::Error::new(
80 std::io::ErrorKind::InvalidData,
81 format!("Language mismatch: expected {}, got {}", language, bundle.language),
82 ));
83 }
84
85 Ok(bundle)
86 }
87
88 pub fn to_hashmap(&self, language:&str) -> HashMap<String, String> {
90 let mut map = HashMap::new();
91
92 if let Some(bundle) = self.bundles.get(language) {
93 for entry in &bundle.entries {
94 map.insert(entry.key.clone(), entry.value.clone());
95 }
96 }
97
98 map
99 }
100}
101
102pub fn generate_vscode_bundle(entries:&HashMap<String, String>, language:&str) -> LocalizationBundle {
104 let mut bundle = LocalizationBundle::new(language);
105
106 for (key, value) in entries {
107 bundle.add_entry(key, value);
108 }
109
110 bundle.compute_hash();
111 bundle
112}
113
114pub fn format_metadata(bundle:&LocalizationBundle) -> serde_json::Value {
116 let mut metadata = serde_json::Map::new();
117
118 for entry in &bundle.entries {
119 let mut item = serde_json::Map::new();
120 item.insert("value".to_string(), serde_json::Value::String(entry.value.clone()));
121
122 if let Some(comment) = &entry.comment {
123 item.insert("comment".to_string(), serde_json::Value::String(comment.clone()));
124 }
125
126 metadata.insert(entry.key.clone(), serde_json::Value::Object(item));
127 }
128
129 serde_json::Value::Object(metadata)
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_bundle_creation() {
138 let config = NLSConfig { languages:vec!["en".to_string(), "de".to_string()], ..Default::default() };
139
140 let bundle = NLSBundle::new(config);
141 assert!(bundle.get_bundle("en").is_some());
142 assert!(bundle.get_bundle("de").is_some());
143 }
144
145 #[test]
146 fn test_add_entry() {
147 let config = NLSConfig { languages:vec!["en".to_string()], ..Default::default() };
148
149 let mut bundle = NLSBundle::new(config);
150 bundle.add_entry("en", "hello", "Hello World");
151
152 let en_bundle = bundle.get_bundle("en").unwrap();
153 assert_eq!(en_bundle.entries.len(), 1);
154 assert_eq!(en_bundle.entries[0].key, "hello");
155 }
156
157 #[test]
158 fn test_to_hashmap() {
159 let config = NLSConfig { languages:vec!["en".to_string()], ..Default::default() };
160
161 let mut bundle = NLSBundle::new(config);
162 bundle.add_entry("en", "hello", "Hello World");
163
164 let map = bundle.to_hashmap("en");
165 assert_eq!(map.get("hello"), Some(&"Hello World".to_string()));
166 }
167}