From 88fa09755ff31b39b0454f0da58bc41a90263e89 Mon Sep 17 00:00:00 2001 From: cel 🌸 Date: Sat, 10 Feb 2024 06:54:25 +0000 Subject: add initial localisation --- src/error.rs | 1 + src/main.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++--------- src/templates.rs | 22 +++++++++++++++++----- 3 files changed, 63 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/error.rs b/src/error.rs index 611ce79..adaf77f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -56,6 +56,7 @@ impl ResponseError for BlossomError { Self: std::error::Error + Send + Sync + 'static, { templates::Error { + title: self.to_string(), status: self.status(), message: self.to_string(), } diff --git a/src/main.rs b/src/main.rs index 2f1a00b..de7bc73 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,6 +15,7 @@ mod utils; use std::{collections::HashSet, time::Duration}; use poem::http::StatusCode; +use poem::i18n::{I18NResources, Locale}; use poem::{ endpoint::EmbeddedFilesEndpoint, get, handler, @@ -44,7 +45,7 @@ type Result = std::result::Result; struct Static; #[handler] -async fn home(Data(reqwest): Data<&reqwest::Client>) -> templates::Home { +async fn home(Data(reqwest): Data<&reqwest::Client>, locale: Locale) -> templates::Home { let listenbrainz_client = listenbrainz::raw::Client::new(); let (live, listenbrainz, blogposts, poems) = tokio::join!( live::get_live_status(reqwest), @@ -59,20 +60,27 @@ async fn home(Data(reqwest): Data<&reqwest::Client>) -> templates::Home { let poems = poems.unwrap_or_default(); let poem = poems.choose(&mut rand::thread_rng()).cloned(); templates::Home { + title: locale.text("title").unwrap(), is_live, listenbrainz, blogposts, poem, + locale, } } // #[get("/blog/")] #[handler] -async fn blogpost(Path(blogpost): Path) -> Result { +async fn blogpost(Path(blogpost): Path, locale: Locale) -> Result { let blogpost = Blogpost::get_article(&blogpost).await?; Ok(templates::Blogpost { + title: blogpost + .subject() + .unwrap_or(locale.text("untitled").unwrap().as_str()) + .to_owned(), blogpost, filter_tags: HashSet::new(), + locale, }) } @@ -83,7 +91,10 @@ struct FilterTags { // #[get("/blog?")] #[handler] -async fn get_blog(filter_tags: Option>) -> Result { +async fn get_blog( + filter_tags: Option>, + locale: Locale, +) -> Result { let mut blogposts = Blogpost::get_articles().await?; let tags: Vec = posts::Post::get_tags(&blogposts) .into_iter() @@ -95,12 +106,15 @@ async fn get_blog(filter_tags: Option>) -> Result Result { let blogposts: Vec> = Blogpost::get_articles() @@ -132,8 +146,11 @@ async fn feed() -> Result { } #[handler] -async fn contact() -> templates::Contact { - templates::Contact +async fn contact(locale: Locale) -> templates::Contact { + templates::Contact { + title: locale.text("title-contact").unwrap(), + locale, + } } #[handler] @@ -142,21 +159,34 @@ async fn plants() -> Result<()> { } #[handler] -async fn get_poem(Path(poem): Path) -> Result { +async fn get_poem(Path(poem): Path, locale: Locale) -> Result { let poem = Poem::get_article(&poem).await?; - Ok(templates::Poem { poem, jiggle: 4 }) + Ok(templates::Poem { + title: (&poem.title) + .clone() + .unwrap_or(locale.text("untitled").unwrap()), + poem, + jiggle: 4, + locale, + }) } #[handler] -async fn get_poetry() -> Result { +async fn get_poetry(locale: Locale) -> Result { let mut poems = Poem::get_articles().await?; poems.sort_by_key(|poem| poem.created_at); poems.reverse(); - Ok(templates::Poetry { poems, jiggle: 16 }) + Ok(templates::Poetry { + title: locale.text("title-poetry").unwrap(), + poems, + jiggle: 16, + locale, + }) } async fn custom_error(err: poem::Error) -> impl IntoResponse { templates::Error { + title: err.to_string(), status: err.status(), message: err.to_string(), } @@ -171,6 +201,11 @@ async fn main() -> std::result::Result<(), std::io::Error> { // let mut skinny_data = mastodon_async::Data::default(); // skinny_data.base = Cow::from("https://skinnyver.se"); + let resources = I18NResources::builder() + .add_path("./resources") + .build() + .unwrap(); + let blossom = Route::new() .at("/", get(home)) .at("/blog", get(get_blog)) @@ -182,6 +217,7 @@ async fn main() -> std::result::Result<(), std::io::Error> { .at("/plants", get(plants)) .nest("/static/", EmbeddedFilesEndpoint::::new()) .catch_all_error(custom_error) + .data(resources) .with(Tracing) .with(AddData::new( reqwest::Client::builder() diff --git a/src/templates.rs b/src/templates.rs index 4bcb64b..2ab9c41 100644 --- a/src/templates.rs +++ b/src/templates.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use askama::Template; use poem::http::StatusCode; +use poem::i18n::Locale; use rand::{thread_rng, Rng}; use crate::poetry; @@ -16,56 +17,67 @@ mod filters { } } -#[derive(Template)] -#[template(path = "base.html")] -struct Base; - #[derive(Template)] #[template(path = "home.html")] pub struct Home { + pub title: String, pub is_live: bool, pub listenbrainz: NowPlayingData, pub blogposts: Vec, pub poem: Option, + pub locale: Locale, } #[derive(Template)] #[template(path = "blogpost.html")] pub struct Blogpost { + pub title: String, pub blogpost: blog::Blogpost, pub filter_tags: HashSet, + pub locale: Locale, } // filtertags, blogpost-panel #[derive(Template)] #[template(path = "blog.html")] pub struct Blog { + pub title: String, pub blogposts: Vec, pub tags: Vec, pub filter_tags: HashSet, + pub locale: Locale, } #[derive(Template)] #[template(path = "poem.html")] pub struct Poem { + pub title: String, pub poem: poetry::Poem, pub jiggle: isize, + pub locale: Locale, } #[derive(Template)] #[template(path = "poetry.html")] pub struct Poetry { + pub title: String, pub poems: Vec, pub jiggle: isize, + pub locale: Locale, } #[derive(Template)] #[template(path = "contact.html")] -pub struct Contact; +pub struct Contact { + pub title: String, + pub locale: Locale, +} #[derive(Template)] #[template(path = "error.html")] pub struct Error { + pub title: String, pub status: StatusCode, pub message: String, + // TODO: localize error page } -- cgit