feat: localization support
This commit is contained in:
parent
e3e92a158a
commit
f48d78d03b
9 changed files with 106 additions and 26 deletions
|
|
@ -1 +1,6 @@
|
||||||
not-found = We couldn't find that page.
|
not-found = We couldn't find that page.
|
||||||
|
title = Hypergeometric Distribution Calculator
|
||||||
|
population = Population Size
|
||||||
|
successes = Successes in Population
|
||||||
|
sample = Sample Size
|
||||||
|
sample_successes = Successes in Sample
|
||||||
|
|
|
||||||
|
|
@ -1 +1,6 @@
|
||||||
not-found = No pudimos encontrar esta página.
|
not-found = No pudimos encontrar esta página.
|
||||||
|
title = Calculadora Distribución Hipergeométrica
|
||||||
|
population = Tamaño población
|
||||||
|
successes = Éxitos en la población
|
||||||
|
sample = Tamaño de la muestra
|
||||||
|
sample_successes = Éxitos en la muestra
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ h6 {
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
width: 80vw;
|
||||||
|
max-inline-size: 80vw;
|
||||||
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: var(--size-6);
|
margin: var(--size-6);
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +64,7 @@ form input {
|
||||||
|
|
||||||
form > div.results {
|
form > div.results {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 6em 6em 1fr;
|
grid-template-columns: 1fr 8em 5em 1fr;
|
||||||
min-width: 20em;
|
min-width: 20em;
|
||||||
max-width: 30em;
|
max-width: 30em;
|
||||||
width: 30vw;
|
width: 30vw;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
//! Hypergeometric Distribution Calculator
|
//! Hypergeometric Distribution Calculator
|
||||||
use leptos::html::ElementChild;
|
use leptos::html::ElementChild;
|
||||||
use leptos::prelude::{
|
use leptos::prelude::{
|
||||||
signal, ClassAttribute, Get, GlobalAttributes, OnTargetAttribute, PropAttribute, Set,
|
ClassAttribute, Get, GlobalAttributes, OnTargetAttribute, PropAttribute, Set, signal,
|
||||||
};
|
};
|
||||||
use leptos::{component, view, IntoView};
|
use leptos::{IntoView, component, view};
|
||||||
|
use leptos_fluent::move_tr;
|
||||||
|
|
||||||
use crate::calc::hyper_geometric;
|
use crate::calc::hyper_geometric;
|
||||||
|
|
||||||
|
|
@ -26,7 +27,7 @@ pub fn Calculator() -> impl IntoView {
|
||||||
view! {
|
view! {
|
||||||
<form>
|
<form>
|
||||||
<p>
|
<p>
|
||||||
<label for="population">Population Size</label>
|
<label for="population">{move_tr!("population")}</label>
|
||||||
<input
|
<input
|
||||||
id="population"
|
id="population"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -38,7 +39,7 @@ pub fn Calculator() -> impl IntoView {
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="successes">Successes in Population</label>
|
<label for="successes">{move_tr!("successes")}</label>
|
||||||
<input
|
<input
|
||||||
id="successes"
|
id="successes"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -51,7 +52,7 @@ pub fn Calculator() -> impl IntoView {
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="sample">Sample Size</label>
|
<label for="sample">{move_tr!("sample")}</label>
|
||||||
<input
|
<input
|
||||||
id="sample"
|
id="sample"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
@ -64,7 +65,7 @@ pub fn Calculator() -> impl IntoView {
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<label for="sample_successes">Successes in Sample</label>
|
<label for="sample_successes">{move_tr!("sample_successes")}</label>
|
||||||
<input
|
<input
|
||||||
id="sample_successes"
|
id="sample_successes"
|
||||||
type="number"
|
type="number"
|
||||||
|
|
|
||||||
55
src/components/localization.rs
Normal file
55
src/components/localization.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
//! Localization selector
|
||||||
|
|
||||||
|
use fluent_templates::static_loader;
|
||||||
|
use leptos::html::ElementChild;
|
||||||
|
use leptos::prelude::{Children, GlobalAttributes, OnAttribute, PropAttribute, Set};
|
||||||
|
use leptos::{IntoView, component, view};
|
||||||
|
use leptos_fluent::{Language, expect_i18n, leptos_fluent};
|
||||||
|
|
||||||
|
static_loader! {
|
||||||
|
pub static TRANSLATIONS = {
|
||||||
|
locales: "./locales",
|
||||||
|
fallback_language: "en",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This component provide localization context to every children component.
|
||||||
|
#[component]
|
||||||
|
pub fn I18n(children: Children) -> impl IntoView {
|
||||||
|
leptos_fluent! {
|
||||||
|
children: children(),
|
||||||
|
translations: [TRANSLATIONS],
|
||||||
|
locales: "./locales",
|
||||||
|
check_translations: "./src/**/*.rs",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[component]
|
||||||
|
pub fn LanguageSelector() -> impl IntoView {
|
||||||
|
// Use `expect_i18n()` to get the current i18n context:
|
||||||
|
let i18n = expect_i18n();
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<label for="language">"A/文:"</label>
|
||||||
|
<select id="language">
|
||||||
|
{move || {
|
||||||
|
i18n.languages.iter().map(|lang| render_language(lang)).collect::<Vec<_>>()
|
||||||
|
}}
|
||||||
|
</select>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_language(lang: &'static Language) -> impl IntoView {
|
||||||
|
// Passed as atrribute, `Language` is converted to their code,
|
||||||
|
// so `<input id=lang` becomes `<input id=lang.id.to_string()`
|
||||||
|
let i18n = expect_i18n();
|
||||||
|
view! {
|
||||||
|
<option
|
||||||
|
id=lang
|
||||||
|
value=lang
|
||||||
|
prop:selected=lang.is_active()
|
||||||
|
on:click=move |_| i18n.language.set(lang)
|
||||||
|
>
|
||||||
|
{lang.name}
|
||||||
|
</option>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
pub mod calculator;
|
pub mod calculator;
|
||||||
|
pub mod localization;
|
||||||
|
|
|
||||||
13
src/lib.rs
13
src/lib.rs
|
|
@ -1,6 +1,5 @@
|
||||||
use fluent_templates::static_loader;
|
|
||||||
use leptos::prelude::{AddAnyAttr, IntoAttribute};
|
use leptos::prelude::{AddAnyAttr, IntoAttribute};
|
||||||
use leptos::{component, view, IntoView};
|
use leptos::{IntoView, component, view};
|
||||||
use leptos_meta::*;
|
use leptos_meta::*;
|
||||||
use leptos_router::{components::*, path};
|
use leptos_router::{components::*, path};
|
||||||
|
|
||||||
|
|
@ -12,14 +11,6 @@ mod pages;
|
||||||
// Top-Level pages
|
// Top-Level pages
|
||||||
use crate::pages::home::Home;
|
use crate::pages::home::Home;
|
||||||
|
|
||||||
// Localization
|
|
||||||
static_loader! {
|
|
||||||
pub static TRANSLATIONS = {
|
|
||||||
locales: "./locales",
|
|
||||||
fallback_language: "en",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An app router which renders the homepage and handles 404's
|
/// An app router which renders the homepage and handles 404's
|
||||||
#[component]
|
#[component]
|
||||||
pub fn App() -> impl IntoView {
|
pub fn App() -> impl IntoView {
|
||||||
|
|
@ -30,7 +21,7 @@ pub fn App() -> impl IntoView {
|
||||||
<Html attr:lang="en" attr:dir="ltr" attr:data-theme="light" />
|
<Html attr:lang="en" attr:dir="ltr" attr:data-theme="light" />
|
||||||
|
|
||||||
// sets the document title
|
// sets the document title
|
||||||
<Title text="Welcome to Leptos CSR" />
|
<Title text="Hypergeometric Calculator" />
|
||||||
|
|
||||||
// injects metadata in the <head> of the page
|
// injects metadata in the <head> of the page
|
||||||
<Meta charset="UTF-8" />
|
<Meta charset="UTF-8" />
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,11 @@ use leptos::attr::global::ClassAttribute;
|
||||||
use leptos::error::ErrorBoundary;
|
use leptos::error::ErrorBoundary;
|
||||||
use leptos::html::ElementChild;
|
use leptos::html::ElementChild;
|
||||||
use leptos::prelude::{CollectView, Get};
|
use leptos::prelude::{CollectView, Get};
|
||||||
use leptos::{component, view, IntoView};
|
use leptos::{IntoView, component, view};
|
||||||
|
use leptos_fluent::move_tr;
|
||||||
|
|
||||||
use crate::components::calculator::Calculator;
|
use crate::components::calculator::Calculator;
|
||||||
|
use crate::components::localization::{I18n, LanguageSelector};
|
||||||
|
|
||||||
/// Default Home Page
|
/// Default Home Page
|
||||||
#[component]
|
#[component]
|
||||||
|
|
@ -28,13 +30,21 @@ pub fn Home() -> impl IntoView {
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
|
<I18n>
|
||||||
|
<header>
|
||||||
|
<LanguageSelector />
|
||||||
|
</header>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>"Hypergeometric Distribution Calculator"</h1>
|
<Title />
|
||||||
|
|
||||||
<div class="calculator">
|
|
||||||
<Calculator />
|
<Calculator />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</I18n>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Title
|
||||||
|
#[component]
|
||||||
|
pub fn Title() -> impl IntoView {
|
||||||
|
view! {<h1 class="title">{move_tr!("title")}</h1>}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
use leptos::html::ElementChild;
|
use leptos::html::ElementChild;
|
||||||
use leptos::{component, view, IntoView};
|
use leptos::{IntoView, component, view};
|
||||||
|
use leptos_fluent::move_tr;
|
||||||
|
|
||||||
|
use crate::components::localization::I18n;
|
||||||
|
|
||||||
/// 404 Not Found Page
|
/// 404 Not Found Page
|
||||||
#[component]
|
#[component]
|
||||||
pub fn NotFound() -> impl IntoView {
|
pub fn NotFound() -> impl IntoView {
|
||||||
view! { <h1>"We couldn't find that page."</h1> }
|
view! {
|
||||||
|
<I18n>
|
||||||
|
<h1>{move_tr!("not-found")}</h1>
|
||||||
|
</I18n>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue