forked from
smokesignal.events/smokesignal
i18n+filtering fork - fluent-templates v2
1use anyhow::Result;
2use axum::{
3 extract::State,
4 response::{IntoResponse, Redirect},
5};
6use axum_extra::extract::{
7 cookie::{Cookie, CookieJar, SameSite},
8 Cached, Form,
9};
10use minijinja::context as template_context;
11use serde::Deserialize;
12use std::{borrow::Cow, str::FromStr};
13use unic_langid::LanguageIdentifier;
14
15use crate::storage::handle::{handle_update_field, HandleField};
16
17use super::{
18 context::WebContext, errors::WebError, middleware_auth::Auth, middleware_i18n::COOKIE_LANG,
19 templates::render_alert,
20};
21
22#[derive(Deserialize, Clone)]
23pub struct LanguageForm {
24 language: String,
25}
26
27#[tracing::instrument(skip_all, err)]
28pub async fn handle_set_language(
29 State(web_context): State<WebContext>,
30 Cached(auth): Cached<Auth>,
31 jar: CookieJar,
32 Form(language_form): Form<LanguageForm>,
33) -> Result<impl IntoResponse, WebError> {
34 let default_context = template_context! {
35 current_handle => auth.0,
36 canonical_url => format!("https://{}/language", web_context.config.external_base),
37 };
38
39 let use_language = LanguageIdentifier::from_str(&language_form.language);
40 if use_language.is_err() {
41 return Ok(render_alert(
42 web_context.engine.clone(),
43 "en-us",
44 "Invalid language",
45 default_context,
46 )
47 .into_response());
48 }
49
50 let use_language = use_language.unwrap();
51
52 let found = web_context
53 .i18n_context
54 .supported_languages
55 .iter()
56 .find(|lang| lang.matches(&use_language, true, false));
57 if found.is_none() {
58 return Ok(render_alert(
59 web_context.engine.clone(),
60 "en-us",
61 "Invalid language",
62 default_context,
63 )
64 .into_response());
65 }
66 let found = found.unwrap();
67
68 if let Some(handle) = auth.0 {
69 if let Err(err) = handle_update_field(
70 &web_context.pool,
71 &handle.did,
72 HandleField::Language(Cow::Owned(found.to_string())),
73 )
74 .await
75 {
76 tracing::error!(error = ?err, "Failed to update language");
77 }
78 }
79
80 let mut cookie = Cookie::new(COOKIE_LANG, found.to_string());
81 cookie.set_path("/");
82 cookie.set_http_only(true);
83 cookie.set_secure(true);
84 cookie.set_same_site(Some(SameSite::Lax));
85
86 let updated_jar = jar.add(cookie);
87
88 Ok((updated_jar, Redirect::to("/")).into_response())
89}