diff --git a/src/app.rs b/src/app.rs index 14e6b46..1ef756a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,5 +1,5 @@ use leptos::prelude::*; -use leptos_meta::{provide_meta_context, HashedStylesheet, MetaTags, Title}; +use leptos_meta::{provide_meta_context, HashedStylesheet, Html, MetaTags, Title}; use leptos_router::{ components::{Route, Router, Routes}, hooks::{use_location, use_navigate, use_query_map}, @@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize}; use crate::answers::{Answer, SelfTransitionAnswer, TransitionAnswers, TransitionItem}; use crate::auth::{current_user, User}; use crate::content::{is_qualified, render_inline_markdown, Alternative, Question, Responsible, SiteConfig, Transition}; +use crate::i18n::t; use crate::resource::{get_requirement_binding, get_requirement_options, get_resource}; /// The visible site name/wordmark - "portal" is just this codebase's @@ -68,8 +69,18 @@ pub fn App() -> impl IntoView { // context instead of fetching their own copy. let site = Resource::new(|| (), |_| get_site()); provide_context(site); + // The chrome's language, from site.yaml (default "en"); content + // speaks for itself. Components read this via context for t(). + let lang = Memo::new(move |_| { + site.get() + .and_then(|r| r.ok()) + .and_then(|s| s.lang) + .unwrap_or_else(|| "en".to_string()) + }); + provide_context(Lang(lang)); view! { + {move || { site.get() @@ -88,6 +99,15 @@ pub fn App() -> impl IntoView { } } +/// The site's chrome language as a context signal - see App. +#[derive(Clone, Copy)] +pub struct Lang(pub Memo); + +/// The current chrome language, for `t()` calls inside views. +fn lang() -> Memo { + expect_context::().0 +} + /// Every server-fn resource the pages read, created exactly once for /// the app's lifetime and handed down via context. Wrapper structs /// because a bare `Resource` context is claimed by whoever provides @@ -241,7 +261,7 @@ fn QuestionView( />
-

"This page follows from an answer you don't seem to carry yet."

+

{move || t(&lang().get(), "follows_answer")}

{label} @@ -269,7 +289,7 @@ fn QuestionView(
{if signed_in { - view! {

"This part of the site is for organizational owners — sign in with that account to take a look."

} + view! {

{move || t(&lang().get(), "owners_only")}

} .into_any() } else { view! { @@ -278,7 +298,7 @@ fn QuestionView( href=format!("/auth/login?redirect={question_id}") rel="external" > - "Sign in" + {move || t(&lang().get(), "sign_in")} } .into_any() @@ -371,7 +391,7 @@ fn QuestionNav(current_id: String, has_chain: bool) -> impl IntoView { .collect(); (!others.is_empty()).then(|| view! {