♻️ Refactor code removing L10n component

This commit is contained in:
Manuel Cillero 2023-10-21 20:33:20 +02:00
parent f5cfc4442e
commit 0613278f7a
17 changed files with 148 additions and 229 deletions

View file

@ -82,8 +82,8 @@ impl ToString for BreakPoint {
mod html; mod html;
pub use html::{Html, COMPONENT_BASE_HTML}; pub use html::{Html, COMPONENT_BASE_HTML};
mod l10n; mod translate;
pub use l10n::{L10n, COMPONENT_BASE_L10N}; pub use translate::{Translate, COMPONENT_BASE_TRANSLATE};
mod wrapper; mod wrapper;
pub use wrapper::{Wrapper, WrapperType, COMPONENT_BASE_WRAPPER}; pub use wrapper::{Wrapper, WrapperType, COMPONENT_BASE_WRAPPER};

View file

@ -21,7 +21,6 @@ pub enum AnchorTarget {
} }
type AnchorIcon = TypedComponent<Icon>; type AnchorIcon = TypedComponent<Icon>;
type AnchorHtml = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
@ -32,7 +31,7 @@ pub struct Anchor {
classes : OptionClasses, classes : OptionClasses,
anchor_type: AnchorType, anchor_type: AnchorType,
href : OptionString, href : OptionString,
html : AnchorHtml, html : OptionTranslate,
left_icon : AnchorIcon, left_icon : AnchorIcon,
right_icon : AnchorIcon, right_icon : AnchorIcon,
target : AnchorTarget, target : AnchorTarget,
@ -77,7 +76,7 @@ impl ComponentTrait for Anchor {
target=[target] target=[target]
{ {
(self.left_icon().prepare(cx)) (self.left_icon().prepare(cx))
" " span { (self.html().prepare(cx)) } " " " " span { (self.html().escaped(cx.langid())) } " "
(self.right_icon().prepare(cx)) (self.right_icon().prepare(cx))
} }
}) })
@ -147,7 +146,7 @@ impl Anchor {
#[fn_builder] #[fn_builder]
pub fn alter_html(&mut self, html: L10n) -> &mut Self { pub fn alter_html(&mut self, html: L10n) -> &mut Self {
self.html.set(html); self.html.alter_value(html);
self self
} }
@ -189,7 +188,7 @@ impl Anchor {
&self.href &self.href
} }
pub fn html(&self) -> &AnchorHtml { pub fn html(&self) -> &OptionTranslate {
&self.html &self.html
} }

View file

