use std::{
fs::File,
io::{BufRead, Write},
path::Path,
};
use crate::ProjectDescriptor;
pub fn build_gettext(project_dir: &Path, project_descriptor: &ProjectDescriptor) {
let gra_gen_abs_dir = project_dir.join("target/gra-gen");
let gra_gen_rel_dir = std::path::Path::new("target/gra-gen");
let id = &project_descriptor.app.id;
let domain = &project_descriptor.package.name;
let target_pot_dir = &gra_gen_abs_dir.join("po");
std::fs::create_dir_all(target_pot_dir).expect("Could not create target/po.");
let potfiles = target_pot_dir.join("POTFILES");
let mut potfiles_file = File::create(&potfiles).expect("Could not create target/po/POTFILES");
let mut pofiles: Vec<String> = match std::process::Command::new("grep")
.current_dir(project_dir)
.args(["-lr", "-E", "gettext|translatable", "src/"])
.output()
{
Ok(output) => String::from_utf8(output.stdout)
.unwrap()
.lines()
.map(String::from)
.collect(),
Err(e) => {
eprintln!("[gra] {:?}", e);
return;
}
};
pofiles.push(
gra_gen_rel_dir
.join(format!("data/{}.appdata.xml", id))
.to_str()
.unwrap()
.to_string(),
);
if let Err(e) = potfiles_file.write_all(pofiles.join("\n").as_bytes()) {
eprintln!("[gra] {:?}", e);
}
if let Err(e) = std::fs::create_dir_all(target_pot_dir) {
eprintln!("[gra] {:?}", e);
return;
}
println!("[gra] Update po files");
let lines = read_lines(project_dir.join("po/LINGUAS"));
if lines.is_err() {
eprintln!("[gra] Can not read po/LINGUAS file: {}", lines.unwrap_err());
return;
}
for line in lines.unwrap().map_while(Result::ok) {
if !line.starts_with('#') {
let locale = &line;
let po_file = project_dir.join(format!("po/{}.po", locale)); let pot_file = target_pot_dir.join(format!("{}.pot", locale));
let target_mo_dir = gra_gen_abs_dir
.join("locale")
.join(locale)
.join("LC_MESSAGES");
let target_mo = gra_gen_abs_dir
.join("locale")
.join(locale)
.join("LC_MESSAGES")
.join(format!("{}.mo", domain));
if let Err(e) = std::fs::create_dir_all(target_mo_dir) {
eprintln!("[gra] {:?}", e);
}
println!("[gra] Generate/Update translations {:?}", &po_file);
println!(
"[gra] xgettext -f {:?} -o {:?} in {:?}",
&potfiles, &pot_file, &project_dir
);
match std::process::Command::new("xgettext")
.current_dir(project_dir)
.arg("-f")
.arg(&potfiles)
.arg("-o")
.arg(&pot_file)
.output()
{
Err(e) => {
println!("[gra] {:?}", e);
}
Ok(output) => {
let o = String::from_utf8(output.stdout).unwrap();
if !o.trim().is_empty() {
println!("[gra] {}", o);
}
if !output.stderr.is_empty() {
for line in String::from_utf8(output.stderr)
.unwrap_or_else(|_| "".into())
.lines()
{
if line.is_empty() || line.contains("'rs'") || line.contains("warning")
{
continue;
}
eprintln!("[gra] {}", line);
}
}
}
}
println!("[gra] msgmerge {:?} -U {:?}", &po_file, &pot_file);
match std::process::Command::new("msgmerge")
.current_dir(project_dir)
.arg(&po_file)
.arg(&pot_file)
.arg("-U")
.output()
{
Err(e) => {
eprintln!("[gra] {:?}", e);
}
Ok(output) => {
let o = String::from_utf8(output.stdout).unwrap();
if !o.trim().is_empty() {
println!("[gra] {}", o);
}
if !output.stderr.is_empty() {
let s = String::from_utf8(output.stderr).unwrap_or_else(|_| "".into());
if !s.contains("...") {
eprintln!("[gra] {}", s)
}
}
}
}
println!(
"[gra] msgfmt -o {:?} {:?} in {:?}",
&target_mo, &pot_file, &project_dir
);
match std::process::Command::new("msgfmt")
.current_dir(project_dir)
.arg("-o")
.arg(&target_mo)
.arg(&po_file)
.output()
{
Err(e) => {
eprintln!("[gra] {:?}", e);
}
Ok(output) => {
let o = String::from_utf8(output.stdout).unwrap();
if !o.trim().is_empty() {
println!("[gra] {}", o);
}
if !output.stderr.is_empty() {
let s = String::from_utf8(output.stderr).unwrap_or_else(|_| "".into());
eprintln!("[gra] {}", s)
}
}
}
}
}
}
fn read_lines<P>(filename: P) -> std::io::Result<std::io::Lines<std::io::BufReader<std::fs::File>>>
where
P: AsRef<std::path::Path>,
{
let file = std::fs::File::open(filename)?;
Ok(std::io::BufReader::new(file).lines())
}