diff options
Diffstat (limited to 'locale/tools/src')
| -rw-r--r-- | locale/tools/src/main.rs | 161 | 
1 files changed, 161 insertions, 0 deletions
diff --git a/locale/tools/src/main.rs b/locale/tools/src/main.rs new file mode 100644 index 00000000..017d9d74 --- /dev/null +++ b/locale/tools/src/main.rs @@ -0,0 +1,161 @@ +#![feature(iterator_try_collect)] +use anyhow::{anyhow, Context, Result}; +use clap::Parser; +use std::{ +    collections::BTreeMap, +    fs::{read_to_string, File}, +    io::Write, +    path::PathBuf, +}; + +#[derive(Parser)] +enum Args { +    ImportOldPot { +        input: PathBuf, +        output: PathBuf, +    }, +    ImportOldPo { +        reference: PathBuf, +        input: PathBuf, +        output: PathBuf, +    }, +} + +fn main() -> Result<()> { +    let args = Args::parse(); +    match args { +        Args::ImportOldPo { +            reference, +            input, +            output, +        } => { +            let reference = read_to_string(reference)?; +            let input = read_to_string(input)?; + +            let id_reverse = reference +                .lines() +                .skip(1) +                .map(|l| { +                    l.split_once("=") +                        .map(|(k, v)| (v, k)) +                        .ok_or(anyhow!("invalid ini")) +                }) +                .try_collect::<BTreeMap<&str, &str>>()?; + +            let mut outmap = BTreeMap::new(); +            let mut mode = 0; +            let mut msgid = String::new(); +            let mut msgstr = String::new(); +            for (i, mut line) in input.lines().enumerate() { +                if line.starts_with("#") { +                    continue; +                } +                if line.is_empty() { +                    continue; +                } +                if let Some(rest) = line.strip_prefix("msgid ") { +                    if !msgid.is_empty() { +                        if let Some(id) = id_reverse.get(&msgid.as_str()) { +                            outmap.insert(id.to_owned(), msgstr.clone()); +                        } else { +                            eprintln!("warning: message id {msgid:?} is unknown") +                        } +                    } +                    line = rest; +                    msgid = String::new(); +                    mode = 1; +                } else if let Some(rest) = line.strip_prefix("msgstr ") { +                    line = rest; +                    msgstr = String::new(); +                    mode = 2; +                } else if let Some(_) = line.strip_prefix("msgctxt ") { +                    mode = 0; +                    eprintln!("warning: msgctxt not implemented (line {})", i + 1); +                    continue; +                } +                let frag = +                    serde_json::from_str::<String>(line).context(anyhow!("line {}", i + 1))?; +                match mode { +                    0 => (), +                    1 => msgid.push_str(&frag), +                    2 => msgstr.push_str(&frag), +                    _ => unreachable!(), +                }; +            } + +            File::create(output)?.write_all( +                format!( +                    "[hurrycurry]\n{}", +                    outmap +                        .into_iter() +                        .map(|(k, v)| format!("{k}={v}\n")) +                        .collect::<String>() +                ) +                .as_bytes(), +            )?; + +            Ok(()) +        } +        Args::ImportOldPot { input, output } => { +            let output_raw = read_to_string(&output).unwrap_or("".to_owned()); +            let input = read_to_string(input)?; + +            let mut output_flip = output_raw +                .lines() +                .skip(1) +                .map(|l| { +                    l.split_once("=") +                        .map(|(k, v)| (v.to_owned(), k.to_owned())) +                        .ok_or(anyhow!("invalid ini")) +                }) +                .try_collect::<BTreeMap<String, String>>()?; + +            let mut id = false; +            let mut msgid = String::new(); +            for (i, mut line) in input.lines().enumerate() { +                if line.starts_with("#") { +                    continue; +                } +                if line.is_empty() { +                    continue; +                } +                if let Some(rest) = line.strip_prefix("msgid ") { +                    if !msgid.is_empty() { +                        if !output_flip.contains_key(&msgid) { +                            output_flip.insert(msgid.replace("\n", "\\n"), format!("unknown{i}")); +                        } +                    } +                    line = rest; +                    id = true; +                    msgid = String::new(); +                } else if line.starts_with("msgctxt ") || line.starts_with("msgstr ") { +                    id = false; +                    continue; +                } +                if id { +                    let frag = +                        serde_json::from_str::<String>(line).context(anyhow!("line {}", i + 1))?; +                    msgid.push_str(frag.as_str()); +                } +            } + +            let output_unflip = output_flip +                .into_iter() +                .map(|(v, k)| (k, v)) +                .collect::<BTreeMap<_, _>>(); + +            File::create(output)?.write_all( +                format!( +                    "[hurrycurry]\n{}", +                    output_unflip +                        .into_iter() +                        .map(|(k, v)| format!("{k}={v}\n")) +                        .collect::<String>() +                ) +                .as_bytes(), +            )?; + +            Ok(()) +        } +    } +}  |