From 2b54f5c51ff9a26d4077037631ed39d62ed2b3fb Mon Sep 17 00:00:00 2001 From: Joel Klinghed Date: Thu, 12 Jun 2025 09:11:18 +0200 Subject: Initial support for translation reviews --- server/common/src/grit.rs | 98 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 20 deletions(-) (limited to 'server/common/src/grit.rs') diff --git a/server/common/src/grit.rs b/server/common/src/grit.rs index ee96500..9d01dac 100644 --- a/server/common/src/grit.rs +++ b/server/common/src/grit.rs @@ -4,7 +4,7 @@ use anyhow::Error; use std::collections::VecDeque; use std::fs; use std::io::{BufReader, Read}; -use std::path::Path; +use std::path::{Path, PathBuf}; use tokio::task::spawn_blocking; use xml::attribute::OwnedAttribute; use xml::reader::{EventReader, ParserConfig, XmlEvent}; @@ -1018,9 +1018,16 @@ fn parse_grit_part_element( pub async fn parse_grit(path: impl AsRef) -> anyhow::Result { let path = path.as_ref().to_path_buf(); + parse_grit_with_opener(move || Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_grit_with_opener(opener: F) -> anyhow::Result +where + F: FnOnce() -> anyhow::Result> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) @@ -1064,9 +1071,16 @@ pub async fn parse_grit(path: impl AsRef) -> anyhow::Result { pub async fn parse_grit_part(path: impl AsRef) -> anyhow::Result { let path = path.as_ref().to_path_buf(); + parse_grit_part_with_opener(|| Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_grit_part_with_opener(opener: F) -> anyhow::Result +where + F: FnOnce() -> anyhow::Result> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) @@ -1121,20 +1135,20 @@ fn if_message_to_if_message_part(messages: Vec) -> Vec .collect() } -async fn maybe_expand_message(message: &mut IfMessagePart, basepath: &Path) -> anyhow::Result<()> { +async fn maybe_expand_message(message: &mut IfMessagePart, opener: &F) -> anyhow::Result<()> +where + F: Fn(&str) -> anyhow::Result> + Clone + Send + 'static, + R: Read, +{ match message { IfMessagePart::Message(_) => Ok(()), IfMessagePart::Part { file, ref mut messages, } => { - let file_path = Path::new(file.as_str()); - let part_path = if let Some(parent) = basepath.parent() { - parent.join(file_path) - } else { - file_path.to_path_buf() - }; - let grit_part = parse_grit_part(part_path).await?; + let file = file.to_string(); + let opener = opener.clone(); + let grit_part = parse_grit_part_with_opener(move || opener(file.as_str())).await?; *messages = if_message_to_if_message_part(grit_part.messages); Ok(()) } @@ -1142,23 +1156,60 @@ async fn maybe_expand_message(message: &mut IfMessagePart, basepath: &Path) -> a expr: _, ref mut message, } => { - Box::pin(expand_messages(message, basepath)).await?; + Box::pin(expand_messages(message, opener)).await?; Ok(()) } } } -async fn expand_messages(messages: &mut Vec, basepath: &Path) -> anyhow::Result<()> { +async fn expand_messages(messages: &mut Vec, opener: &F) -> anyhow::Result<()> +where + F: Fn(&str) -> anyhow::Result> + Clone + Send + 'static, + R: Read, +{ for message in messages { - maybe_expand_message(message, basepath).await?; + maybe_expand_message(message, opener).await?; } Ok(()) } pub async fn parse_grit_with_parts(path: impl AsRef) -> anyhow::Result { let path = path.as_ref(); - let mut grit = parse_grit(path).await?; - expand_messages(&mut grit.release.messages.messages, path).await?; + if let Some(basepath) = path.parent() { + let basepath = basepath.to_path_buf(); + parse_grit_with_parts_and_resolver(path, move |x| basepath.join(x)).await + } else { + parse_grit_with_parts_and_resolver(path, |x| PathBuf::from(x)).await + } +} + +pub async fn parse_grit_with_parts_and_resolver( + path: impl AsRef, + path_resolver: F, +) -> anyhow::Result +where + F: Fn(&str) -> PathBuf + Send + Clone + 'static, +{ + let path = path.as_ref().to_path_buf(); + let grit_opener = || Ok(BufReader::new(fs::File::open(path)?)); + let part_opener = move |x: &str| { + let part_path = path_resolver(x); + Ok(BufReader::new(fs::File::open(part_path)?)) + }; + parse_grit_with_parts_and_opener(grit_opener, part_opener).await +} + +pub async fn parse_grit_with_parts_and_opener( + grit_opener: F, + part_opener: G, +) -> anyhow::Result +where + F: FnOnce() -> anyhow::Result> + Send + 'static, + G: Fn(&str) -> anyhow::Result> + Clone + Send + 'static, + R: Read, +{ + let mut grit = parse_grit_with_opener(grit_opener).await?; + expand_messages(&mut grit.release.messages.messages, &part_opener).await?; Ok(grit) } @@ -1513,9 +1564,16 @@ fn parse_xliff_element( pub async fn parse_xlf(path: impl AsRef) -> anyhow::Result { let path = path.as_ref().to_path_buf(); + parse_xlf_with_opener(|| Ok(BufReader::new(fs::File::open(path)?))).await +} + +pub async fn parse_xlf_with_opener(opener: F) -> anyhow::Result +where + F: FnOnce() -> anyhow::Result> + Send + 'static, + R: Read, +{ spawn_blocking(move || { - let file = fs::File::open(path)?; - let reader = BufReader::new(file); + let reader = opener()?; let mut ereader = ParserConfig::new() .ignore_comments(true) .whitespace_to_characters(true) -- cgit v1.2.3-70-g09d2