♻️ 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;
pub use html::{Html, COMPONENT_BASE_HTML};
mod l10n;
pub use l10n::{L10n, COMPONENT_BASE_L10N};
mod translate;
pub use translate::{Translate, COMPONENT_BASE_TRANSLATE};
mod wrapper;
pub use wrapper::{Wrapper, WrapperType, COMPONENT_BASE_WRAPPER};

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,8 +25,6 @@ pub enum HeadingDisplay {
Subtitle,
}
type HeadingText = TypedComponent<L10n>;
#[rustfmt::skip]
#[derive(Default)]
pub struct Heading {
@ -35,7 +33,7 @@ pub struct Heading {
id : OptionId,
classes : OptionClasses,
heading_type: HeadingType,
text : HeadingText,
text : OptionTranslate,
display : HeadingDisplay,
template : String,
}
@ -65,12 +63,12 @@ impl ComponentTrait for Heading {
let id = self.id();
let classes = self.classes().get();
PrepareMarkup::With(html! { @match &self.heading_type() {
HeadingType::H1 => h1 id=[id] class=[classes] { (self.text().prepare(cx)) },
HeadingType::H2 => h2 id=[id] class=[classes] { (self.text().prepare(cx)) },
HeadingType::H3 => h3 id=[id] class=[classes] { (self.text().prepare(cx)) },
HeadingType::H4 => h4 id=[id] class=[classes] { (self.text().prepare(cx)) },
HeadingType::H5 => h5 id=[id] class=[classes] { (self.text().prepare(cx)) },
HeadingType::H6 => h6 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().escaped(cx.langid())) },
HeadingType::H3 => h3 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H4 => h4 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H5 => h5 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
HeadingType::H6 => h6 id=[id] class=[classes] { (self.text().escaped(cx.langid())) },
}})
}
}
@ -146,7 +144,7 @@ impl Heading {
#[fn_builder]
pub fn alter_text(&mut self, text: L10n) -> &mut Self {
self.text.set(text);
self.text.alter_value(text);
self
}
@ -185,7 +183,7 @@ impl Heading {
&self.heading_type
}
pub fn text(&self) -> &HeadingText {
pub fn text(&self) -> &OptionTranslate {
&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);
type Label = TypedComponent<L10n>;
type Label = L10n;
type Content = TypedComponent<Html>;
type SubmenuItems = TypedComponent<Submenu>;
type MegamenuGroups = TypedComponent<Megamenu>;
type Description = TypedComponent<L10n>;
#[derive(Default)]
pub enum ItemType {
@ -30,7 +29,7 @@ pub struct Item {
weight : Weight,
renderable : Renderable,
item_type : ItemType,
description: Description,
description: OptionTranslate,
}
impl ComponentTrait for Item {
@ -51,27 +50,27 @@ impl ComponentTrait for Item {
}
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() {
ItemType::Void => PrepareMarkup::None,
ItemType::Label(label) => PrepareMarkup::With(html! {
li class="pt-menu__label" {
span title=[description] {
(label.prepare(cx))
(label.escaped(cx.langid()))
}
}
}),
ItemType::Link(label, path) => PrepareMarkup::With(html! {
li class="pt-menu__link" {
a href=(path(cx)) title=[description] {
(label.prepare(cx))
(label.escaped(cx.langid()))
}
}
}),
ItemType::LinkBlank(label, path) => PrepareMarkup::With(html! {
li class="pt-menu__link" {
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! {
li class="pt-menu__children" {
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" {
(submenu.prepare(cx))
@ -93,7 +92,7 @@ impl ComponentTrait for Item {
ItemType::Megamenu(label, megamenu) => PrepareMarkup::With(html! {
li class="pt-menu__children" {
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" {
(megamenu.prepare(cx))
@ -107,21 +106,21 @@ impl ComponentTrait for Item {
impl Item {
pub fn label(label: L10n) -> Self {
Item {
item_type: ItemType::Label(Label::with(label)),
item_type: ItemType::Label(label),
..Default::default()
}
}
pub fn link(label: L10n, path: FnContextualPath) -> Self {
Item {
item_type: ItemType::Link(Label::with(label), path),
item_type: ItemType::Link(label, path),
..Default::default()
}
}
pub fn link_blank(label: L10n, path: FnContextualPath) -> Self {
Item {
item_type: ItemType::LinkBlank(Label::with(label), path),
item_type: ItemType::LinkBlank(label, path),
..Default::default()
}
}
@ -135,14 +134,14 @@ impl Item {
pub fn submenu(label: L10n, submenu: Submenu) -> Self {
Item {
item_type: ItemType::Submenu(Label::with(label), SubmenuItems::with(submenu)),
item_type: ItemType::Submenu(label, SubmenuItems::with(submenu)),
..Default::default()
}
}
pub fn megamenu(label: L10n, megamenu: Megamenu) -> Self {
Item {
item_type: ItemType::Megamenu(Label::with(label), MegamenuGroups::with(megamenu)),
item_type: ItemType::Megamenu(label, MegamenuGroups::with(megamenu)),
..Default::default()
}
}
@ -163,7 +162,7 @@ impl Item {
#[fn_builder]
pub fn alter_description(&mut self, text: L10n) -> &mut Self {
self.description.set(text);
self.description.alter_value(text);
self
}
@ -173,7 +172,7 @@ impl Item {
&self.item_type
}
pub fn description(&self) -> &Description {
pub fn description(&self) -> &OptionTranslate {
&self.description
}
}

View file

@ -1,5 +1,4 @@
use crate::prelude::*;
use crate::LOCALES_PAGETOP;
use super::Item;
@ -68,7 +67,7 @@ impl ComponentTrait for Menu {
button
type="button"
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 {}
}

View file

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

View file

@ -60,7 +60,11 @@ impl ComponentTrait for Paragraph {
impl Paragraph {
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.
@ -89,11 +93,17 @@ impl Paragraph {
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
}
pub fn add_translated(mut self, l10n: L10n) -> Self {
self.stuff
.alter(ArcOp::Add(ArcComponent::with(Translate::with(l10n))));
self
}
#[fn_builder]
pub fn alter_components(&mut self, op: ArcOp) -> &mut Self {
self.stuff.alter(op);

View file

@ -1,5 +1,4 @@
use crate::prelude::*;
use crate::LOCALES_PAGETOP;
new_handle!(COMPONENT_BASE_POWEREDBY);
@ -51,10 +50,10 @@ impl ComponentTrait for PoweredBy {
fn prepare_component(&self, cx: &mut Context) -> PrepareMarkup {
let logo = match self.logo() {
PoweredByLogo::Color => {
let logo_txt = L10n::t("pagetop_logo", &LOCALES_PAGETOP);
let logo_txt = &L10n::l("pagetop_logo").using(cx.langid());
html! {
span class="pt-pagetop__logo" aria-label=[logo_txt.into_string(cx)] {
img src="/base/pagetop-logo.svg" alt=[logo_txt.into_string(cx)] {}
span class="pt-pagetop__logo" aria-label=[logo_txt] {
img src="/base/pagetop-logo.svg" alt=[logo_txt] {}
}
}
}
@ -64,17 +63,19 @@ impl ComponentTrait for PoweredBy {
_ => html! {},
};
let mut credits = L10n::e("poweredby_pagetop", &LOCALES_PAGETOP).with_arg(
"pagetop_link",
"<a href=\"https://crates.io/crates/pagetop\">PageTop</a>",
);
let credits = L10n::l("poweredby_pagetop")
.with_arg(
"pagetop_link",
"<a href=\"https://crates.io/crates/pagetop\">PageTop</a>",
)
.escaped(cx.langid());
PrepareMarkup::With(html! {
div id=[self.id()] {
@if let Some(c) = self.copyright() {
span class="copyright" { (c) "." } " "
}
span class="powered" { (credits.prepare(cx)) " " (logo) }
span class="powered" { (credits) " " (logo) }
}
})
}
@ -120,10 +121,10 @@ impl PoweredBy {
// PoweredBy PRIVATE.
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);
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" {
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" {}

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::theme::ThemeRef;
use crate::locale::L10n;
use crate::{actions, service, util, Handle};
#[cfg(feature = "database")]

View file

@ -3,7 +3,7 @@ pub use error403::ERROR_403;
mod error404;
pub use error404::ERROR_404;
use crate::base::component::L10n;
use crate::locale::L10n;
use crate::response::{page::Page, ResponseError};
use crate::service::http::{header::ContentType, StatusCode};
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::component::L10n;
use crate::core::component::{ArcComponent, ComponentTrait, TypedComponent};
use crate::core::component::{ArcComponent, ComponentTrait};
use crate::core::component::{Context, ContextOp};
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::{fn_builder, service};
@ -11,13 +13,10 @@ use unic_langid::CharacterDirection;
pub use actix_web::Result as ResultPage;
type PageTitle = TypedComponent<L10n>;
type PageDescription = TypedComponent<L10n>;
#[rustfmt::skip]
pub struct Page {
title : PageTitle,
description : PageDescription,
title : OptionTranslate,
description : OptionTranslate,
metadata : Vec<(&'static str, &'static str)>,
properties : Vec<(&'static str, &'static str)>,
favicon : Option<Favicon>,
@ -31,8 +30,8 @@ impl Page {
#[rustfmt::skip]
pub fn new(request: service::HttpRequest) -> Self {
Page {
title : PageTitle::new(),
description : PageDescription::new(),
title : OptionTranslate::new(),
description : OptionTranslate::new(),
metadata : Vec::new(),
properties : Vec::new(),
favicon : None,
@ -47,13 +46,13 @@ impl Page {
#[fn_builder]
pub fn alter_title(&mut self, title: L10n) -> &mut Self {
self.title.set(title);
self.title.alter_value(title);
self
}
#[fn_builder]
pub fn alter_description(&mut self, description: L10n) -> &mut Self {
self.description.set(description);
self.description.alter_value(description);
self
}
@ -102,11 +101,13 @@ impl Page {
// Page GETTERS.
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 {
self.description.prepare(&mut self.context).into_string()
self.description
.using(self.context.langid())
.unwrap_or_default()
}
pub fn metadata(&self) -> &Vec<(&str, &str)> {