You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.3 KiB
119 lines
3.3 KiB
use crate::command_runner::CommandRunner;
|
|
use crate::symbols::Symbol;
|
|
use async_trait::async_trait;
|
|
use regex::Regex;
|
|
use std::cmp::max;
|
|
use std::error::Error;
|
|
use std::fs::File as FsFile;
|
|
use std::io;
|
|
use std::io::{BufRead, BufReader};
|
|
use std::path::Path;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Translation<'a, C, D, R> {
|
|
path: D,
|
|
version: &'a str,
|
|
locale: C,
|
|
command_runner: &'a R,
|
|
}
|
|
|
|
impl<'a, D, C: AsRef<str>, R> Translation<'a, C, D, R> {
|
|
pub const fn new(path: D, version: &'a str, locale: C, command_runner: &'a R) -> Self {
|
|
Self {
|
|
path,
|
|
version,
|
|
locale,
|
|
command_runner,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Translation<'_, C, D, R> {
|
|
fn get_pairs(&self) -> impl Iterator<Item = (Box<str>, Box<Path>)> + '_ {
|
|
let version_x = self
|
|
.version
|
|
.trim_end_matches(|c: char| c.is_ascii_digit())
|
|
.to_owned()
|
|
+ "x";
|
|
let locale = self.locale.as_ref();
|
|
let path_locale = if locale == "de_DE" {
|
|
"de".to_owned()
|
|
} else {
|
|
locale.to_lowercase().replace('_', "-")
|
|
};
|
|
[
|
|
("", ""),
|
|
("cc/", "continents-cities-"),
|
|
("admin/", "admin-"),
|
|
("admin/network/", "admin-network-"),
|
|
].into_iter().flat_map(move |(in_slug, out_slug)|{
|
|
["po", "mo"].map(|format|
|
|
(
|
|
format!("https://translate.wordpress.org/projects/wp/{version_x}/{in_slug}{path_locale}/default/export-translations?format={format}").into(),
|
|
self.path.as_ref().join(format!("{}{}.{}", out_slug, self.locale.as_ref(), format)).into()
|
|
))
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
#[async_trait(?Send)]
|
|
impl<C: AsRef<str>, D: AsRef<Path>, R: CommandRunner> Symbol for Translation<'_, C, D, R> {
|
|
async fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
|
|
let mut newest = String::new();
|
|
let match_date = Regex::new("(?m)^\"PO-Revision-Date: (.+)\\+0000\\\\n\"$").unwrap();
|
|
for (_, target) in self.get_pairs() {
|
|
match FsFile::open(target.clone()) {
|
|
Err(e) => {
|
|
// Check if file exists
|
|
return if e.kind() == io::ErrorKind::NotFound {
|
|
Ok(false)
|
|
} else {
|
|
Err(Box::new(e))
|
|
};
|
|
}
|
|
Ok(file) => {
|
|
if target.ends_with(".po") {
|
|
let reader = BufReader::new(file);
|
|
for content in reader.lines() {
|
|
if let Some(match_result) = match_date.captures(&content?) {
|
|
newest = max(newest, match_result[1].into());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let upstream = self
|
|
.command_runner
|
|
.get_output(
|
|
"curl",
|
|
args![format!(
|
|
"https://api.wordpress.org/core/version-check/1.7/?version={}&locale={}",
|
|
self.version,
|
|
self.locale.as_ref()
|
|
)],
|
|
)
|
|
.await?;
|
|
Ok(std::str::from_utf8(&upstream)?.contains(&format!(
|
|
r###"language":"{}","version":"{}","updated":"{}"###,
|
|
self.locale.as_ref(),
|
|
self.version,
|
|
newest
|
|
)))
|
|
}
|
|
|
|
async fn execute(&self) -> Result<(), Box<dyn Error>> {
|
|
for (source, target) in self.get_pairs() {
|
|
self
|
|
.command_runner
|
|
.run_successfully(
|
|
"curl",
|
|
args!["--compressed", "-o", target.as_os_str(), source.as_ref(),],
|
|
)
|
|
.await?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|