Update dependencies, add translation endpoint, and display a user message when logged in

This commit is contained in:
Greg Burri 2025-05-05 01:59:30 +02:00
parent 6b043620b8
commit 348b0f24e9
19 changed files with 170 additions and 34 deletions

View file

@ -31,13 +31,12 @@ sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono"] }
async-compression = { version = "0.4", features = ["tokio", "gzip"] }
askama = "0.14"
comrak = "0.38"
comrak = "0.39"
argon2 = { version = "0.5", features = ["default", "std"] }
rand_core = { version = "0.9", features = ["std"] }
rand = "0.9"
strum = "0.27"
strum_macros = "0.27"
strum = { version = "0.27", features = ["derive"] }
async-trait = "0.1"
lettre = { version = "0.11", default-features = false, features = [

View file

@ -233,6 +233,7 @@ pub fn make_service(
"/shopping_list/checked",
patch(services::ron::shopping_list::set_entry_checked),
)
.route("/translation", get(services::ron::get_translation))
.fallback(services::ron::not_found);
let fragments_routes = Router::new().route(

View file

@ -1,7 +1,7 @@
use chrono::{Duration, prelude::*};
use rand::distr::{Alphanumeric, SampleString};
use sqlx::Sqlite;
use strum_macros::Display;
use strum::Display;
use super::{Connection, DBError, Result};
use crate::{

View file

@ -1,13 +1,18 @@
use axum::{
debug_handler,
extract::{Extension, State},
extract::{Extension, Query, State},
http::{HeaderMap, StatusCode},
response::{IntoResponse, Result},
};
use axum_extra::extract::cookie::{Cookie, CookieJar, SameSite};
use common::ron_api;
use crate::{
app::Context, consts, data::db, data::model, ron_extractor::ExtractRon, ron_utils::ron_error,
app::Context,
consts,
data::{db, model},
ron_extractor::ExtractRon,
ron_utils::{ron_error, ron_response_ok},
};
pub mod calendar;
@ -36,6 +41,16 @@ pub async fn set_lang(
Ok((jar, StatusCode::OK))
}
#[debug_handler]
pub async fn get_translation(
Extension(context): Extension<Context>,
translation_id: Query<ron_api::Id>,
) -> Result<impl IntoResponse> {
Ok(ron_response_ok(ron_api::Value {
value: context.tr.t_from_id(translation_id.id),
}))
}
/*** 404 ***/
#[debug_handler]

View file

@ -58,7 +58,7 @@ pub async fn get(
pub async fn set_entry_checked(
State(connection): State<db::Connection>,
Extension(context): Extension<Context>,
ExtractRon(ron): ExtractRon<ron_api::Value<bool>>,
ExtractRon(ron): ExtractRon<ron_api::KeyValue<bool>>,
) -> Result<impl IntoResponse> {
check_user_rights_shopping_list_entry(&connection, &context.user, ron.id).await?;
Ok(ron_response_ok(

View file

@ -367,7 +367,15 @@ pub async fn sign_in_post(
.same_site(cookie::SameSite::Strict);
Ok((
jar.add(cookie),
Redirect::to(&format!("/{}/", context.tr.current_lang_code())).into_response(),
Redirect::to(&format!(
"/{}/?{}={}&{}={}",
context.tr.current_lang_code(),
common::consts::GET_PARAMETER_USER_MESSAGE,
Sentence::SignInSuccess as i64,
common::consts::GET_PARAMETER_USER_MESSAGE_LEVEL,
common::toast::Level::Success as usize
))
.into_response(),
))
}
}

View file

@ -5,11 +5,11 @@ use common::utils;
use ron::de::from_reader;
use serde::Deserialize;
use strum::EnumCount;
use strum_macros::EnumCount;
use tracing::warn;
use crate::consts;
#[repr(i64)]
#[derive(Debug, Clone, EnumCount, Deserialize)]
pub enum Sentence {
MainTitle = 0,
@ -34,6 +34,7 @@ pub enum Sentence {
SignInMenu,
SignInTitle,
SignInButton,
SignInSuccess,
WrongEmailOrPassword,
// Sign up page.
@ -188,6 +189,11 @@ impl Tr {
self.lang.get(sentence)
}
pub fn t_from_id(&self, sentence_id: i64) -> &'static str {
self.lang.get_from_id(sentence_id)
}
/// Translate a sentence with parameters.
pub fn tp(&self, sentence: Sentence, params: &[Box<dyn ToString + Send>]) -> String {
let text = self.lang.get(sentence);
let params_as_string: Vec<String> = params.iter().map(|p| p.to_string()).collect();
@ -246,6 +252,7 @@ impl Tr {
| "VE" // Venezuela.
| "ZW" // Zimbabwe.
=> Weekday::Sun,
"AF" // Afghanistan.
| "DZ" // Algeria.
| "BH" // Bahrain.
@ -262,6 +269,7 @@ impl Tr {
| "AE" // United Arab Emirates.
| "YE" // Yemen.
=> Weekday::Sat,
_ => Weekday::Mon,
}
}
@ -320,14 +328,17 @@ impl Language {
T: Borrow<Sentence>,
{
let sentence_cloned: Sentence = sentence.borrow().clone();
self.get_from_id(sentence_cloned as i64)
}
let text: &str = match self.translation.get(sentence_cloned as usize) {
pub fn get_from_id(&'static self, sentence_id: i64) -> &'static str {
let text: &str = match self.translation.get(sentence_id as usize) {
None => UNABLE_TO_FIND_TRANSLATION_MESSAGE,
Some(text) => text,
};
if text.is_empty() && self.code != DEFAULT_LANGUAGE_CODE {
return get_language_translation(DEFAULT_LANGUAGE_CODE).get(sentence);
return get_language_translation(DEFAULT_LANGUAGE_CODE).get_from_id(sentence_id);
}
text
}

View file

@ -25,7 +25,9 @@
(SignInMenu, "Sign in"),
(SignInTitle, "Sign in"),
(SignInButton, "Sign in"),
(SignInSuccess, "Sign in successful"),
(WrongEmailOrPassword, "Wrong email or password"),
(AccountMustBeValidatedFirst, "This account must be validated first"),
(InvalidEmail, "Invalid email"),
(PasswordDontMatch, "Passwords don't match"),
@ -175,7 +177,9 @@
(SignInMenu, "Se connecter"),
(SignInTitle, "Se connecter"),
(SignInButton, "Se connecter"),
(SignInSuccess, "Connexion réussie"),
(WrongEmailOrPassword, "Mot de passe ou email invalide"),
(AccountMustBeValidatedFirst, "Ce compte doit d'abord être validé"),
(InvalidEmail, "Adresse email invalide"),
(PasswordDontMatch, "Les mots de passe ne correspondent pas"),