diff options
| author | Fuwn <[email protected]> | 2023-03-30 02:02:57 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-03-30 02:02:57 -0700 |
| commit | 7e1c907be3612b77f66f93b4dcfa388aad201430 (patch) | |
| tree | d8385027739070f7c331a1ee0bec1adc60050c42 | |
| parent | feat(router): add uwufy demo (diff) | |
| download | locus-7e1c907be3612b77f66f93b4dcfa388aad201430.tar.xz locus-7e1c907be3612b77f66f93b4dcfa388aad201430.zip | |
feat(router): add translation engine
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | content/static/translate.gmi | 11 | ||||
| -rw-r--r-- | content/templates/partials/footer.hbs | 2 | ||||
| -rw-r--r-- | src/modules/router.rs | 69 | ||||
| -rw-r--r-- | src/modules/router/deepl.rs | 50 | ||||
| -rw-r--r-- | src/modules/router/module.rs | 98 | ||||
| -rw-r--r-- | src/modules/static.rs | 5 |
8 files changed, 171 insertions, 66 deletions
@@ -38,6 +38,7 @@ yarte = "0.15.6" # Templating Engine tempfile = "3.3.0" # Temporary File Creation and Access dotenv = "0.15.0" # .env File Support once_cell = "1.13.1" # Lazy Statics +germ = { version = "0.3.7", default-features = false, features = ["ast"] } # Gemini Tool-kit [build-dependencies] vergen = { version = "8.0.0", features = [ @@ -18,5 +18,6 @@ - Background page indexing and caching - Simple module integration - Critical data caching +- Full-capsule translation engine Built with [Windmark](https://github.com/gemrest/windmark). diff --git a/content/static/translate.gmi b/content/static/translate.gmi new file mode 100644 index 0000000..4542114 --- /dev/null +++ b/content/static/translate.gmi @@ -0,0 +1,11 @@ +# Translate + +This Gemini capsule contains a **global** translation engine (using DeepL)! + +To translate any page into your language of choice, just add the "translate" query parameter to the URL. + +For example, to translate this page into French, you would go to: <gemini://fuwn.me/translate?language=fr> + +=> /translate?language=fr Try it! + +Before visiting a page in another language, make note of your Gemini client. Not all Gemini clients have support for other typefaces, encodings, etc., so languages with non-Latin alphabets may not display correctly. diff --git a/content/templates/partials/footer.hbs b/content/templates/partials/footer.hbs index 4e98866..4be4242 100644 --- a/content/templates/partials/footer.hbs +++ b/content/templates/partials/footer.hbs @@ -24,6 +24,8 @@ Hits: {{ hits }} => http://fuwnme4wbs5x36jjf2usedw2zscozwhazykhyfkjsmudtb7egs3mb7yd.onion Tor => http://fuwn.i2p/?i2paddresshelper=umaux4l3q3j33pfsz3mzxk6o5c7f6lu47wln5vo5nqvv5nyufgra.b32.i2p I2P +=> /translate Translate this page to your language of choice! + Copyright (C) 2021-2022 Fuwn => /licensing Further and more explicit licensing terms can be found here diff --git a/src/modules/router.rs b/src/modules/router.rs index ade7d33..8f24a9b 100644 --- a/src/modules/router.rs +++ b/src/modules/router.rs @@ -16,70 +16,7 @@ // Copyright (C) 2022-2022 Fuwn <[email protected]> // SPDX-License-Identifier: GPL-3.0-only -use crate::DATABASE; +mod deepl; +mod module; -pub fn module(router: &mut windmark::Router) { - router.set_pre_route_callback(Box::new(|context| { - info!( - "accepted connection from {} to {}", - context.tcp.peer_addr().unwrap().ip(), - context.url.to_string(), - ); - - let url_path = if context.url.path().is_empty() { - "/" - } else { - context.url.path() - }; - - let previous_database = (*DATABASE.lock().unwrap()).get::<i32>(url_path); - - match previous_database { - None => { - (*DATABASE.lock().unwrap()) - .set::<i32>(url_path, &0) - .unwrap(); - } - Some(_) => {} - } - - let new_database = (*DATABASE.lock().unwrap()).get::<i32>(url_path); - - (*DATABASE.lock().unwrap()) - .set(url_path, &(new_database.unwrap() + 1)) - .unwrap(); - })); - - router.set_post_route_callback(Box::new(|context, content| { - info!( - "closed connection from {} to {}", - context.tcp.peer_addr().unwrap().ip(), - context.url.to_string(), - ); - - // Just a simple demo for now. - if let Some(uwu) = - windmark::utilities::queries_from_url(context.url).get("uwu") - { - if uwu.to_lowercase() == "true" || uwu == "1" { - let mut lines = content - .lines() - .map(ToString::to_string) - .collect::<Vec<String>>(); - - for line in &mut lines { - if !line.starts_with("=>") { - *line = line - .replace('l', "w") - .replace('r', "w") - .replace('L', "W") - .replace('R', "W") - .replace('!', "! >w<"); - } - } - - *content = lines.join("\n"); - } - } - })); -} +pub use module::module; diff --git a/src/modules/router/deepl.rs b/src/modules/router/deepl.rs new file mode 100644 index 0000000..d4e210f --- /dev/null +++ b/src/modules/router/deepl.rs @@ -0,0 +1,50 @@ +// This file is part of Locus <https://github.com/gemrest/locus>. +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// SPDX-License-Identifier: GPL-3.0-only + +#[derive(serde::Deserialize)] +pub struct DeepL { + translations: Vec<Translation>, +} + +impl DeepL { + pub fn text(&self) -> String { self.translations[0].text.clone() } +} + +#[derive(serde::Deserialize)] +struct Translation { + pub text: String, +} + +pub fn translate(text: &str, language: &str) -> DeepL { + let deepl_response: DeepL = serde_json::from_str( + &reqwest::blocking::Client::new() + .post("https://api-free.deepl.com/v2/translate") + .header( + "Authorization", + "DeepL-Auth-Key 182c8c21-730e-f99d-8f2e-61e9cc861faa:fx", + ) + .form(&[("text", text), ("target_lang", language)]) + .send() + .unwrap() + .text() + .unwrap(), + ) + .unwrap(); + + deepl_response +} diff --git a/src/modules/router/module.rs b/src/modules/router/module.rs new file mode 100644 index 0000000..a97c973 --- /dev/null +++ b/src/modules/router/module.rs @@ -0,0 +1,98 @@ +// This file is part of Locus <https://github.com/gemrest/locus>. +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 3. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +// Copyright (C) 2022-2022 Fuwn <[email protected]> +// SPDX-License-Identifier: GPL-3.0-only + +use crate::{modules::router::deepl::translate, DATABASE}; + +pub fn module(router: &mut windmark::Router) { + router.set_pre_route_callback(Box::new(|context| { + info!( + "accepted connection from {} to {}", + context.tcp.peer_addr().unwrap().ip(), + context.url.to_string(), + ); + + let url_path = if context.url.path().is_empty() { + "/" + } else { + context.url.path() + }; + + let previous_database = (*DATABASE.lock().unwrap()).get::<i32>(url_path); + + match previous_database { + None => { + (*DATABASE.lock().unwrap()) + .set::<i32>(url_path, &0) + .unwrap(); + } + Some(_) => {} + } + + let new_database = (*DATABASE.lock().unwrap()).get::<i32>(url_path); + + (*DATABASE.lock().unwrap()) + .set(url_path, &(new_database.unwrap() + 1)) + .unwrap(); + })); + router.set_post_route_callback(Box::new({ + |context, content| { + info!( + "closed connection from {} to {}", + context.tcp.peer_addr().unwrap().ip(), + context.url.to_string(), + ); + + if let Some(language) = + windmark::utilities::queries_from_url(context.url).get("translate") + { + let mut lines = content + .lines() + .map(ToString::to_string) + .collect::<Vec<String>>(); + let mut preformatted = true; + + for line in &mut lines { + if line == "```" { + preformatted = !preformatted; + } + + if line.starts_with("=>") { + if let Some(germ::ast::Node::Link { + to, + text, + }) = germ::ast::Ast::from_string(line).inner().get(0) + { + *line = format!( + "=> {to}?translate={language}{}", + text.clone().map_or_else( + || "".to_string(), + |text| { format!(" {}", translate(&text, language).text()) } + ) + ); + } + } else if !line.starts_with("=>") && preformatted && !line.is_empty() + { + *line = translate(line, language).text(); + } + } + + *content = lines.join("\n"); + } + } + })); +} diff --git a/src/modules/static.rs b/src/modules/static.rs index b829b44..7197ac2 100644 --- a/src/modules/static.rs +++ b/src/modules/static.rs @@ -60,6 +60,11 @@ pub fn module(router: &mut windmark::Router) { "/stocks/telegram", "Stock Market Related Telegram Groups", "stocks_telegram" + ), + ( + "/translate", + "Translate a page to your language of choice!", + "translate" ) ); } |