From 800036ce497627e88c9648b59389ecdbf23f81d4 Mon Sep 17 00:00:00 2001 From: tuxmain Date: Sun, 4 Dec 2022 18:06:29 +0100 Subject: [PATCH] Translation args in templates --- locales/en.ftl | 9 ++++++- locales/fr.ftl | 6 ++++- src/helpers.rs | 54 ++++++++++++++++++++++++++++------------- src/locales.rs | 19 ++++++++++++++- src/main.rs | 6 +++-- src/server.rs | 4 +-- templates/comments.html | 4 +-- 7 files changed, 76 insertions(+), 26 deletions(-) diff --git a/locales/en.ftl b/locales/en.ftl index 611d147..0cf2300 100644 --- a/locales/en.ftl +++ b/locales/en.ftl @@ -5,7 +5,14 @@ admin_login-password_prompt = Password: admin_login-submit_button = Login admin_login-title = Admin login | Comments error-antispam = The edition quota from your IP is reached. You will be unblocked in { $antispam_timeout }s. -error-list = Whoops, the following error occurred: +error-comment-author_name_too_long = Author name length is { $len } but maximum is { $max_len }. +error-comment-email_too_long = E-mail length is { $len } but maximum is { $max_len }. +error-comment-text_too_long = Comment length is { $len } but maximum is { $max_len }. +error-list = + { $nb_errors -> + [one] Whoops, the following error occurred: + *[other] Whoops, the following { $nb_errors } errors occurred: + } comment_form-author = Your name: comment_form-email = Your email: comment_form-edit_button = Edit comment diff --git a/locales/fr.ftl b/locales/fr.ftl index 2bfd3d1..eb66ae1 100644 --- a/locales/fr.ftl +++ b/locales/fr.ftl @@ -5,7 +5,11 @@ admin_login-password_prompt = Mot de passe : admin_login-submit_button = S'authentifier admin_login-title = Authentification admin | Commentaires error-antispam = Le quota d'édition de votre adresse IP est atteint, elle sera débloquée dans { $antispam_timeout }s. -error-list = Oups, l'erreur suivante est survenue : +error-list = + { $nb_errors -> + [one] Oups, l'erreur suivante est survenue : + *[other] Oups, les { $nb_errors } erreurs suivantes sont survenues : + } comment_form-author = Votre nom : comment_form-email = Votre e-mail : comment_form-edit_button = Modifier diff --git a/src/helpers.rs b/src/helpers.rs index 099fff9..93c09bc 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,7 +1,9 @@ -use crate::{config::Config, db::*, queries::*}; +use crate::{config::Config, db::*, locales::Locales, queries::*}; +use fluent_bundle::FluentArgs; use log::error; use std::{net::IpAddr, str::FromStr}; +use unic_langid::LanguageIdentifier; pub fn new_pending_comment( comment: &Comment, @@ -173,27 +175,45 @@ pub fn get_client_addr( )) } -pub fn check_comment(config: &Config, comment: &CommentForm, errors: &mut Vec) { +pub fn check_comment( + config: &Config, + locales: &Locales, + langs: &[LanguageIdentifier], + comment: &CommentForm, + errors: &mut Vec, +) { if comment.author.len() > config.comment_author_max_len { - errors.push(format!( - "Author name length is {} but maximum is {}.", - comment.author.len(), - config.comment_author_max_len - )); + let mut args = FluentArgs::new(); + args.set("len", comment.author.len()); + args.set("max_len", config.comment_author_max_len); + errors.push( + locales + .tr(langs, "error-comment-author_name_too_long", Some(&args)) + .unwrap() + .to_string(), + ); } if comment.email.len() > config.comment_email_max_len { - errors.push(format!( - "E-mail length is {} but maximum is {}.", - comment.email.len(), - config.comment_email_max_len - )); + let mut args = FluentArgs::new(); + args.set("len", comment.email.len()); + args.set("max_len", config.comment_email_max_len); + errors.push( + locales + .tr(langs, "error-comment-email_too_long", Some(&args)) + .unwrap() + .to_string(), + ); } if comment.text.len() > config.comment_text_max_len { - errors.push(format!( - "Comment length is {} but maximum is {}.", - comment.text.len(), - config.comment_text_max_len - )); + let mut args = FluentArgs::new(); + args.set("len", comment.text.len()); + args.set("max_len", config.comment_text_max_len); + errors.push( + locales + .tr(langs, "error-comment-text_too_long", Some(&args)) + .unwrap() + .to_string(), + ); } } diff --git a/src/locales.rs b/src/locales.rs index f68f2d2..a23738d 100644 --- a/src/locales.rs +++ b/src/locales.rs @@ -1,6 +1,6 @@ use crate::config::Config; -use fluent_bundle::{bundle::FluentBundle, FluentArgs, FluentResource}; +use fluent_bundle::{bundle::FluentBundle, FluentArgs, FluentResource, FluentValue}; use fluent_langneg::{ accepted_languages, negotiate::filter_matches, negotiate_languages, NegotiationStrategy, }; @@ -101,3 +101,20 @@ pub fn get_time_lang(langs: &[LanguageIdentifier]) -> Option { } None } + +pub fn tera_to_fluent(val: &tera::Value) -> FluentValue { + match val { + tera::Value::Null => FluentValue::None, + tera::Value::Number(v) => { + if v.is_i64() { + FluentValue::Number(v.as_i64().unwrap().into()) + } else if v.is_u64() { + FluentValue::Number(v.as_u64().unwrap().into()) + } else { + FluentValue::Number(v.as_f64().unwrap().into()) + } + } + tera::Value::String(v) => FluentValue::String(v.into()), + _ => FluentValue::Error, + } +} diff --git a/src/main.rs b/src/main.rs index 318f141..5e5bdef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,7 +34,6 @@ async fn main() { let config = Box::leak(Box::new(config)); let locales = Box::leak(Box::new(locales::Locales::new(config))); - // TODO args templates.tera.register_function( "tr", Box::new( @@ -53,7 +52,10 @@ async fn main() { .ok_or_else(|| tera::Error::from("Missing argument `k`"))? .as_str() .ok_or_else(|| tera::Error::from("Argument `k` must be string"))?; - let res = locales.tr(&langs, key, None); + let args_iter = fluent_bundle::FluentArgs::from_iter( + args.iter().map(|(k, v)| (k, locales::tera_to_fluent(v))), + ); + let res = locales.tr(&langs, key, Some(&args_iter)); if res.is_none() { warn!("(calling `tr` in template) translation key `{key}` not found"); } diff --git a/src/server.rs b/src/server.rs index 6148e21..ab0880f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -286,7 +286,7 @@ async fn handle_post_comments( return Err(tide::Error::from_str(404, "No topic")) }; - helpers::check_comment(config, &query.comment, &mut errors); + helpers::check_comment(config, locales, &client_langs, &query.comment, &mut errors); if let Some(client_addr) = &client_addr { if antispam_enabled { @@ -360,7 +360,7 @@ async fn handle_post_comments( return Err(tide::Error::from_str(403, "Forbidden")); } - helpers::check_comment(config, &query.comment, &mut errors); + helpers::check_comment(config, locales, &client_langs, &query.comment, &mut errors); let comment_id = if let Ok(comment_id) = CommentId::from_base64(&query.id) { comment_id diff --git a/templates/comments.html b/templates/comments.html index 7cf683f..3960fa5 100644 --- a/templates/comments.html +++ b/templates/comments.html @@ -48,7 +48,7 @@
{% if new_comment_errors %} -

{{ tr(l=l,k="error-list")|safe }}

+

{{ tr(l=l,k="error-list",nb_errors=new_comment_errors|length)|safe }}

    {% for error in new_comment_errors %}
  • {{ error | safe }}
  • @@ -66,7 +66,7 @@ {% if edit_comment %} {% if edit_comment_errors %} -

    {{ tr(l=l,k="error-list")|safe }}

    +

    {{ tr(l=l,k="error-list",nb_errors=edit_comment_errors|length)|safe }}

      {% for error in edit_comment_errors %}
    • {{ error | safe }}