@ -4,8 +4,6 @@ new_handle!(COMPONENT_BASE_BLOCK);
actions_for_component!(Block); actions_for_component!(Block);
type BlockTitle = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Block { pub struct Block {
@ -13,7 +11,7 @@ pub struct Block {
renderable: Renderable, renderable: Renderable,
id : OptionId, id : OptionId,
classes : OptionClasses, classes : OptionClasses,
title : BlockTitle, title : OptionTranslate,
stuff : ArcComponents, stuff : ArcComponents,
template : String, template : String,
} }
@ -47,7 +45,7 @@ impl ComponentTrait for Block {
let id = cx.required_id::<Block>(self.id()); let id = cx.required_id::<Block>(self.id());
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
div id=(id) class=[self.classes().get()] { div id=(id) class=[self.classes().get()] {
@if let Some(title) = self.title().get().into_string(cx) { @if let Some(title) = self.title().using(cx.langid()) {
h2 class="block-title" { (title) } h2 class="block-title" { (title) }
} }
div class="block-body" { div class="block-body" {
@ -91,7 +89,7 @@ impl Block {
#[fn_builder] #[fn_builder]
pub fn alter_title(&mut self, title: L10n) -> &mut Self { pub fn alter_title(&mut self, title: L10n) -> &mut Self {
self.title.set(title); self.title.alter_value(title);
self self
} }
@ -118,7 +116,7 @@ impl Block {
&self.classes &self.classes
} }
pub fn title(&self) -> &BlockTitle { pub fn title(&self) -> &OptionTranslate {
&self.title &self.title
} }

View file

@ -1,17 +1,15 @@
use crate::prelude::*; use crate::prelude::*;
use crate::LOCALES_PAGETOP;
new_handle!(COMPONENT_BASE_BRANDING); new_handle!(COMPONENT_BASE_BRANDING);
type SiteSlogan = TypedComponent<L10n>;
type SiteLogo = TypedComponent<Image>; type SiteLogo = TypedComponent<Image>;
#[rustfmt::skip] #[rustfmt::skip]
pub struct Branding { pub struct Branding {
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
name : String, app_name : String,
slogan : SiteSlogan, slogan : OptionTranslate,
logo : SiteLogo, logo : SiteLogo,
frontpage : FnContextualPath, frontpage : FnContextualPath,
} }
@ -22,8 +20,8 @@ impl Default for Branding {
Branding { Branding {
weight : Weight::default(), weight : Weight::default(),
renderable: Renderable::default(), renderable: Renderable::default(),
name : config::SETTINGS.app.name.to_owned(), app_name : config::SETTINGS.app.name.to_owned(),
slogan : SiteSlogan::default(), slogan : OptionTranslate::default(),
logo : SiteLogo::default(), logo : SiteLogo::default(),
frontpage : |_| "/", frontpage : |_| "/",
} }
@ -52,8 +50,8 @@ impl ComponentTrait for Branding {
} }
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let title = L10n::t("site_home", &LOCALES_PAGETOP).prepare(cx); let title = L10n::l("site_home").using(cx.langid());
let slogan = self.slogan().prepare(cx); let slogan = self.slogan().using(cx.langid()).unwrap_or_default();
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
div id=[self.id()] { div id=[self.id()] {
div class="pt-branding__wrapper" { div class="pt-branding__wrapper" {
@ -62,7 +60,9 @@ impl ComponentTrait for Branding {
} }
div class="pt-branding__text" { div class="pt-branding__text" {
div class="pt-branding__name" { div class="pt-branding__name" {
a href=(self.frontpage()(cx)) title=(title) rel="home" { (self.name()) } a href=(self.frontpage()(cx)) title=[title] rel="home" {
(self.app_name())
}
} }
@if !slogan.is_empty() { @if !slogan.is_empty() {
div class="pt-branding__slogan" { div class="pt-branding__slogan" {
@ -92,14 +92,14 @@ impl Branding {
} }
#[fn_builder] #[fn_builder]
pub fn alter_name(&mut self, name: impl Into<String>) -> &mut Self { pub fn alter_app_name(&mut self, app_name: impl Into<String>) -> &mut Self {
self.name = name.into(); self.app_name = app_name.into();
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_slogan(&mut self, slogan: L10n) -> &mut Self { pub fn alter_slogan(&mut self, slogan: L10n) -> &mut Self {
self.slogan = SiteSlogan::with(slogan); self.slogan.alter_value(slogan);
self self
} }
@ -117,11 +117,11 @@ impl Branding {
// Branding GETTERS. // Branding GETTERS.
pub fn name(&self) -> &String { pub fn app_name(&self) -> &String {
&self.name &self.app_name
} }
pub fn slogan(&self) -> &SiteSlogan { pub fn slogan(&self) -> &OptionTranslate {
&self.slogan &self.slogan
} }

View file

@ -10,8 +10,6 @@ pub enum ButtonType {
Reset, Reset,
} }
type ButtonValue = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Button { pub struct Button {
@ -20,7 +18,7 @@ pub struct Button {
classes : OptionClasses, classes : OptionClasses,
button_type: ButtonType, button_type: ButtonType,
name : OptionString, name : OptionString,
value : ButtonValue, value : OptionTranslate,
autofocus : OptionString, autofocus : OptionString,
disabled : OptionString, disabled : OptionString,
template : String, template : String,
@ -50,18 +48,17 @@ impl ComponentTrait for Button {
ButtonType::Reset => "reset", ButtonType::Reset => "reset",
}; };
let id = self.name().get().map(|name| concat_string!("edit-", name)); let id = self.name().get().map(|name| concat_string!("edit-", name));
let value = self.value().prepare(cx);
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
button button
type=(button_type) type=(button_type)
id=[id] id=[id]
class=[self.classes().get()] class=[self.classes().get()]
name=[self.name().get()] name=[self.name().get()]
value=(value) value=[self.value().using(cx.langid())]
autofocus=[self.autofocus().get()] autofocus=[self.autofocus().get()]
disabled=[self.disabled().get()] disabled=[self.disabled().get()]
{ {
(value) (self.value().escaped(cx.langid()))
} }
}) })
} }
@ -116,7 +113,7 @@ impl Button {
#[fn_builder] #[fn_builder]
pub fn alter_value(&mut self, value: L10n) -> &mut Self { pub fn alter_value(&mut self, value: L10n) -> &mut Self {
self.value.set(value); self.value.alter_value(value);
self self
} }
@ -158,7 +155,7 @@ impl Button {
&self.name &self.name
} }
pub fn value(&self) -> &ButtonValue { pub fn value(&self) -> &OptionTranslate {
&self.value &self.value
} }

View file

@ -13,9 +13,6 @@ pub enum InputType {
Url, Url,
} }
type InputLabel = TypedComponent<L10n>;
type InputHelpText = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Input { pub struct Input {
@ -25,7 +22,7 @@ pub struct Input {
input_type : InputType, input_type : InputType,
name : OptionName, name : OptionName,
value : OptionString, value : OptionString,
label : InputLabel, label : OptionTranslate,
size : Option<u16>, size : Option<u16>,
minlength : Option<u16>, minlength : Option<u16>,
maxlength : Option<u16>, maxlength : Option<u16>,
@ -35,7 +32,7 @@ pub struct Input {
disabled : OptionString, disabled : OptionString,
readonly : OptionString, readonly : OptionString,
required : OptionString, required : OptionString,
help_text : InputHelpText, help_text : OptionTranslate,
template : String, template : String,
} }
@ -70,8 +67,8 @@ impl ComponentTrait for Input {
InputType::Url => "url", InputType::Url => "url",
}; };
let id = self.name().get().map(|name| concat_string!("edit-", name)); let id = self.name().get().map(|name| concat_string!("edit-", name));
let label = self.label().prepare(cx); let label = self.label().using(cx.langid()).unwrap_or_default();
let description = self.help_text().prepare(cx); let description = self.help_text().using(cx.langid()).unwrap_or_default();
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
div class=[self.classes().get()] { div class=[self.classes().get()] {
@if !label.is_empty() { @if !label.is_empty() {
@ -195,7 +192,7 @@ impl Input {
#[fn_builder] #[fn_builder]
pub fn alter_label(&mut self, label: L10n) -> &mut Self { pub fn alter_label(&mut self, label: L10n) -> &mut Self {
self.label.set(label); self.label.alter_value(label);
self self
} }
@ -270,7 +267,7 @@ impl Input {
#[fn_builder] #[fn_builder]
pub fn alter_help_text(&mut self, help_text: L10n) -> &mut Self { pub fn alter_help_text(&mut self, help_text: L10n) -> &mut Self {
self.help_text.set(help_text); self.help_text.alter_value(help_text);
self self
} }
@ -298,7 +295,7 @@ impl Input {
&self.value &self.value
} }
pub fn label(&self) -> &InputLabel { pub fn label(&self) -> &OptionTranslate {
&self.label &self.label
} }
@ -338,7 +335,7 @@ impl Input {
&self.required &self.required
} }
pub fn help_text(&self) -> &InputHelpText { pub fn help_text(&self) -> &OptionTranslate {
&self.help_text &self.help_text
} }

View file

@ -25,8 +25,6 @@ pub enum HeadingDisplay {
Subtitle, Subtitle,
} }
type HeadingText = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
#[derive(Default)] #[derive(Default)]
pub struct Heading { pub struct Heading {
@ -35,7 +33,7 @@ pub struct Heading {
id : OptionId, id : OptionId,
classes : OptionClasses, classes : OptionClasses,
heading_type: HeadingType, heading_type: HeadingType,
text : HeadingText, text : OptionTranslate,
display : HeadingDisplay, display : HeadingDisplay,
template : String, template : String,
} }
@ -65,12 +63,12 @@ impl ComponentTrait for Heading {
let id = self.id(); let id = self.id();
let classes = self.classes().get(); let classes = self.classes().get();
PrepareMarkup::With(html! { @match &self.heading_type() { PrepareMarkup::With(html! { @match &self.heading_type() {
HeadingType::H1 => h1 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H1 => h1 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H2 => h2 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H2 => h2 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H3 => h3 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H3 => h3 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H4 => h4 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H4 => h4 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H5 => h5 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H5 => h5 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H6 => h6 id=[id] class=[classes] { (self.text().prepare(cx)) }, HeadingType::H6 => h6 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
}}) }})
} }
} }
@ -146,7 +144,7 @@ impl Heading {
#[fn_builder] #[fn_builder]
pub fn alter_text(&mut self, text: L10n) -> &mut Self { pub fn alter_text(&mut self, text: L10n) -> &mut Self {
self.text.set(text); self.text.alter_value(text);
self self
} }
@ -185,7 +183,7 @@ impl Heading {
&self.heading_type &self.heading_type
} }
pub fn text(&self) -> &HeadingText { pub fn text(&self) -> &OptionTranslate {
&self.text &self.text
} }

View file

@ -1,119 +0,0 @@
use crate::prelude::*;
use std::collections::HashMap;
new_handle!(COMPONENT_BASE_L10N);
#[derive(Default)]
pub enum L10nOp {
#[default]
None,
Text(&'static str),
Translated(&'static str, &'static Locales),
Escaped(&'static str, &'static Locales),
}
#[derive(Default)]
pub struct L10n {
op: L10nOp,
args: HashMap<&'static str, String>,
}
impl ComponentTrait for L10n {
fn new() -> Self {
L10n::default()
}
fn handle(&self) -> Handle {
COMPONENT_BASE_L10N
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
match self.op() {
L10nOp::None => PrepareMarkup::None,
L10nOp::Text(text) => PrepareMarkup::Text(text),
L10nOp::Translated(key, locales) => PrepareMarkup::With(html! {
(locales
.lookup_with_args(
cx.langid(),
key,
&self.args().iter().fold(HashMap::new(), |mut args, (key, value)| {
args.insert(key.to_string(), value.to_owned().into());
args
})
)
.unwrap_or(key.to_string())
)
}),
L10nOp::Escaped(key, locales) => PrepareMarkup::With(html! {
(PreEscaped(locales
.lookup_with_args(
cx.langid(),
key,
&self.args().iter().fold(HashMap::new(), |mut args, (key, value)| {
args.insert(key.to_string(), value.to_owned().into());
args
})
)
.unwrap_or(key.to_string())
))
}),
}
}
}
impl L10n {
pub fn n(text: &'static str) -> Self {
L10n {
op: L10nOp::Text(text),
..Default::default()
}
}
pub fn t(key: &'static str, locales: &'static Locales) -> Self {
L10n {
op: L10nOp::Translated(key, locales),
..Default::default()
}
}
pub fn e(key: &'static str, locales: &'static Locales) -> Self {
L10n {
op: L10nOp::Escaped(key, locales),
..Default::default()
}
}
// L10n BUILDER.
#[fn_builder]
pub fn alter_op(&mut self, op: L10nOp) -> &mut Self {
self.op = op;
self
}
#[fn_builder]
pub fn alter_arg(&mut self, arg: &'static str, value: impl Into<String>) -> &mut Self {
self.args.insert(arg, value.into());
self
}
pub fn clear_args(&mut self) -> &mut Self {
self.args.drain();
self
}
// L10n GETTERS.
pub fn op(&self) -> &L10nOp {
&self.op
}
pub fn args(&self) -> &HashMap<&str, String> {
&self.args
}
pub fn into_string(&self, cx: &mut Context) -> Option<String> {
self.prepare_component(cx).into_string()
}
}

View file

@ -4,11 +4,10 @@ use super::{Megamenu, Submenu};
new_handle!(COMPONENT_BASE_MENU_ITEM); new_handle!(COMPONENT_BASE_MENU_ITEM);
type Label = TypedComponent<L10n>; type Label = L10n;
type Content = TypedComponent<Html>; type Content = TypedComponent<Html>;
type SubmenuItems = TypedComponent<Submenu>; type SubmenuItems = TypedComponent<Submenu>;
type MegamenuGroups = TypedComponent<Megamenu>; type MegamenuGroups = TypedComponent<Megamenu>;
type Description = TypedComponent<L10n>;
#[derive(Default)] #[derive(Default)]
pub enum ItemType { pub enum ItemType {
@ -30,7 +29,7 @@ pub struct Item {
weight : Weight, weight : Weight,
renderable : Renderable, renderable : Renderable,
item_type : ItemType, item_type : ItemType,
description: Description, description: OptionTranslate,
} }
impl ComponentTrait for Item { impl ComponentTrait for Item {
@ -51,27 +50,27 @@ impl ComponentTrait for Item {
} }
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let description = self.description.get().into_string(cx); let description = self.description.using(cx.langid());
match self.item_type() { match self.item_type() {
ItemType::Void => PrepareMarkup::None, ItemType::Void => PrepareMarkup::None,
ItemType::Label(label) => PrepareMarkup::With(html! { ItemType::Label(label) => PrepareMarkup::With(html! {
li class="pt-menu__label" { li class="pt-menu__label" {
span title=[description] { span title=[description] {
(label.prepare(cx)) (label.escaped(cx.langid()))
} }
} }
}), }),
ItemType::Link(label, path) => PrepareMarkup::With(html! { ItemType::Link(label, path) => PrepareMarkup::With(html! {
li class="pt-menu__link" { li class="pt-menu__link" {
a href=(path(cx)) title=[description] { a href=(path(cx)) title=[description] {
(label.prepare(cx)) (label.escaped(cx.langid()))
} }
} }
}), }),
ItemType::LinkBlank(label, path) => PrepareMarkup::With(html! { ItemType::LinkBlank(label, path) => PrepareMarkup::With(html! {
li class="pt-menu__link" { li class="pt-menu__link" {
a href=(path(cx)) title=[description] target="_blank" { a href=(path(cx)) title=[description] target="_blank" {
(label.prepare(cx)) (label.escaped(cx.langid()))
} }
} }
}), }),
@ -83,7 +82,7 @@ impl ComponentTrait for Item {
ItemType::Submenu(label, submenu) => PrepareMarkup::With(html! { ItemType::Submenu(label, submenu) => PrepareMarkup::With(html! {
li class="pt-menu__children" { li class="pt-menu__children" {
a href="#" title=[description] { a href="#" title=[description] {
(label.prepare(cx)) i class="pt-menu__icon bi-chevron-down" {} (label.escaped(cx.langid())) i class="pt-menu__icon bi-chevron-down" {}
} }
div class="pt-menu__subs" { div class="pt-menu__subs" {
(submenu.prepare(cx)) (submenu.prepare(cx))
@ -93,7 +92,7 @@ impl ComponentTrait for Item {
ItemType::Megamenu(label, megamenu) => PrepareMarkup::With(html! { ItemType::Megamenu(label, megamenu) => PrepareMarkup::With(html! {
li class="pt-menu__children" { li class="pt-menu__children" {
a href="#" title=[description] { a href="#" title=[description] {
(label.prepare(cx)) i class="pt-menu__icon bi-chevron-down" {} (label.escaped(cx.langid())) i class="pt-menu__icon bi-chevron-down" {}
} }
div class="pt-menu__subs pt-menu__mega" { div class="pt-menu__subs pt-menu__mega" {
(megamenu.prepare(cx)) (megamenu.prepare(cx))
@ -107,21 +106,21 @@ impl ComponentTrait for Item {
impl Item { impl Item {
pub fn label(label: L10n) -> Self { pub fn label(label: L10n) -> Self {
Item { Item {
item_type: ItemType::Label(Label::with(label)), item_type: ItemType::Label(label),
..Default::default() ..Default::default()
} }
} }
pub fn link(label: L10n, path: FnContextualPath) -> Self { pub fn link(label: L10n, path: FnContextualPath) -> Self {
Item { Item {
item_type: ItemType::Link(Label::with(label), path), item_type: ItemType::Link(label, path),
..Default::default() ..Default::default()
} }
} }
pub fn link_blank(label: L10n, path: FnContextualPath) -> Self { pub fn link_blank(label: L10n, path: FnContextualPath) -> Self {
Item { Item {
item_type: ItemType::LinkBlank(Label::with(label), path), item_type: ItemType::LinkBlank(label, path),
..Default::default() ..Default::default()
} }
} }
@ -135,14 +134,14 @@ impl Item {
pub fn submenu(label: L10n, submenu: Submenu) -> Self { pub fn submenu(label: L10n, submenu: Submenu) -> Self {
Item { Item {
item_type: ItemType::Submenu(Label::with(label), SubmenuItems::with(submenu)), item_type: ItemType::Submenu(label, SubmenuItems::with(submenu)),
..Default::default() ..Default::default()
} }
} }
pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self { pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self {
Item { Item {
item_type: ItemType::Megamenu(Label::with(label), MegamenuGroups::with(megamenu)), item_type: ItemType::Megamenu(label, MegamenuGroups::with(megamenu)),
..Default::default() ..Default::default()
} }
} }
@ -163,7 +162,7 @@ impl Item {
#[fn_builder] #[fn_builder]
pub fn alter_description(&mut self, text: L10n) -> &mut Self { pub fn alter_description(&mut self, text: L10n) -> &mut Self {
self.description.set(text); self.description.alter_value(text);
self self
} }
@ -173,7 +172,7 @@ impl Item {
&self.item_type &self.item_type
} }
pub fn description(&self) -> &Description { pub fn description(&self) -> &OptionTranslate {
&self.description &self.description
} }
} }

View file

@ -1,5 +1,4 @@
use crate::prelude::*; use crate::prelude::*;
use crate::LOCALES_PAGETOP;
use super::Item; use super::Item;
@ -68,7 +67,7 @@ impl ComponentTrait for Menu {
button button
type="button" type="button"
class="pt-menu__trigger" class="pt-menu__trigger"
title=[L10n::t("menu_toggle", &LOCALES_PAGETOP).into_string(cx)] title=[L10n::l("menu_toggle").using(cx.langid())]
{ {
span {} span {} span {} span {} span {} span {}
} }

View file

@ -4,7 +4,6 @@ use super::Item;
new_handle!(COMPONENT_BASE_MENU_SUBMENU); new_handle!(COMPONENT_BASE_MENU_SUBMENU);
type TitleSubmenu = TypedComponent<L10n>;
type Items = TypedComponents<Item>; type Items = TypedComponents<Item>;
#[rustfmt::skip] #[rustfmt::skip]
@ -13,7 +12,7 @@ pub struct Submenu {
weight : Weight, weight : Weight,
renderable: Renderable, renderable: Renderable,
id : OptionId, id : OptionId,
title : TitleSubmenu, title : OptionTranslate,
items : Items, items : Items,
} }
@ -41,7 +40,7 @@ impl ComponentTrait for Submenu {
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
div id=[self.id()] class="pt-menu__items" { div id=[self.id()] class="pt-menu__items" {
@if let Some(title) = self.title().get().into_string(cx) { @if let Some(title) = self.title().using(cx.langid()) {
h4 class="pt-menu__title" { (title) } h4 class="pt-menu__title" { (title) }
} }
ul { ul {
@ -75,7 +74,7 @@ impl Submenu {
#[fn_builder] #[fn_builder]
pub fn alter_title(&mut self, title: L10n) -> &mut Self { pub fn alter_title(&mut self, title: L10n) -> &mut Self {
self.title.set(title); self.title.alter_value(title);
self self
} }
@ -92,7 +91,7 @@ impl Submenu {
// Submenu GETTERS. // Submenu GETTERS.
pub fn title(&self) -> &TitleSubmenu { pub fn title(&self) -> &OptionTranslate {
&self.title &self.title
} }

View file

@ -60,7 +60,11 @@ impl ComponentTrait for Paragraph {
impl Paragraph { impl Paragraph {
pub fn with(component: impl ComponentTrait) -> Self { pub fn with(component: impl ComponentTrait) -> Self {
Paragraph::new().with_component(component) Paragraph::new().add_component(component)
}
pub fn translated(l10n: L10n) -> Self {
Paragraph::new().add_translated(l10n)
} }
// Paragraph BUILDER. // Paragraph BUILDER.
@ -89,11 +93,17 @@ impl Paragraph {
self self
} }
pub fn with_component(mut self, component: impl ComponentTrait) -> Self { pub fn add_component(mut self, component: impl ComponentTrait) -> Self {
self.stuff.alter(ArcOp::Add(ArcComponent::with(component))); self.stuff.alter(ArcOp::Add(ArcComponent::with(component)));
self self
} }
pub fn add_translated(mut self, l10n: L10n) -> Self {
self.stuff
.alter(ArcOp::Add(ArcComponent::with(Translate::with(l10n))));
self
}
#[fn_builder] #[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self { pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op); self.stuff.alter(op);

View file

@ -1,5 +1,4 @@
use crate::prelude::*; use crate::prelude::*;
use crate::LOCALES_PAGETOP;
new_handle!(COMPONENT_BASE_POWEREDBY); new_handle!(COMPONENT_BASE_POWEREDBY);
@ -51,10 +50,10 @@ impl ComponentTrait for PoweredBy {
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup { fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let logo = match self.logo() { let logo = match self.logo() {
PoweredByLogo::Color => { PoweredByLogo::Color => {
let logo_txt = L10n::t("pagetop_logo", &LOCALES_PAGETOP); let logo_txt = &L10n::l("pagetop_logo").using(cx.langid());
html! { html! {
span class="pt-pagetop__logo" aria-label=[logo_txt.into_string(cx)] { span class="pt-pagetop__logo" aria-label=[logo_txt] {
img src="/base/pagetop-logo.svg" alt=[logo_txt.into_string(cx)] {} img src="/base/pagetop-logo.svg" alt=[logo_txt] {}
} }
} }
} }
@ -64,17 +63,19 @@ impl ComponentTrait for PoweredBy {
_ => html! {}, _ => html! {},
}; };
let mut credits = L10n::e("poweredby_pagetop", &LOCALES_PAGETOP).with_arg( let credits = L10n::l("poweredby_pagetop")
"pagetop_link", .with_arg(
"<a href=\"https://crates.io/crates/pagetop\">PageTop</a>", "pagetop_link",
); "<a href=\"https://crates.io/crates/pagetop\">PageTop</a>",
)
.escaped(cx.langid());
PrepareMarkup::With(html! { PrepareMarkup::With(html! {
div id=[self.id()] { div id=[self.id()] {
@if let Some(c) = self.copyright() { @if let Some(c) = self.copyright() {
span class="copyright" { (c) "." } " " span class="copyright" { (c) "." } " "
} }
span class="powered" { (credits.prepare(cx)) " " (logo) } span class="powered" { (credits) " " (logo) }
} }
}) })
} }
@ -120,10 +121,10 @@ impl PoweredBy {
// PoweredBy PRIVATE. // PoweredBy PRIVATE.
fn logo_line(&self, r: u8, g: u8, b: u8, cx: &mut Context) -> Markup { fn logo_line(&self, r: u8, g: u8, b: u8, cx: &mut Context) -> Markup {
let logo_txt = L10n::t("pagetop_logo", &LOCALES_PAGETOP); let logo_txt = L10n::l("pagetop_logo").using(cx.langid());
let logo_rgb = format!("rgb({},{},{})", r, g, b); let logo_rgb = format!("rgb({},{},{})", r, g, b);
html! { html! {
span class="pt-pagetop__logo" aria-label=[logo_txt.into_string(cx)] { span class="pt-pagetop__logo" aria-label=[logo_txt] {
svg viewBox="0 0 1614 1614" xmlns="http://www.w3.org/2000/svg" role="img" { svg viewBox="0 0 1614 1614" xmlns="http://www.w3.org/2000/svg" role="img" {
path fill=(logo_rgb) d="M 1573,357 L 1415,357 C 1400,357 1388,369 1388,383 L 1388,410 1335,410 1335,357 C 1335,167 1181,13 992,13 L 621,13 C 432,13 278,167 278,357 L 278,410 225,410 225,383 C 225,369 213,357 198,357 L 40,357 C 25,357 13,369 13,383 L 13,648 C 13,662 25,674 40,674 L 198,674 C 213,674 225,662 225,648 L 225,621 278,621 278,1256 C 278,1446 432,1600 621,1600 L 992,1600 C 1181,1600 1335,1446 1335,1256 L 1335,621 1388,621 1388,648 C 1388,662 1400,674 1415,674 L 1573,674 C 1588,674 1600,662 1600,648 L 1600,383 C 1600,369 1588,357 1573,357 L 1573,357 1573,357 Z M 66,410 L 172,410 172,621 66,621 66,410 66,410 Z M 1282,357 L 1282,488 C 1247,485 1213,477 1181,464 L 1196,437 C 1203,425 1199,409 1186,401 1174,394 1158,398 1150,411 L 1133,440 C 1105,423 1079,401 1056,376 L 1075,361 C 1087,352 1089,335 1079,324 1070,313 1054,311 1042,320 L 1023,335 C 1000,301 981,263 967,221 L 1011,196 C 1023,189 1028,172 1021,160 1013,147 997,143 984,150 L 953,168 C 945,136 941,102 940,66 L 992,66 C 1152,66 1282,197 1282,357 L 1282,357 1282,357 Z M 621,66 L 674,66 674,225 648,225 C 633,225 621,237 621,251 621,266 633,278 648,278 L 674,278 674,357 648,357 C 633,357 621,369 621,383 621,398 633,410 648,410 L 674,410 674,489 648,489 C 633,489 621,501 621,516 621,530 633,542 648,542 L 664,542 C 651,582 626,623 600,662 583,653 563,648 542,648 469,648 410,707 410,780 410,787 411,794 412,801 388,805 361,806 331,806 L 331,357 C 331,197 461,66 621,66 L 621,66 621,66 Z M 621,780 C 621,824 586,859 542,859 498,859 463,824 463,780 463,736 498,701 542,701 586,701 621,736 621,780 L 621,780 621,780 Z M 225,463 L 278,463 278,569 225,569 225,463 225,463 Z M 992,1547 L 621,1547 C 461,1547 331,1416 331,1256 L 331,859 C 367,859 400,858 431,851 454,888 495,912 542,912 615,912 674,853 674,780 674,747 662,718 642,695 675,645 706,594 720,542 L 780,542 C 795,542 807,530 807,516 807,501 795,489 780,489 L 727,489 727,410 780,410 C 795,410 807,398 807,383 807,369 795,357 780,357 L 727,357 727,278 780,278 C 795,278 807,266 807,251 807,237 795,225 780,225 L 727,225 727,66 887,66 C 889,111 895,155 905,196 L 869,217 C 856,224 852,240 859,253 864,261 873,266 882,266 887,266 891,265 895,263 L 921,248 C 937,291 958,331 983,367 L 938,403 C 926,412 925,429 934,440 939,447 947,450 954,450 960,450 966,448 971,444 L 1016,408 C 1043,438 1074,465 1108,485 L 1084,527 C 1076,539 1081,555 1093,563 1098,565 1102,566 1107,566 1116,566 1125,561 1129,553 L 1155,509 C 1194,527 1237,538 1282,541 L 1282,1256 C 1282,1416 1152,1547 992,1547 L 992,1547 992,1547 Z M 1335,463 L 1388,463 1388,569 1335,569 1335,463 1335,463 Z M 1441,410 L 1547,410 1547,621 1441,621 1441,410 1441,410 Z" {} path fill=(logo_rgb) d="M 1573,357 L 1415,357 C 1400,357 1388,369 1388,383 L 1388,410 1335,410 1335,357 C 1335,167 1181,13 992,13 L 621,13 C 432,13 278,167 278,357 L 278,410 225,410 225,383 C 225,369 213,357 198,357 L 40,357 C 25,357 13,369 13,383 L 13,648 C 13,662 25,674 40,674 L 198,674 C 213,674 225,662 225,648 L 225,621 278,621 278,1256 C 278,1446 432,1600 621,1600 L 992,1600 C 1181,1600 1335,1446 1335,1256 L 1335,621 1388,621 1388,648 C 1388,662 1400,674 1415,674 L 1573,674 C 1588,674 1600,662 1600,648 L 1600,383 C 1600,369 1588,357 1573,357 L 1573,357 1573,357 Z M 66,410 L 172,410 172,621 66,621 66,410 66,410 Z M 1282,357 L 1282,488 C 1247,485 1213,477 1181,464 L 1196,437 C 1203,425 1199,409 1186,401 1174,394 1158,398 1150,411 L 1133,440 C 1105,423 1079,401 1056,376 L 1075,361 C 1087,352 1089,335 1079,324 1070,313 1054,311 1042,320 L 1023,335 C 1000,301 981,263 967,221 L 1011,196 C 1023,189 1028,172 1021,160 1013,147 997,143 984,150 L 953,168 C 945,136 941,102 940,66 L 992,66 C 1152,66 1282,197 1282,357 L 1282,357 1282,357 Z M 621,66 L 674,66 674,225 648,225 C 633,225 621,237 621,251 621,266 633,278 648,278 L 674,278 674,357 648,357 C 633,357 621,369 621,383 621,398 633,410 648,410 L 674,410 674,489 648,489 C 633,489 621,501 621,516 621,530 633,542 648,542 L 664,542 C 651,582 626,623 600,662 583,653 563,648 542,648 469,648 410,707 410,780 410,787 411,794 412,801 388,805 361,806 331,806 L 331,357 C 331,197 461,66 621,66 L 621,66 621,66 Z M 621,780 C 621,824 586,859 542,859 498,859 463,824 463,780 463,736 498,701 542,701 586,701 621,736 621,780 L 621,780 621,780 Z M 225,463 L 278,463 278,569 225,569 225,463 225,463 Z M 992,1547 L 621,1547 C 461,1547 331,1416 331,1256 L 331,859 C 367,859 400,858 431,851 454,888 495,912 542,912 615,912 674,853 674,780 674,747 662,718 642,695 675,645 706,594 720,542 L 780,542 C 795,542 807,530 807,516 807,501 795,489 780,489 L 727,489 727,410 780,410 C 795,410 807,398 807,383 807,369 795,357 780,357 L 727,357 727,278 780,278 C 795,278 807,266 807,251 807,237 795,225 780,225 L 727,225 727,66 887,66 C 889,111 895,155 905,196 L 869,217 C 856,224 852,240 859,253 864,261 873,266 882,266 887,266 891,265 895,263 L 921,248 C 937,291 958,331 983,367 L 938,403 C 926,412 925,429 934,440 939,447 947,450 954,450 960,450 966,448 971,444 L 1016,408 C 1043,438 1074,465 1108,485 L 1084,527 C 1076,539 1081,555 1093,563 1098,565 1102,566 1107,566 1116,566 1125,561 1129,553 L 1155,509 C 1194,527 1237,538 1282,541 L 1282,1256 C 1282,1416 1152,1547 992,1547 L 992,1547 992,1547 Z M 1335,463 L 1388,463 1388,569 1335,569 1335,463 1335,463 Z M 1441,410 L 1547,410 1547,621 1441,621 1441,410 1441,410 Z" {}
path fill=(logo_rgb) d="M 1150,1018 L 463,1018 C 448,1018 436,1030 436,1044 L 436,1177 C 436,1348 545,1468 701,1468 L 912,1468 C 1068,1468 1177,1348 1177,1177 L 1177,1044 C 1177,1030 1165,1018 1150,1018 L 1150,1018 1150,1018 Z M 912,1071 L 1018,1071 1018,1124 912,1124 912,1071 912,1071 Z M 489,1071 L 542,1071 542,1124 489,1124 489,1071 489,1071 Z M 701,1415 L 700,1415 C 701,1385 704,1352 718,1343 731,1335 759,1341 795,1359 802,1363 811,1363 818,1359 854,1341 882,1335 895,1343 909,1352 912,1385 913,1415 L 912,1415 701,1415 701,1415 701,1415 Z M 1124,1177 C 1124,1296 1061,1384 966,1408 964,1365 958,1320 922,1298 894,1281 856,1283 807,1306 757,1283 719,1281 691,1298 655,1320 649,1365 647,1408 552,1384 489,1296 489,1177 L 569,1177 C 583,1177 595,1165 595,1150 L 595,1071 859,1071 859,1150 C 859,1165 871,1177 886,1177 L 1044,1177 C 1059,1177 1071,1165 1071,1150 L 1071,1071 1124,1071 1124,1177 1124,1177 1124,1177 Z" {} path fill=(logo_rgb) d="M 1150,1018 L 463,1018 C 448,1018 436,1030 436,1044 L 436,1177 C 436,1348 545,1468 701,1468 L 912,1468 C 1068,1468 1177,1348 1177,1177 L 1177,1044 C 1177,1030 1165,1018 1150,1018 L 1150,1018 1150,1018 Z M 912,1071 L 1018,1071 1018,1124 912,1124 912,1071 912,1071 Z M 489,1071 L 542,1071 542,1124 489,1124 489,1071 489,1071 Z M 701,1415 L 700,1415 C 701,1385 704,1352 718,1343 731,1335 759,1341 795,1359 802,1363 811,1363 818,1359 854,1341 882,1335 895,1343 909,1352 912,1385 913,1415 L 912,1415 701,1415 701,1415 701,1415 Z M 1124,1177 C 1124,1296 1061,1384 966,1408 964,1365 958,1320 922,1298 894,1281 856,1283 807,1306 757,1283 719,1281 691,1298 655,1320 649,1365 647,1408 552,1384 489,1296 489,1177 L 569,1177 C 583,1177 595,1165 595,1150 L 595,1071 859,1071 859,1150 C 859,1165 871,1177 886,1177 L 1044,1177 C 1059,1177 1071,1165 1071,1150 L 1071,1071 1124,1071 1124,1177 1124,1177 1124,1177 Z" {}

View file

@ -0,0 +1,40 @@
use crate::prelude::*;
new_handle!(COMPONENT_BASE_TRANSLATE);
#[derive(Default)]
pub struct Translate(L10n);
impl ComponentTrait for Translate {
fn new() -> Self {
Translate::default()
}
fn handle(&self) -> Handle {
COMPONENT_BASE_TRANSLATE
}
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
PrepareMarkup::With(self.l10n().escaped(cx.langid()))
}
}
impl Translate {
pub fn with(l10n: L10n) -> Self {
Translate(l10n)
}
// Translate BUILDER.
#[fn_builder]
pub fn alter_l10n(&mut self, l10n: L10n) -> &mut Self {
self.0 = l10n;
self
}
// Translate GETTERS.
pub fn l10n(&self) -> &L10n {
&self.0
}
}

View file

@ -1,6 +1,6 @@
use crate::base::component::L10n;
use crate::core::action::Action; use crate::core::action::Action;
use crate::core::theme::ThemeRef; use crate::core::theme::ThemeRef;
use crate::locale::L10n;
use crate::{actions, service, util, Handle}; use crate::{actions, service, util, Handle};
#[cfg(feature = "database")] #[cfg(feature = "database")]

View file

@ -3,7 +3,7 @@ pub use error403::ERROR_403;
mod error404; mod error404;
pub use error404::ERROR_404; pub use error404::ERROR_404;
use crate::base::component::L10n; use crate::locale::L10n;
use crate::response::{page::Page, ResponseError}; use crate::response::{page::Page, ResponseError};
use crate::service::http::{header::ContentType, StatusCode}; use crate::service::http::{header::ContentType, StatusCode};
use crate::service::{HttpRequest, HttpResponse}; use crate::service::{HttpRequest, HttpResponse};

View file

@ -1,9 +1,11 @@
use crate::base::action::page::{run_actions_after_prepare_body, run_actions_before_prepare_body}; use crate::base::action::page::{run_actions_after_prepare_body, run_actions_before_prepare_body};
use crate::base::component::L10n; use crate::core::component::{ArcComponent, ComponentTrait};
use crate::core::component::{ArcComponent, ComponentTrait, TypedComponent};
use crate::core::component::{Context, ContextOp}; use crate::core::component::{Context, ContextOp};
use crate::core::theme::ComponentsRegions; use crate::core::theme::ComponentsRegions;
use crate::html::{html, ClassesOp, Favicon, Markup, OptionClasses, OptionId, DOCTYPE}; use crate::html::{
html, ClassesOp, Favicon, Markup, OptionClasses, OptionId, OptionTranslate, DOCTYPE,
};
use crate::locale::L10n;
use crate::response::fatal_error::FatalError; use crate::response::fatal_error::FatalError;
use crate::{fn_builder, service}; use crate::{fn_builder, service};
@ -11,13 +13,10 @@ use unic_langid::CharacterDirection;
pub use actix_web::Result as ResultPage; pub use actix_web::Result as ResultPage;
type PageTitle = TypedComponent<L10n>;
type PageDescription = TypedComponent<L10n>;
#[rustfmt::skip] #[rustfmt::skip]
pub struct Page { pub struct Page {
title : PageTitle, title : OptionTranslate,
description : PageDescription, description : OptionTranslate,
metadata : Vec<(&'static str, &'static str)>, metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>, properties : Vec<(&'static str, &'static str)>,
favicon : Option<Favicon>, favicon : Option<Favicon>,
@ -31,8 +30,8 @@ impl Page {
#[rustfmt::skip] #[rustfmt::skip]
pub fn new(request: service::HttpRequest) -> Self { pub fn new(request: service::HttpRequest) -> Self {
Page { Page {
title : PageTitle::new(), title : OptionTranslate::new(),
description : PageDescription::new(), description : OptionTranslate::new(),
metadata : Vec::new(), metadata : Vec::new(),
properties : Vec::new(), properties : Vec::new(),
favicon : None, favicon : None,
@ -47,13 +46,13 @@ impl Page {
#[fn_builder] #[fn_builder]
pub fn alter_title(&mut self, title: L10n) -> &mut Self { pub fn alter_title(&mut self, title: L10n) -> &mut Self {
self.title.set(title); self.title.alter_value(title);
self self
} }
#[fn_builder] #[fn_builder]
pub fn alter_description(&mut self, description: L10n) -> &mut Self { pub fn alter_description(&mut self, description: L10n) -> &mut Self {
self.description.set(description); self.description.alter_value(description);
self self
} }
@ -102,11 +101,13 @@ impl Page {
// Page GETTERS. // Page GETTERS.
pub fn title(&mut self) -> String { pub fn title(&mut self) -> String {
self.title.prepare(&mut self.context).into_string() self.title.using(self.context.langid()).unwrap_or_default()
} }
pub fn description(&mut self) -> String { pub fn description(&mut self) -> String {
self.description.prepare(&mut self.context).into_string() self.description
.using(self.context.langid())
.unwrap_or_default()
} }
pub fn metadata(&self) -> &Vec<(&str, &str)> { pub fn metadata(&self) -> &Vec<(&str, &str)> {