Skip to content

Commit

Permalink
made language listing fast
Browse files Browse the repository at this point in the history
  • Loading branch information
ede1998 committed Oct 3, 2019
1 parent 6c5c50a commit 9c2d829
Show file tree
Hide file tree
Showing 7 changed files with 962 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dict"
version = "1.4.0"
version = "1.4.1"
authors = ["ede1998 <online@erik-hennig.me>"]
edition = "2018"
description = "A small command-line translator. It queries the dict.cc website for translations."
Expand Down
709 changes: 709 additions & 0 deletions dict-responses/available_languages.html

Large diffs are not rendered by default.

8 changes: 1 addition & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,15 @@ fn print_info(arguments: &clap::ArgMatches) {
.expect("Unexpected missing subcommand. Please contact the developer.");
match subcommand {
args::AVAILABLE => {
let languages = Language::get_all_languages();
println!("The following language pairs are available:");
for l1 in [Language::EN, Language::DE].iter() {
for l2 in &languages {
if DictccTranslator::is_language_available((*l1, *l2)) {
for (l1,l2) in DictccTranslator::get_available_languages() {
println!(
"{} {} => {} - {}",
l1.get_abbreviation(),
l2.get_abbreviation(),
l1,
l2
);
}
}
println!();
}
}
args::ABBREVIATIONS => {
Expand Down
113 changes: 112 additions & 1 deletion src/translator/dictcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct DictccTranslator {
}

const URL: &str = "https://{}{}.dict.cc";
const URL_LANGUAGE_LIST: &str = "https://www.dict.cc";

#[derive(Debug)]
enum RequestError {
Expand Down Expand Up @@ -49,6 +50,10 @@ impl DictccTranslator {
}
}

fn make_request(request: &str) -> Result<String, RequestError> {
Ok(reqwest::get(request)?.text()?)
}

fn download_translations(
request: &str,
language: LanguagePair,
Expand All @@ -58,7 +63,7 @@ impl DictccTranslator {
.replacen("{}", &language.0.get_abbreviation(), 1)
.replacen("{}", &language.1.get_abbreviation(), 1);
let request = reqwest::Url::parse_with_params(&request_url, &[("s", request)])?;
Ok(reqwest::get(request)?.text()?)
DictccTranslator::make_request(&request.as_str())
}

fn parse_column(html: &Html, column_selector: &str) -> Vec<String> {
Expand Down Expand Up @@ -128,6 +133,34 @@ impl DictccTranslator {

Some((left, right))
}

fn parse_available_languages(html: &Html) -> Vec<LanguagePair> {
use itertools::Itertools;
use scraper::Selector;
const SELECTOR: &str = "#lpddbsf option";

let selector = Selector::parse(&SELECTOR).unwrap();
let rows: Vec<LanguagePair> = html
.select(&selector)
.filter_map(|element| {
// filter wrong elements
let element = element.value().attr("value")?;
if element.contains("-") || element.len() != 4 {
return None;
}

let language = (
element[0..2].parse::<Language>().ok()?,
element[2..4].parse::<Language>().ok()?,
);

Some(language)
})
.unique()
.collect();

rows
}
}

impl Translator for DictccTranslator {
Expand Down Expand Up @@ -195,6 +228,20 @@ impl Translator for DictccTranslator {
}
false
}

fn get_available_languages() -> Vec<LanguagePair> {
match DictccTranslator::make_request(URL_LANGUAGE_LIST) {
Ok(html) => {
let document = Html::parse_document(&html);
return DictccTranslator::parse_available_languages(&document);
}
Err(failure) => println!(
"Checking available translations from dict.cc failed. Reason: {}",
failure
),
}
vec![]
}
}

#[cfg(test)]
Expand Down Expand Up @@ -331,4 +378,68 @@ mod tests {
let result = result.unwrap();
Html::parse_document(&result);
}

#[test]
fn available_languages() {
let website = read_website("dict-responses/available_languages.html");
let languages = [
(Language::DE, Language::EN),
(Language::DE, Language::BG),
(Language::DE, Language::BS),
(Language::DE, Language::CS),
(Language::DE, Language::DA),
(Language::DE, Language::EL),
(Language::DE, Language::EO),
(Language::DE, Language::ES),
(Language::DE, Language::FI),
(Language::DE, Language::FR),
(Language::DE, Language::HR),
(Language::DE, Language::HU),
(Language::DE, Language::IS),
(Language::DE, Language::IT),
(Language::DE, Language::LA),
(Language::DE, Language::NL),
(Language::DE, Language::NO),
(Language::DE, Language::PL),
(Language::DE, Language::PT),
(Language::DE, Language::RO),
(Language::DE, Language::RU),
(Language::DE, Language::SK),
(Language::DE, Language::SQ),
(Language::DE, Language::SR),
(Language::DE, Language::SV),
(Language::DE, Language::TR),
(Language::EN, Language::BG),
(Language::EN, Language::BS),
(Language::EN, Language::CS),
(Language::EN, Language::DA),
(Language::EN, Language::EL),
(Language::EN, Language::EO),
(Language::EN, Language::ES),
(Language::EN, Language::FI),
(Language::EN, Language::FR),
(Language::EN, Language::HR),
(Language::EN, Language::HU),
(Language::EN, Language::IS),
(Language::EN, Language::IT),
(Language::EN, Language::LA),
(Language::EN, Language::NL),
(Language::EN, Language::NO),
(Language::EN, Language::PL),
(Language::EN, Language::PT),
(Language::EN, Language::RO),
(Language::EN, Language::RU),
(Language::EN, Language::SK),
(Language::EN, Language::SQ),
(Language::EN, Language::SR),
(Language::EN, Language::SV),
(Language::EN, Language::TR),
];

let result = DictccTranslator::parse_available_languages(&website);

for pair in languages.iter() {
assert!(result.contains(pair));
}
}
}
166 changes: 137 additions & 29 deletions src/translator/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub type LanguagePair = (Language, Language);
pub const DEFAULT_LANGUAGES: LanguagePair = (Language::EN, Language::DE);

#[allow(dead_code)]
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Language {
BG,
BS,
Expand Down Expand Up @@ -56,34 +56,142 @@ struct LanguageFull {
value: Language,
}

const LANGUAGE: [LanguageFull;27] = [
LanguageFull{ value: Language::BG, abbreviation: "BG", name: "Bulgarian"},
LanguageFull{ value: Language::BS, abbreviation: "BS", name: "Bosnian"},
LanguageFull{ value: Language::CS, abbreviation: "CS", name: "Czech"},
LanguageFull{ value: Language::DA, abbreviation: "DA", name: "Danish"},
LanguageFull{ value: Language::DE, abbreviation: "DE", name: "German"},
LanguageFull{ value: Language::EL, abbreviation: "EL", name: "Greek"},
LanguageFull{ value: Language::EN, abbreviation: "EN", name: "English"},
LanguageFull{ value: Language::EO, abbreviation: "EO", name: "Esperanto"},
LanguageFull{ value: Language::ES, abbreviation: "ES", name: "Spanish"},
LanguageFull{ value: Language::FI, abbreviation: "FI", name: "Finnish"},
LanguageFull{ value: Language::FR, abbreviation: "FR", name: "French"},
LanguageFull{ value: Language::HR, abbreviation: "HR", name: "Croatian"},
LanguageFull{ value: Language::HU, abbreviation: "HU", name: "Hungarian"},
LanguageFull{ value: Language::IS, abbreviation: "IS", name: "Icelandic"},
LanguageFull{ value: Language::IT, abbreviation: "IT", name: "Italian"},
LanguageFull{ value: Language::LA, abbreviation: "LA", name: "Latin"},
LanguageFull{ value: Language::NL, abbreviation: "NL", name: "Dutch"},
LanguageFull{ value: Language::NO, abbreviation: "NO", name: "Norwegian"},
LanguageFull{ value: Language::PL, abbreviation: "PL", name: "Polish"},
LanguageFull{ value: Language::PT, abbreviation: "PT", name: "Portuguese"},
LanguageFull{ value: Language::RO, abbreviation: "RO", name: "Romanian"},
LanguageFull{ value: Language::RU, abbreviation: "RU", name: "Russian"},
LanguageFull{ value: Language::SK, abbreviation: "SK", name: "Slovak"},
LanguageFull{ value: Language::SQ, abbreviation: "SQ", name: "Albanian"},
LanguageFull{ value: Language::SR, abbreviation: "SR", name: "Serbian"},
LanguageFull{ value: Language::SV, abbreviation: "SV", name: "Swedish"},
LanguageFull{ value: Language::TR, abbreviation: "TR", name: "Turkish"},
const LANGUAGE: [LanguageFull; 27] = [
LanguageFull {
value: Language::BG,
abbreviation: "BG",
name: "Bulgarian",
},
LanguageFull {
value: Language::BS,
abbreviation: "BS",
name: "Bosnian",
},
LanguageFull {
value: Language::CS,
abbreviation: "CS",
name: "Czech",
},
LanguageFull {
value: Language::DA,
abbreviation: "DA",
name: "Danish",
},
LanguageFull {
value: Language::DE,
abbreviation: "DE",
name: "German",
},
LanguageFull {
value: Language::EL,
abbreviation: "EL",
name: "Greek",
},
LanguageFull {
value: Language::EN,
abbreviation: "EN",
name: "English",
},
LanguageFull {
value: Language::EO,
abbreviation: "EO",
name: "Esperanto",
},
LanguageFull {
value: Language::ES,
abbreviation: "ES",
name: "Spanish",
},
LanguageFull {
value: Language::FI,
abbreviation: "FI",
name: "Finnish",
},
LanguageFull {
value: Language::FR,
abbreviation: "FR",
name: "French",
},
LanguageFull {
value: Language::HR,
abbreviation: "HR",
name: "Croatian",
},
LanguageFull {
value: Language::HU,
abbreviation: "HU",
name: "Hungarian",
},
LanguageFull {
value: Language::IS,
abbreviation: "IS",
name: "Icelandic",
},
LanguageFull {
value: Language::IT,
abbreviation: "IT",
name: "Italian",
},
LanguageFull {
value: Language::LA,
abbreviation: "LA",
name: "Latin",
},
LanguageFull {
value: Language::NL,
abbreviation: "NL",
name: "Dutch",
},
LanguageFull {
value: Language::NO,
abbreviation: "NO",
name: "Norwegian",
},
LanguageFull {
value: Language::PL,
abbreviation: "PL",
name: "Polish",
},
LanguageFull {
value: Language::PT,
abbreviation: "PT",
name: "Portuguese",
},
LanguageFull {
value: Language::RO,
abbreviation: "RO",
name: "Romanian",
},
LanguageFull {
value: Language::RU,
abbreviation: "RU",
name: "Russian",
},
LanguageFull {
value: Language::SK,
abbreviation: "SK",
name: "Slovak",
},
LanguageFull {
value: Language::SQ,
abbreviation: "SQ",
name: "Albanian",
},
LanguageFull {
value: Language::SR,
abbreviation: "SR",
name: "Serbian",
},
LanguageFull {
value: Language::SV,
abbreviation: "SV",
name: "Swedish",
},
LanguageFull {
value: Language::TR,
abbreviation: "TR",
name: "Turkish",
},
];

use std::fmt;
Expand Down
2 changes: 1 addition & 1 deletion src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub trait Translator {
fn set_languages_if_available(&mut self, languages: LanguagePair) -> bool;

fn is_language_available(language: LanguagePair) -> bool;
//TODO fn get_available_languages() -> Vec<LanguagePair>;
fn get_available_languages() -> Vec<LanguagePair>;
}

pub use dictcc::DictccTranslator;
Expand Down

0 comments on commit 9c2d829

Please sign in to comment.