use crate::poly_translator::async_translator::{AsyncTranslator, Language, TranslationListOutput, TranslationOutput};
use crate::poly_translator::translator_error::TranslatorError;
use reqwest::Client;
use serde_json::Value;
pub struct AlibabaTranslator {
input_limit: u32,
host: String,
client: Client,
}
impl Default for AlibabaTranslator {
fn default() -> Self {
AlibabaTranslator::new()
}
}
pub fn input_limit_checker(query: &str, input_limit: u32) -> Result<(), TranslatorError> {
if query.len() > input_limit as usize {
return Err(TranslatorError::RequestToLong(query.len() as u32, input_limit));
}
Ok(())
}
#[async_trait::async_trait]
impl AsyncTranslator for AlibabaTranslator {
fn local(&self) -> bool {
false
}
async fn translate(
&self,
query: &str,
from: Option<Language>,
to: &Language,
) -> anyhow::Result<TranslationOutput> {
input_limit_checker(query, self.input_limit)?;
let _from_orig = from;
let _from = match _from_orig {
Some(lang) => lang.to_mymemory_short().ok_or(TranslatorError::UnknownLanguage(lang))?,
None => "auto",
};
let url = format!(
"{}?domain={}&query={}&srcLang={}&tgtLang={}",
self.host,
"general",
query,
_from,
to.to_mymemory_short().ok_or(TranslatorError::UnknownLanguage(*to))?
);
let response = self
.client
.get(&url)
.send()
.await?;
if !response.status().is_success() {
return Err(TranslatorError::RequestFailed(response.status().as_u16()).into());
}
let resp: Value = response.json().await?;
let resp = &resp["data"];
let _lang = resp["detectLanguage"].to_string();
let mut text = resp["translateText"].to_string();
if text == "null" {
return Err(TranslatorError::NoResponse.into());
}
if text.starts_with('"') && text.ends_with('"') {
text = text[1..text.len() - 1].to_string();
}
Ok(TranslationOutput {
text,
lang: Some(*to),
})
}
async fn translate_vec(
&self,
query: &[String],
from: Option<Language>,
to: &Language,
) -> anyhow::Result<TranslationListOutput> {
let t = self.translate(&query.join("_._._"), from, to).await?;
Ok(TranslationListOutput {
text: t
.text
.split("_._._")
.map(|s| s.to_string())
.collect::<Vec<_>>(),
lang: t.lang,
})
}
}
impl AlibabaTranslator {
#[allow(dead_code)]
pub fn new() -> Self {
AlibabaTranslator {
client: Client::new(),
input_limit: 500,
host: "https://translate.alibaba.com/api/translate/text".to_string(),
}
}
}
#[cfg(test)]
mod tests {
use crate::poly_translator::async_translator::AsyncTranslator;
use crate::poly_translator::alibaba_translator::AlibabaTranslator;
#[tokio::test]
async fn test_create_translator() {
let translator = AlibabaTranslator::new();
assert!(!translator.local());
}
#[test]
fn test_input_limit_checker() {
use crate::poly_translator::alibaba_translator::input_limit_checker;
let result = input_limit_checker("short text", 500);
assert!(result.is_ok());
let long_text = "a".repeat(600);
let result = input_limit_checker(&long_text, 500);
assert!(result.is_err());
}
#[test]
fn test_default() {
let translator = AlibabaTranslator::default();
assert!(!translator.local());
}
}