#![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::>()?; 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::(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::() ) .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::>()?; 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::(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::>(); File::create(output)?.write_all( format!( "[hurrycurry]\n{}", output_unflip .into_iter() .map(|(k, v)| format!("{k}={v}\n")) .collect::() ) .as_bytes(), )?; Ok(()) } } }