feat: add profile language preferences and refine toast, dropdown and history UI

This commit is contained in:
Mateusz Gruszczyński
2026-09-04 23:48:09 +02:00
parent f036240d5d
commit bf13587a71
42 changed files with 3971 additions and 357 deletions
+34 -2
View File
@@ -11,7 +11,7 @@ mod pages;
use axum::{
Json, Router,
extract::{DefaultBodyLimit, Request},
extract::{DefaultBodyLimit, Path, Request},
http::{HeaderMap, HeaderValue, Method, StatusCode, header},
middleware::{self, Next},
response::{IntoResponse, Response},
@@ -79,6 +79,8 @@ pub fn router(
.route("/w/{workspace_slug}", get(workspace))
.route("/w/{workspace_slug}/n/{note_slug}", get(note))
.route("/health", get(health))
.route("/lang", get(language_catalog))
.route("/lang/{code}", get(language_bundle))
.route("/robots.txt", get(robots_txt))
.route("/favicon.ico", get(favicon))
.route("/favicon.svg", get(favicon_svg))
@@ -240,6 +242,36 @@ pub fn router(
.with_state(state)
}
async fn language_catalog() -> Response {
let mut response = Json(crate::i18n::metadata()).into_response();
response.headers_mut().insert(
header::CACHE_CONTROL,
HeaderValue::from_static("public, max-age=300"),
);
response
}
async fn language_bundle(Path(code): Path<String>) -> Response {
let Some(source) = crate::i18n::source(&code) else {
return (
StatusCode::NOT_FOUND,
Json(serde_json::json!({ "error": "Language not found" })),
)
.into_response();
};
let mut response = source.into_response();
response.headers_mut().insert(
header::CONTENT_TYPE,
HeaderValue::from_static("application/json; charset=utf-8"),
);
response.headers_mut().insert(
header::CACHE_CONTROL,
HeaderValue::from_static("public, max-age=86400"),
);
response
}
async fn require_csrf_token(request: Request, next: Next) -> Response {
let method = request.method();
let unsafe_method = method == Method::POST
@@ -324,7 +356,7 @@ fn is_file_path(path: &str) -> bool {
}
fn is_asset_path(path: &str) -> bool {
path == "/assets" || path.starts_with("/assets/")
path == "/assets" || path.starts_with("/assets/") || path == "/lang" || path.starts_with("/lang/")
}
fn is_icon_path(path: &str) -> bool {