From: Greg Burri Date: Tue, 7 Jan 2025 15:47:24 +0000 (+0100) Subject: Avoid to use an hash map in translations X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=91ab379718e091c110f21b986f88982f24dceb82;p=recipes.git Avoid to use an hash map in translations --- diff --git a/Cargo.lock b/Cargo.lock index 82ec42d..d9421b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.84" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", @@ -1756,18 +1756,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", @@ -1776,9 +1776,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1930,9 +1930,10 @@ dependencies = [ "rinja", "rinja_axum", "ron", - "rustc-hash", "serde", "sqlx", + "strum", + "strum_macros", "thiserror 2.0.9", "tokio", "tower", @@ -2210,9 +2211,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -2572,6 +2573,25 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + [[package]] name = "subtle" version = "2.6.1" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 9a47b14..0030c25 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -23,7 +23,6 @@ ron = "0.8" serde = { version = "1.0", features = ["derive"] } itertools = "0.14" -rustc-hash = "2.1" clap = { version = "4", features = ["derive"] } sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono"] } @@ -34,6 +33,8 @@ rinja_axum = "0.3" argon2 = { version = "0.5", features = ["default", "std"] } rand_core = { version = "0.6", features = ["std"] } rand = "0.8" +strum = "0.26" +strum_macros = "0.26" lettre = { version = "0.11", default-features = false, features = [ "smtp-transport", diff --git a/backend/scss/style.scss b/backend/scss/style.scss index fa47f09..b1c26fc 100644 --- a/backend/scss/style.scss +++ b/backend/scss/style.scss @@ -76,6 +76,12 @@ body { font-size: 0.5em; } + .drag-handle { + width: 20px; + height: 20px; + background-color: gray; + } + .main-container { display: flex; flex-direction: row; diff --git a/backend/src/html_templates.rs b/backend/src/html_templates.rs index ab8ca0a..1679e6a 100644 --- a/backend/src/html_templates.rs +++ b/backend/src/html_templates.rs @@ -2,7 +2,7 @@ use rinja_axum::Template; use crate::{ data::model, - translation::{Sentence, Tr}, + translation::{self, Sentence, Tr}, }; pub struct Recipes { diff --git a/backend/src/main.rs b/backend/src/main.rs index 610ea49..274349a 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -231,7 +231,7 @@ async fn translation( let language = if let Some(user) = user { user.lang } else { - let available_codes = Tr::available_codes(); + let available_codes = translation::available_codes(); let jar = CookieJar::from_headers(req.headers()); match jar.get(consts::COOKIE_LANG_NAME) { Some(lang) if available_codes.contains(&lang.value()) => lang.value().to_string(), diff --git a/backend/src/services/ron.rs b/backend/src/services/ron.rs index 0d31103..f93c3b1 100644 --- a/backend/src/services/ron.rs +++ b/backend/src/services/ron.rs @@ -249,7 +249,7 @@ pub async fn set_language( Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { - if !crate::translation::Tr::available_codes() + if !crate::translation::available_codes() .iter() .any(|&l| l == ron.lang) { diff --git a/backend/src/translation.rs b/backend/src/translation.rs index 2049ac2..aede01d 100644 --- a/backend/src/translation.rs +++ b/backend/src/translation.rs @@ -1,15 +1,16 @@ use std::{fs::File, sync::LazyLock}; use ron::de::from_reader; -use rustc_hash::FxHashMap; use serde::Deserialize; +use strum::EnumCount; +use strum_macros::EnumCount; use tracing::{event, Level}; use crate::consts; -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Clone)] +#[derive(Debug, Clone, EnumCount, Deserialize)] pub enum Sentence { - MainTitle, + MainTitle = 0, CreateNewRecipe, UnpublishedRecipes, UntitledRecipe, @@ -107,6 +108,8 @@ pub enum Sentence { RecipeIngredientComment, } +const DEFAULT_LANGUAGE_CODE: &str = "en"; + #[derive(Clone)] pub struct Tr { lang: &'static Language, @@ -114,61 +117,48 @@ pub struct Tr { impl Tr { pub fn new(code: &str) -> Self { - for lang in TRANSLATIONS.iter() { - if lang.code == code { - return Self { lang }; - } + Self { + lang: get_language_translation(code), } - - event!( - Level::WARN, - "Unable to find translation for language {}", - code - ); - - Tr::new("en") } pub fn t(&self, sentence: Sentence) -> String { - match self.lang.translation.get(&sentence) { - Some(str) => str.clone(), - None => format!( - "Translation missing, lang: {}/{}, element: {:?}", - self.lang.name, self.lang.code, sentence - ), - } + //&'static str { + self.lang.get(sentence).to_string() + // match self.lang.translation.get(&sentence) { + // Some(str) => str.clone(), + // None => format!( + // "Translation missing, lang: {}/{}, element: {:?}", + // self.lang.name, self.lang.code, sentence + // ), + // } } pub fn tp(&self, sentence: Sentence, params: &[Box]) -> String { - match self.lang.translation.get(&sentence) { - Some(str) => { - let mut result = str.clone(); - for p in params { - result = result.replacen("{}", &p.to_string(), 1); - } - result - } - None => format!( - "Translation missing, lang: {}/{}, element: {:?}", - self.lang.name, self.lang.code, sentence - ), + // match self.lang.translation.get(&sentence) { + // Some(str) => { + // let mut result = str.clone(); + // for p in params { + // result = result.replacen("{}", &p.to_string(), 1); + // } + // result + // } + // None => format!( + // "Translation missing, lang: {}/{}, element: {:?}", + // self.lang.name, self.lang.code, sentence + // ), + // } + let text = self.lang.get(sentence); + let mut result = text.to_string(); + for p in params { + result = result.replacen("{}", &p.to_string(), 1); } + result } pub fn current_lang_code(&self) -> &str { &self.lang.code } - - pub fn available_languages() -> Vec<(&'static str, &'static str)> { - TRANSLATIONS - .iter() - .map(|tr| (tr.code.as_ref(), tr.name.as_ref())) - .collect() - } - - pub fn available_codes() -> Vec<&'static str> { - TRANSLATIONS.iter().map(|tr| tr.code.as_ref()).collect() - } } // #[macro_export] @@ -185,22 +175,98 @@ impl Tr { // }; // } -#[derive(Debug, Deserialize, Clone)] +#[derive(Debug, Deserialize)] +struct StoredLanguage { + code: String, + name: String, + translation: Vec<(Sentence, String)>, +} + +#[derive(Debug)] struct Language { code: String, name: String, - translation: FxHashMap, + translation: Vec, +} + +impl Language { + pub fn from_stored_language(stored_language: StoredLanguage) -> Self { + println!("!!!!!!!!!!!! {:?}", &stored_language.code); + Self { + code: stored_language.code, + name: stored_language.name, + translation: { + let mut translation = vec![String::new(); Sentence::COUNT]; + for (sentence, text) in stored_language.translation { + translation[sentence as usize] = text; + } + translation + }, + } + } + + pub fn get(&'static self, sentence: Sentence) -> &'static str { + let text: &str = self + .translation + .get(sentence.clone() as usize) + .unwrap() + .as_ref(); + if text.is_empty() && self.code != DEFAULT_LANGUAGE_CODE { + return get_language_translation(DEFAULT_LANGUAGE_CODE).get(sentence); + } + text + } +} + +pub fn available_languages() -> Vec<(&'static str, &'static str)> { + TRANSLATIONS + .iter() + .map(|tr| (tr.code.as_ref(), tr.name.as_ref())) + .collect() +} + +pub fn available_codes() -> Vec<&'static str> { + TRANSLATIONS.iter().map(|tr| tr.code.as_ref()).collect() +} + +fn get_language_translation(code: &str) -> &'static Language { + for lang in TRANSLATIONS.iter() { + if lang.code == code { + return lang; + } + } + + event!( + Level::WARN, + "Unable to find translation for language {}", + code + ); + + if code != DEFAULT_LANGUAGE_CODE { + get_language_translation(DEFAULT_LANGUAGE_CODE) + } else { + // 'DEFAULT_LANGUAGE_CODE' must exist. + panic!("Unable to find language {}", code); + } } static TRANSLATIONS: LazyLock> = LazyLock::new(|| match File::open(consts::TRANSLATION_FILE) { - Ok(file) => from_reader(file).unwrap_or_else(|error| { - panic!( - "Failed to read translation file {}: {}", - consts::TRANSLATION_FILE, - error - ) - }), + Ok(file) => { + let stored_languages: Vec = from_reader(file).unwrap_or_else(|error| { + { + panic!( + "Failed to read translation file {}: {}", + consts::TRANSLATION_FILE, + error + ) + } + }); + stored_languages + .into_iter() + .map(Language::from_stored_language) + .collect() + } Err(error) => { panic!( "Failed to open translation file {}: {}", diff --git a/backend/templates/base_with_header.html b/backend/templates/base_with_header.html index dfca040..c90a2b4 100644 --- a/backend/templates/base_with_header.html +++ b/backend/templates/base_with_header.html @@ -21,7 +21,7 @@ {% endmatch %} - {% for lang in Tr::available_languages() %} + {% for lang in translation::available_languages() %}