Add DE/EN language toggle with bilingual descriptions
- Language switcher in sidebar (DE/EN buttons, persists to localStorage) - i18n module with pick_desc/pick_name helpers for language-aware fallback - All detail/list pages use language context for names and descriptions - Species/Cultivar types updated with description_de/description_en - Common Name column added to species/families lists
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
use dioxus::prelude::*;
|
||||
use gloo_storage::{LocalStorage, Storage};
|
||||
|
||||
use crate::api;
|
||||
use crate::types::MeResponse;
|
||||
|
||||
/// Global language signal shared via context. Values: "de" or "en".
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Lang(pub Signal<String>);
|
||||
|
||||
#[derive(Routable, Clone, Debug, PartialEq)]
|
||||
#[rustfmt::skip]
|
||||
pub enum Route {
|
||||
@@ -43,6 +48,15 @@ pub fn App() -> Element {
|
||||
|
||||
#[component]
|
||||
fn Layout() -> Element {
|
||||
// Language state: load from localStorage, default "de"
|
||||
let lang_signal = use_signal(|| {
|
||||
LocalStorage::get::<String>("herbapi_lang").unwrap_or_else(|_| "de".to_string())
|
||||
});
|
||||
use_context_provider(|| Lang(lang_signal));
|
||||
|
||||
let mut lang = use_context::<Lang>().0;
|
||||
let current_lang = lang.read().clone();
|
||||
|
||||
// Try to get current user (may be None for public access)
|
||||
let auth = use_resource(|| async { api::get_current_user().await.ok() });
|
||||
let user: Option<MeResponse> = auth.read().as_ref().and_then(|r| r.clone());
|
||||
@@ -66,6 +80,26 @@ fn Layout() -> Element {
|
||||
NavLink { to: Route::SearchPage {}, label: "Search" }
|
||||
NavLink { to: Route::Sources {}, label: "Sources" }
|
||||
}
|
||||
div { class: "sidebar-lang",
|
||||
div { class: "lang-toggle",
|
||||
button {
|
||||
class: if current_lang == "de" { "lang-btn lang-btn-active" } else { "lang-btn" },
|
||||
onclick: move |_| {
|
||||
lang.set("de".to_string());
|
||||
let _ = LocalStorage::set("herbapi_lang", "de".to_string());
|
||||
},
|
||||
"DE"
|
||||
}
|
||||
button {
|
||||
class: if current_lang == "en" { "lang-btn lang-btn-active" } else { "lang-btn" },
|
||||
onclick: move |_| {
|
||||
lang.set("en".to_string());
|
||||
let _ = LocalStorage::set("herbapi_lang", "en".to_string());
|
||||
},
|
||||
"EN"
|
||||
}
|
||||
}
|
||||
}
|
||||
div { class: "sidebar-user",
|
||||
if let Some(ref u) = user {
|
||||
span { class: "user-name", "{u.nickname.as_deref().or(u.name.as_deref()).unwrap_or(&u.email)}" }
|
||||
|
||||
Reference in New Issue
Block a user