mod util;
use serde_json::Value;
use regex::{Regex};
#[cfg(feature = "interlude")]
use util::{is_ignored_word, get_random_index, is_one_percent_chance};
#[cfg(not(feature = "interlude"))]
use util::{is_ignored_word, get_random_index};
fn parse_translation() -> Option<Value> {
let translation_string = include_str!("de-oger.json");
Some(serde_json::from_str(&translation_string).expect("Could not parse translation."))
}
pub fn translate(original: &str) -> String {
let words: Vec<&str> = original.split(" ").collect();
let translation: Value = parse_translation().unwrap();
let punctuation_regex = Regex::new(r"[.,\\/#!?$%\^&\*;:{}=\-_`~()]").expect("Could not compile punctuation regex.");
let mut meddl = String::new();
for i in 0..words.len() {
let punctuation = punctuation_regex
.find(words[i])
.map(|punc| punc.as_str())
.unwrap_or("");
let cow = punctuation_regex.replace_all(words[i], "");
let mut word_no_punctuation = String::new();
word_no_punctuation.push_str(&cow);
let translated_punctuation = translate_punctuation(&punctuation, &translation);
#[cfg(feature = "interlude")]
let mut translated_word = translate_word(&word_no_punctuation, &translation);
#[cfg(not(feature = "interlude"))]
let translated_word = translate_word(&word_no_punctuation, &translation);
#[cfg(feature = "interlude")]
if is_one_percent_chance() {
translated_word = add_interlude(&translated_word, &translation);
}
meddl.push_str(&translated_word);
meddl.push_str(&translated_punctuation);
meddl.push(' ');
}
meddl
}
fn translate_word<'a>(word: &'a str, translation: &'a Value) -> String {
let mut word = translate_quotation_marks(word, translation);
if is_ignored_word(&word, &translation) {
return word;
}
if let Some(_key) = translation["translations"].get(&word) {
let possible_translations = translation["translations"][&word]
.as_array()
.unwrap();
let random = get_random_index(&possible_translations);
let translated_word = possible_translations[random]
.as_str()
.unwrap_or(&word);
word = String::from(translated_word);
} else {
word = twist_chars(&word, &translation);
}
word = twist_en(&word, translation);
String::from(&word)
}
fn twist_chars<'a>(word: &'a str, translation: &'a Value) -> String {
let twisted_chars = translation["twistedChars"]
.as_object()
.unwrap();
for (_key, array) in twisted_chars.iter().enumerate() {
let key = array.0;
if word.contains(key) {
let translated_word = word
.replace(key, array.1
.as_str()
.unwrap(),
);
return translated_word;
}
}
String::from(word)
}
fn twist_en<'a>(word: &'a str, translation: &'a Value) -> String {
let mut twisted = String::from(word);
if is_ignored_word(&twisted, translation) {
return twisted;
}
let ens = translation["en"]
.as_object()
.unwrap();
for (_key, array) in ens.iter().enumerate() {
let to_replace = array.0;
if word.ends_with(to_replace) {
let position = word.rfind(to_replace).unwrap();
twisted
.replace_range(position..word.len(), array.1
.as_str()
.unwrap()
)
}
}
twisted
}
fn translate_punctuation<'a>(punctuation: &'a str, translation: &'a Value) -> String {
return match punctuation {
"." => {
let dot_pool = translation["dot"]
.as_array()
.unwrap();
let random = get_random_index(dot_pool);
let translated_dot = dot_pool[random]
.as_str()
.unwrap();
String::from(translated_dot)
}
"!" => {
let exclamation_mark_pool = translation["exclamationMark"]
.as_array()
.unwrap();
let random = get_random_index(exclamation_mark_pool);
let translated_exclamation_mark = exclamation_mark_pool[random]
.as_str()
.unwrap();
String::from(translated_exclamation_mark)
}
"?" => {
let question_mark_pool = translation["questionMark"]
.as_array()
.unwrap();
let random = get_random_index(question_mark_pool);
let translated_question_mark = question_mark_pool[random]
.as_str()
.unwrap();
String::from(translated_question_mark)
}
_ => String::from(punctuation)
};
}
fn translate_quotation_marks(word: &str, translation: &Value) -> String {
if word.starts_with("\"") {
return word.replacen("\"", translation["quotationMark"]
.as_str()
.unwrap(),
1);
}
String::from(word)
}
#[cfg(feature = "interlude")]
fn add_interlude(word_to_add_to: &str, translation: &Value) -> String {
let interlude = translation["interlude"]
.as_str()
.unwrap();
let word_with_interlude = format!(
"{}{}",
word_to_add_to,
interlude
);
word_with_interlude
}
#[cfg(test)]
mod tests {
mod translate_word {
use super::super::*;
#[test]
fn test_ignore_word() {
let translation = serde_json::from_str("{\"ignored\": [\"whatever\"], \"translations\": { \"whatever\": [\"something\"]}}").unwrap();
assert_eq!(translate_word("whatever", &translation), "whatever");
}
#[test]
fn test_translate_word() {
let translation = serde_json::from_str("{\"translations\": { \"whatever\": [\"something\"]}, \"ignored\": [], \"en\": {}}").unwrap();
assert_eq!(translate_word("whatever", &translation), "something");
}
}
mod twist_chars {
use crate::twist_chars;
#[test]
fn test_twist_chars() {
let translation = serde_json::from_str("{\"twistedChars\": {\"ck\": \"gg\"}}").unwrap();
assert_eq!(twist_chars("wicked", &translation), "wigged");
}
}
mod twist_en {
use crate::twist_en;
#[test]
fn test_twist_en_end_of_word() {
let translation = serde_json::from_str("{\"en\": {\"en!\": \"ne!\"}, \"ignored\": []}").unwrap();
assert_eq!(twist_en("laufen!", &translation), "laufne!");
}
#[test]
fn test_twist_en_ignore_char_within() {
let translation = serde_json::from_str("{\"en\": {\"en\": \"ne\"}, \"ignored\": []}").unwrap();
assert_eq!(twist_en("denken", &translation), "denkne");
}
#[test]
fn test_twist_en_ignore_word_completely() {
let translation = serde_json::from_str("{\"en\": {\"en\": \"ne\"}, \"ignored\": [\"denken\"]}").unwrap();
assert_eq!(twist_en("denken", &translation), "denken");
}
}
mod translate_punctuation {
use crate::translate_punctuation;
#[test]
fn translate_punctuation_dot() {
let translation = serde_json::from_str("{\"dot\": [\" dot suffix.\"]}").unwrap();
assert_eq!(translate_punctuation(".", &translation), " dot suffix.");
}
#[test]
fn translation_punctuation_exclamation_mark() {
let translation = serde_json::from_str("{\"exclamationMark\": [\" exclamation mark suffix!\"]}").unwrap();
assert_eq!(translate_punctuation("!", &translation), " exclamation mark suffix!");
}
#[test]
fn translate_punctuation_question_mark() {
let translation = serde_json::from_str("{\"questionMark\": [\" question mark suffix?\"]}").unwrap();
assert_eq!(translate_punctuation("?", &translation), " question mark suffix?");
}
#[test]
fn translate_punctuation_return_anything_else() {
let translation = serde_json::from_str("{}").unwrap();
assert_eq!(translate_punctuation("~", &translation), "~");
}
}
mod translate_quotation_marks {
use crate::translate_quotation_marks;
#[test]
fn test_translate_quotation_marks() {
let translation = serde_json::from_str("{\"quotationMark\":\"I cite: \\\"\"}").unwrap();
assert_eq!(translate_quotation_marks("\"word\"", &translation), "I cite: \"word\"");
}
}
}