langcodec_cli/transformers/
yaml_language_map.rs

1use std::collections::HashMap;
2
3use langcodec::{Entry, EntryStatus, Metadata, Resource, Translation};
4
5/// Transform a YAML language map file into Resources.
6///
7/// Expected format:
8/// ```yaml
9/// key: hello_world
10/// en: Hello, World!
11/// fr: Bonjour, le monde!
12/// ```
13pub fn transform(input: String) -> Result<Vec<Resource>, String> {
14    let file_content = match std::fs::read_to_string(&input) {
15        Ok(content) => content,
16        Err(e) => return Err(format!("Error reading file {}: {}", input, e)),
17    };
18
19    // Try to parse as YAML
20    let yaml_object: HashMap<String, String> = match serde_yaml::from_str(&file_content) {
21        Ok(obj) => obj,
22        Err(e) => {
23            return Err(format!(
24                "Error parsing YAML from {}: {}. Expected format: {{\"en\": \"Hello\", \"fr\": \"Bonjour\"}}",
25                input, e
26            ));
27        }
28    };
29
30    if yaml_object.is_empty() {
31        return Err("Error: YAML object is empty".to_string());
32    }
33
34    // Find the localization key
35    // Priority: "key" field > "en" field > first field value
36    let localization_key = yaml_object.get("key").unwrap_or(
37        yaml_object
38            .get("en")
39            .unwrap_or(yaml_object.iter().next().unwrap().1),
40    );
41
42    let mut resources = Vec::new();
43
44    for (lang_code, value) in yaml_object.iter() {
45        // Skip the "key" field as it's not a language code
46        if lang_code == "key" {
47            continue;
48        }
49
50        let mut metadata_custom: HashMap<String, String> = HashMap::new();
51        metadata_custom.insert("source_language".to_string(), "en".to_string());
52        metadata_custom.insert("version".to_string(), "1.0".to_string());
53        metadata_custom.insert("format".to_string(), "YAMLLanguageMap".to_string());
54
55        let metadata = Metadata {
56            language: lang_code.clone(),
57            domain: "".to_string(),
58            custom: metadata_custom,
59        };
60
61        let mut entry_custom = HashMap::new();
62        entry_custom.insert("extraction_state".to_string(), "manual".to_string());
63
64        let entry = Entry {
65            id: localization_key.clone(),
66            value: Translation::Singular(value.clone()),
67            status: EntryStatus::NeedsReview,
68            comment: None,
69            custom: entry_custom,
70        };
71
72        resources.push(Resource {
73            metadata,
74            entries: vec![entry],
75        });
76    }
77
78    Ok(resources)
79}