🧑💻 Mejora y simplifica localización de módulos
This commit is contained in:
parent
d0add7c7ab
commit
520d3bb20b
21 changed files with 265 additions and 325 deletions
|
|
@ -13,12 +13,12 @@ impl ModuleTrait for Admin {
|
||||||
MODULE_ADMIN
|
MODULE_ADMIN
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
_t("module_name", Locale::From(&LOCALE_ADMIN))
|
L10n::t("module_name", &LOCALE_ADMIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
Some(_t("module_description", Locale::From(&LOCALE_ADMIN)))
|
L10n::t("module_description", &LOCALE_ADMIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
||||||
|
|
@ -5,64 +5,64 @@ use pagetop_minimal::component::*;
|
||||||
|
|
||||||
pub async fn summary(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
pub async fn summary(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
||||||
let top_menu = MegaMenu::new()
|
let top_menu = MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::t("module_name", &LOCALE_ADMIN)))
|
.with_item(MegaMenuItem::label(L10n::t("module_name", &LOCALE_ADMIN)))
|
||||||
.with_item(MegaMenuItem::link(
|
.with_item(MegaMenuItem::link(
|
||||||
Text::n("Opción 2"),
|
L10n::text("Opción 2"),
|
||||||
"https://www.google.es",
|
"https://www.google.es",
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::link_blank(
|
.with_item(MegaMenuItem::link_blank(
|
||||||
Text::n("Opción 3"),
|
L10n::text("Opción 3"),
|
||||||
"https://www.google.es",
|
"https://www.google.es",
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::submenu(
|
.with_item(MegaMenuItem::submenu(
|
||||||
Text::n("Submenú 1"),
|
L10n::text("Submenú 1"),
|
||||||
MegaMenu::new()
|
MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 1")))
|
.with_item(MegaMenuItem::label(L10n::text("Opción 1")))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 2"))),
|
.with_item(MegaMenuItem::label(L10n::text("Opción 2"))),
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::separator())
|
.with_item(MegaMenuItem::separator())
|
||||||
.with_item(MegaMenuItem::submenu(
|
.with_item(MegaMenuItem::submenu(
|
||||||
Text::n("Submenú 2"),
|
L10n::text("Submenú 2"),
|
||||||
MegaMenu::new()
|
MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 1")))
|
.with_item(MegaMenuItem::label(L10n::text("Opción 1")))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 2"))),
|
.with_item(MegaMenuItem::label(L10n::text("Opción 2"))),
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 4")));
|
.with_item(MegaMenuItem::label(L10n::text("Opción 4")));
|
||||||
|
|
||||||
let side_menu = MegaMenu::new()
|
let side_menu = MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 1")))
|
.with_item(MegaMenuItem::label(L10n::text("Opción 1")))
|
||||||
.with_item(MegaMenuItem::link(
|
.with_item(MegaMenuItem::link(
|
||||||
Text::n("Opción 2"),
|
L10n::text("Opción 2"),
|
||||||
"https://www.google.es",
|
"https://www.google.es",
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::link_blank(
|
.with_item(MegaMenuItem::link_blank(
|
||||||
Text::n("Opción 3"),
|
L10n::text("Opción 3"),
|
||||||
"https://www.google.es",
|
"https://www.google.es",
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::submenu(
|
.with_item(MegaMenuItem::submenu(
|
||||||
Text::n("Submenú 1"),
|
L10n::text("Submenú 1"),
|
||||||
MegaMenu::new()
|
MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 1")))
|
.with_item(MegaMenuItem::label(L10n::text("Opción 1")))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 2"))),
|
.with_item(MegaMenuItem::label(L10n::text("Opción 2"))),
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::separator())
|
.with_item(MegaMenuItem::separator())
|
||||||
.with_item(MegaMenuItem::submenu(
|
.with_item(MegaMenuItem::submenu(
|
||||||
Text::n("Submenú 2"),
|
L10n::text("Submenú 2"),
|
||||||
MegaMenu::new()
|
MegaMenu::new()
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 1")))
|
.with_item(MegaMenuItem::label(L10n::text("Opción 1")))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 2"))),
|
.with_item(MegaMenuItem::label(L10n::text("Opción 2"))),
|
||||||
))
|
))
|
||||||
.with_item(MegaMenuItem::label(Text::n("Opción 4")));
|
.with_item(MegaMenuItem::label(L10n::text("Opción 4")));
|
||||||
|
|
||||||
Page::new(request)
|
Page::new(request)
|
||||||
.with_context(ContextOp::Theme("Bootsier"))
|
.with_context(ContextOp::Theme("Bootsier"))
|
||||||
.with_title(Text::n("Admin"))
|
.with_title(L10n::text("Admin"))
|
||||||
.with_this_in("top-menu", top_menu)
|
.with_this_in("top-menu", top_menu)
|
||||||
.with_this_in(
|
.with_this_in(
|
||||||
"region-content",
|
"region-content",
|
||||||
grid::Row::new()
|
grid::Row::new()
|
||||||
.with_column(grid::Column::new().with_component(side_menu))
|
.with_column(grid::Column::new().with_component(side_menu))
|
||||||
.with_column(grid::Column::new().with_component(Html::n(html! {
|
.with_column(grid::Column::new().with_component(L10n::html(html! {
|
||||||
p { "Columna 2"}
|
p { "Columna 2"}
|
||||||
}))),
|
}))),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ impl ThemeTrait for Bootsier {
|
||||||
fn render_component(
|
fn render_component(
|
||||||
&self,
|
&self,
|
||||||
component: &dyn ComponentTrait,
|
component: &dyn ComponentTrait,
|
||||||
_rcx: &mut RenderContext,
|
rcx: &mut RenderContext,
|
||||||
) -> Option<Markup> {
|
) -> Option<Markup> {
|
||||||
match component.handle() {
|
match component.handle() {
|
||||||
ERROR_404 => Some(html! {
|
ERROR_404 => Some(html! {
|
||||||
|
|
@ -59,18 +59,18 @@ impl ThemeTrait for Bootsier {
|
||||||
div class="media-body" {
|
div class="media-body" {
|
||||||
h1 class="display-4" { ("RESOURCE NOT FOUND") }
|
h1 class="display-4" { ("RESOURCE NOT FOUND") }
|
||||||
p class="lead" {
|
p class="lead" {
|
||||||
(_t("e404-description", Locale::From(&LOCALE_BOOTSIER)))
|
(L10n::t("e404-description", &LOCALE_BOOTSIER).render(rcx))
|
||||||
}
|
}
|
||||||
hr class="my-4";
|
hr class="my-4";
|
||||||
p {
|
p {
|
||||||
(_t("e404-description", Locale::From(&LOCALE_BOOTSIER)))
|
(L10n::t("e404-description", &LOCALE_BOOTSIER).render(rcx))
|
||||||
}
|
}
|
||||||
a
|
a
|
||||||
class="btn btn-primary btn-lg"
|
class="btn btn-primary btn-lg"
|
||||||
href="/"
|
href="/"
|
||||||
role="button"
|
role="button"
|
||||||
{
|
{
|
||||||
(_t("back-homepage", Locale::From(&LOCALE_BOOTSIER)))
|
(L10n::t("back-homepage", &LOCALE_BOOTSIER).render(rcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ impl ModuleTrait for HomeDemo {
|
||||||
MODULE_DEMOHOME
|
MODULE_DEMOHOME
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
_t("module_name", Locale::From(&LOCALE_DEMOHOME))
|
L10n::t("module_name", &LOCALE_DEMOHOME)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
Some(_t("module_description", Locale::From(&LOCALE_DEMOHOME)))
|
L10n::t("module_description", &LOCALE_DEMOHOME)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<ModuleStaticRef> {
|
fn dependencies(&self) -> Vec<ModuleStaticRef> {
|
||||||
|
|
@ -34,7 +34,7 @@ impl ModuleTrait for HomeDemo {
|
||||||
|
|
||||||
async fn demo(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
async fn demo(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
||||||
Page::new(request)
|
Page::new(request)
|
||||||
.with_title(Text::t("page_title", &LOCALE_DEMOHOME))
|
.with_title(L10n::t("page_title", &LOCALE_DEMOHOME))
|
||||||
.with_context(ContextOp::AddStyleSheet(StyleSheet::located(
|
.with_context(ContextOp::AddStyleSheet(StyleSheet::located(
|
||||||
"/homedemo/css/styles.css",
|
"/homedemo/css/styles.css",
|
||||||
)))
|
)))
|
||||||
|
|
@ -55,11 +55,11 @@ fn hello_world() -> Container {
|
||||||
.with_classes(ClassesOp::Add, "hello-col-text")
|
.with_classes(ClassesOp::Add, "hello-col-text")
|
||||||
.with_size(grid::ColumnSize::Is5of12)
|
.with_size(grid::ColumnSize::Is5of12)
|
||||||
.with_component(
|
.with_component(
|
||||||
Heading::h1(Text::t("page_title", &LOCALE_DEMOHOME))
|
Heading::h1(L10n::t("page_title", &LOCALE_DEMOHOME))
|
||||||
.with_display(HeadingDisplay::Medium),
|
.with_display(HeadingDisplay::Medium),
|
||||||
)
|
)
|
||||||
.with_component(
|
.with_component(
|
||||||
Paragraph::with(Text::e("hello_intro", &LOCALE_DEMOHOME).with_arg(
|
Paragraph::with(L10n::e("hello_intro", &LOCALE_DEMOHOME).with_arg(
|
||||||
"app",
|
"app",
|
||||||
format!(
|
format!(
|
||||||
"<span class=\"app-name\">{}</span>",
|
"<span class=\"app-name\">{}</span>",
|
||||||
|
|
@ -69,7 +69,7 @@ fn hello_world() -> Container {
|
||||||
.with_display(ParagraphDisplay::Small),
|
.with_display(ParagraphDisplay::Small),
|
||||||
)
|
)
|
||||||
.with_component(Paragraph::with(
|
.with_component(Paragraph::with(
|
||||||
Text::e("hello_powered", &LOCALE_DEMOHOME).with_arg(
|
L10n::e("hello_powered", &LOCALE_DEMOHOME).with_arg(
|
||||||
"pagetop",
|
"pagetop",
|
||||||
format!(
|
format!(
|
||||||
"<a href=\"{}\" target=\"_blank\">{}</a>",
|
"<a href=\"{}\" target=\"_blank\">{}</a>",
|
||||||
|
|
@ -80,14 +80,14 @@ fn hello_world() -> Container {
|
||||||
.with_component(
|
.with_component(
|
||||||
Anchor::button(
|
Anchor::button(
|
||||||
"https://github.com/manuelcillero/pagetop",
|
"https://github.com/manuelcillero/pagetop",
|
||||||
Text::t("hello_code", &LOCALE_DEMOHOME),
|
L10n::t("hello_code", &LOCALE_DEMOHOME),
|
||||||
)
|
)
|
||||||
.with_target(AnchorTarget::Blank)
|
.with_target(AnchorTarget::Blank)
|
||||||
.with_left_icon(Icon::with("git"))
|
.with_left_icon(Icon::with("git"))
|
||||||
.with_classes(ClassesOp::Add, "code-link"),
|
.with_classes(ClassesOp::Add, "code-link"),
|
||||||
)
|
)
|
||||||
.with_component(
|
.with_component(
|
||||||
Anchor::link("#welcome", Text::t("hello_welcome", &LOCALE_DEMOHOME))
|
Anchor::link("#welcome", L10n::t("hello_welcome", &LOCALE_DEMOHOME))
|
||||||
.with_left_icon(Icon::with("arrow-down-circle-fill"))
|
.with_left_icon(Icon::with("arrow-down-circle-fill"))
|
||||||
.with_classes(ClassesOp::Add, "welcome-link"),
|
.with_classes(ClassesOp::Add, "welcome-link"),
|
||||||
),
|
),
|
||||||
|
|
@ -104,9 +104,9 @@ fn welcome() -> Container {
|
||||||
Container::section()
|
Container::section()
|
||||||
.with_id("welcome")
|
.with_id("welcome")
|
||||||
.with_classes(ClassesOp::Add, "welcome-col-text")
|
.with_classes(ClassesOp::Add, "welcome-col-text")
|
||||||
.with_component(Heading::h2(Text::t("welcome_page", &LOCALE_DEMOHOME)))
|
.with_component(Heading::h2(L10n::t("welcome_page", &LOCALE_DEMOHOME)))
|
||||||
.with_component(
|
.with_component(
|
||||||
Heading::h3(Text::e("welcome_subtitle", &LOCALE_DEMOHOME).with_arg(
|
Heading::h3(L10n::e("welcome_subtitle", &LOCALE_DEMOHOME).with_arg(
|
||||||
"app",
|
"app",
|
||||||
format!(
|
format!(
|
||||||
"<span class=\"app-name\">{}</span>",
|
"<span class=\"app-name\">{}</span>",
|
||||||
|
|
@ -116,10 +116,10 @@ fn welcome() -> Container {
|
||||||
.with_display(HeadingDisplay::Subtitle),
|
.with_display(HeadingDisplay::Subtitle),
|
||||||
)
|
)
|
||||||
.with_component(
|
.with_component(
|
||||||
Paragraph::with(Text::t("welcome_text1", &LOCALE_DEMOHOME))
|
Paragraph::with(L10n::t("welcome_text1", &LOCALE_DEMOHOME))
|
||||||
.with_display(ParagraphDisplay::Small),
|
.with_display(ParagraphDisplay::Small),
|
||||||
)
|
)
|
||||||
.with_component(Paragraph::with(Text::t("welcome_text2", &LOCALE_DEMOHOME)))
|
.with_component(Paragraph::with(L10n::t("welcome_text2", &LOCALE_DEMOHOME)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn about_pagetop() -> Container {
|
fn about_pagetop() -> Container {
|
||||||
|
|
@ -134,21 +134,15 @@ fn about_pagetop() -> Container {
|
||||||
.with_column(
|
.with_column(
|
||||||
grid::Column::new()
|
grid::Column::new()
|
||||||
.with_classes(ClassesOp::Add, "pagetop-col-text")
|
.with_classes(ClassesOp::Add, "pagetop-col-text")
|
||||||
.with_component(Heading::h2(Text::t("pagetop_title", &LOCALE_DEMOHOME)))
|
.with_component(Heading::h2(L10n::t("pagetop_title", &LOCALE_DEMOHOME)))
|
||||||
.with_component(
|
.with_component(
|
||||||
Paragraph::with(Text::t("pagetop_text1", &LOCALE_DEMOHOME))
|
Paragraph::with(L10n::t("pagetop_text1", &LOCALE_DEMOHOME))
|
||||||
.with_display(ParagraphDisplay::Small),
|
.with_display(ParagraphDisplay::Small),
|
||||||
)
|
)
|
||||||
.with_component(Paragraph::with(Text::t("pagetop_text2", &LOCALE_DEMOHOME)))
|
.with_component(Paragraph::with(L10n::t("pagetop_text2", &LOCALE_DEMOHOME)))
|
||||||
.with_component(Paragraph::with(
|
.with_component(Paragraph::with(
|
||||||
Text::e("pagetop_text3", &LOCALE_DEMOHOME).with_arg(
|
L10n::e("pagetop_text3", &LOCALE_DEMOHOME)
|
||||||
"pagetop_website",
|
.with_arg("href", "https://docs.rs/pagetop/latest/pagetop".to_string()),
|
||||||
format!(
|
|
||||||
"<a href=\"{}\" target=\"_blank\">{}</a>",
|
|
||||||
"https://docs.rs/pagetop/latest/pagetop",
|
|
||||||
_t("pagetop_website", Locale::From(&LOCALE_DEMOHOME)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
@ -160,12 +154,12 @@ fn promo_pagetop() -> Container {
|
||||||
.with_column(
|
.with_column(
|
||||||
grid::Column::new()
|
grid::Column::new()
|
||||||
.with_classes(ClassesOp::Add, "promo-col-text")
|
.with_classes(ClassesOp::Add, "promo-col-text")
|
||||||
.with_component(Heading::h2(Text::t(
|
.with_component(Heading::h2(L10n::t(
|
||||||
"pagetop_promo_title",
|
"pagetop_promo_title",
|
||||||
&LOCALE_DEMOHOME,
|
&LOCALE_DEMOHOME,
|
||||||
)))
|
)))
|
||||||
.with_component(
|
.with_component(
|
||||||
Paragraph::with(Text::e("pagetop_promo_text1", &LOCALE_DEMOHOME).with_arg(
|
Paragraph::with(L10n::e("pagetop_promo_text1", &LOCALE_DEMOHOME).with_arg(
|
||||||
"pagetop",
|
"pagetop",
|
||||||
format!(
|
format!(
|
||||||
"<a href=\"{}\" target=\"_blank\">{}</a>",
|
"<a href=\"{}\" target=\"_blank\">{}</a>",
|
||||||
|
|
@ -196,15 +190,15 @@ fn reporting_issues() -> Container {
|
||||||
grid::Column::new()
|
grid::Column::new()
|
||||||
.with_classes(ClassesOp::Add, "reporting-col-text")
|
.with_classes(ClassesOp::Add, "reporting-col-text")
|
||||||
.with_size(grid::ColumnSize::Is6of12)
|
.with_size(grid::ColumnSize::Is6of12)
|
||||||
.with_component(Heading::h2(Text::t(
|
.with_component(Heading::h2(L10n::t(
|
||||||
"report_problems_title",
|
"report_problems_title",
|
||||||
&LOCALE_DEMOHOME,
|
&LOCALE_DEMOHOME,
|
||||||
)))
|
)))
|
||||||
.with_component(
|
.with_component(
|
||||||
Paragraph::with(Text::t("report_problems_text1", &LOCALE_DEMOHOME))
|
Paragraph::with(L10n::t("report_problems_text1", &LOCALE_DEMOHOME))
|
||||||
.with_display(ParagraphDisplay::Small),
|
.with_display(ParagraphDisplay::Small),
|
||||||
)
|
)
|
||||||
.with_component(Paragraph::with(Text::t(
|
.with_component(Paragraph::with(L10n::t(
|
||||||
"report_problems_text2",
|
"report_problems_text2",
|
||||||
&LOCALE_DEMOHOME,
|
&LOCALE_DEMOHOME,
|
||||||
))),
|
))),
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ welcome_text2 = If the problem persists, please contact your system administrato
|
||||||
pagetop_title = About PageTop
|
pagetop_title = About PageTop
|
||||||
pagetop_text1 = If you can read this page, it means that the PageTop server is working properly, but has not yet been configured.
|
pagetop_text1 = If you can read this page, it means that the PageTop server is working properly, but has not yet been configured.
|
||||||
pagetop_text2 = PageTop defines an interface for the most stable and popular Rust packages to build modular, extensible and configurable web solutions.
|
pagetop_text2 = PageTop defines an interface for the most stable and popular Rust packages to build modular, extensible and configurable web solutions.
|
||||||
pagetop_text3 = For more information on PageTop please visit the { $pagetop_website }.
|
pagetop_text3 = For more information on PageTop please visit the <a href="{ $href }" target="_blank">technical documentation</a>.
|
||||||
pagetop_website = technical documentation
|
|
||||||
|
|
||||||
pagetop_promo_title = Promoting PageTop
|
pagetop_promo_title = Promoting PageTop
|
||||||
pagetop_promo_text1 = You are free to use the image below on applications powered by { $pagetop }. Thanks for using PageTop!
|
pagetop_promo_text1 = You are free to use the image below on applications powered by { $pagetop }. Thanks for using PageTop!
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@ welcome_text2 = Si el problema persiste, póngase en contacto con el administrad
|
||||||
pagetop_title = Sobre PageTop
|
pagetop_title = Sobre PageTop
|
||||||
pagetop_text1 = Si puedes leer esta página, significa que el servidor PageTop funciona correctamente, pero aún no se ha configurado.
|
pagetop_text1 = Si puedes leer esta página, significa que el servidor PageTop funciona correctamente, pero aún no se ha configurado.
|
||||||
pagetop_text2 = PageTop define una interfaz para los paquetes Rust más estables y populares para crear soluciones web modulares, extensibles y configurables.
|
pagetop_text2 = PageTop define una interfaz para los paquetes Rust más estables y populares para crear soluciones web modulares, extensibles y configurables.
|
||||||
pagetop_text3 = Para más información sobre PageTop, por favor visita la { $pagetop_website }.
|
pagetop_text3 = Para más información sobre PageTop, por favor visita la <a href="{ $href }" target="_blank">documentación técnica</a>.
|
||||||
pagetop_website = documentación técnica
|
|
||||||
|
|
||||||
pagetop_promo_title = Promociona PageTop
|
pagetop_promo_title = Promociona PageTop
|
||||||
pagetop_promo_text1 = Eres libre de usar la siguiente imagen en aplicaciones desarrolladas con { $pagetop }. ¡Gracias por usar PageTop!
|
pagetop_promo_text1 = Eres libre de usar la siguiente imagen en aplicaciones desarrolladas con { $pagetop }. ¡Gracias por usar PageTop!
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ use pagetop::prelude::*;
|
||||||
|
|
||||||
define_handle!(COMPONENT_MEGAMENUITEM);
|
define_handle!(COMPONENT_MEGAMENUITEM);
|
||||||
|
|
||||||
type Label = OneComponent<Text>;
|
type Label = OneComponent<L10n>;
|
||||||
type Content = OneComponent<Html>;
|
type Content = OneComponent<L10n>;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub enum MegaMenuItemType {
|
pub enum MegaMenuItemType {
|
||||||
|
|
@ -86,35 +86,35 @@ impl ComponentTrait for MegaMenuItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MegaMenuItem {
|
impl MegaMenuItem {
|
||||||
pub fn label(label: Text) -> Self {
|
pub fn label(label: L10n) -> Self {
|
||||||
MegaMenuItem {
|
MegaMenuItem {
|
||||||
item_type: MegaMenuItemType::Label(OneComponent::new_with(label)),
|
item_type: MegaMenuItemType::Label(OneComponent::new_with(label)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link(label: Text, path: &str) -> Self {
|
pub fn link(label: L10n, path: &str) -> Self {
|
||||||
MegaMenuItem {
|
MegaMenuItem {
|
||||||
item_type: MegaMenuItemType::Link(OneComponent::new_with(label), path.to_owned()),
|
item_type: MegaMenuItemType::Link(OneComponent::new_with(label), path.to_owned()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link_blank(label: Text, path: &str) -> Self {
|
pub fn link_blank(label: L10n, path: &str) -> Self {
|
||||||
MegaMenuItem {
|
MegaMenuItem {
|
||||||
item_type: MegaMenuItemType::LinkBlank(OneComponent::new_with(label), path.to_owned()),
|
item_type: MegaMenuItemType::LinkBlank(OneComponent::new_with(label), path.to_owned()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn html(content: Html) -> Self {
|
pub fn html(content: L10n) -> Self {
|
||||||
MegaMenuItem {
|
MegaMenuItem {
|
||||||
item_type: MegaMenuItemType::Html(OneComponent::new_with(content)),
|
item_type: MegaMenuItemType::Html(OneComponent::new_with(content)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submenu(label: Text, menu: MegaMenu) -> Self {
|
pub fn submenu(label: L10n, menu: MegaMenu) -> Self {
|
||||||
MegaMenuItem {
|
MegaMenuItem {
|
||||||
item_type: MegaMenuItemType::Submenu(OneComponent::new_with(label), menu),
|
item_type: MegaMenuItemType::Submenu(OneComponent::new_with(label), menu),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ pub enum AnchorTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnchorIcon = OneComponent<Icon>;
|
type AnchorIcon = OneComponent<Icon>;
|
||||||
type AnchorHtml = OneComponent<Text>;
|
type AnchorHtml = OneComponent<L10n>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -91,11 +91,11 @@ impl ComponentTrait for Anchor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Anchor {
|
impl Anchor {
|
||||||
pub fn link(href: &str, html: Text) -> Self {
|
pub fn link(href: &str, html: L10n) -> Self {
|
||||||
Anchor::new().with_href(href).with_html(html)
|
Anchor::new().with_href(href).with_html(html)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn button(href: &str, html: Text) -> Self {
|
pub fn button(href: &str, html: L10n) -> Self {
|
||||||
Anchor::new()
|
Anchor::new()
|
||||||
.with_type(AnchorType::Button)
|
.with_type(AnchorType::Button)
|
||||||
.with_href(href)
|
.with_href(href)
|
||||||
|
|
@ -152,7 +152,7 @@ impl Anchor {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_html(&mut self, html: Text) -> &mut Self {
|
pub fn alter_html(&mut self, html: L10n) -> &mut Self {
|
||||||
self.html.set(html);
|
self.html.set(html);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ pub enum ButtonType {
|
||||||
Reset,
|
Reset,
|
||||||
}
|
}
|
||||||
|
|
||||||
type ButtonValue = OneComponent<Text>;
|
type ButtonValue = OneComponent<L10n>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -77,11 +77,11 @@ impl ComponentTrait for Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Button {
|
impl Button {
|
||||||
pub fn with(value: Text) -> Self {
|
pub fn with(value: L10n) -> Self {
|
||||||
Button::new().with_value(value)
|
Button::new().with_value(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn submit(value: Text) -> Self {
|
pub fn submit(value: L10n) -> Self {
|
||||||
let mut button = Button::new()
|
let mut button = Button::new()
|
||||||
.with_classes(ClassesOp::Replace("form-button"), "form-submit")
|
.with_classes(ClassesOp::Replace("form-button"), "form-submit")
|
||||||
.with_value(value);
|
.with_value(value);
|
||||||
|
|
@ -89,7 +89,7 @@ impl Button {
|
||||||
button
|
button
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(value: Text) -> Self {
|
pub fn reset(value: L10n) -> Self {
|
||||||
let mut button = Button::new()
|
let mut button = Button::new()
|
||||||
.with_classes(ClassesOp::Replace("form-button"), "form-reset")
|
.with_classes(ClassesOp::Replace("form-button"), "form-reset")
|
||||||
.with_value(value);
|
.with_value(value);
|
||||||
|
|
@ -124,7 +124,7 @@ impl Button {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_value(&mut self, value: Text) -> &mut Self {
|
pub fn alter_value(&mut self, value: L10n) -> &mut Self {
|
||||||
self.value.set(value);
|
self.value.set(value);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ pub enum InputType {
|
||||||
Url,
|
Url,
|
||||||
}
|
}
|
||||||
|
|
||||||
type InputLabel = OneComponent<Text>;
|
type InputLabel = OneComponent<L10n>;
|
||||||
type InputHelpText = OneComponent<Text>;
|
type InputHelpText = OneComponent<L10n>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -206,7 +206,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_label(&mut self, label: Text) -> &mut Self {
|
pub fn alter_label(&mut self, label: L10n) -> &mut Self {
|
||||||
self.label.set(label);
|
self.label.set(label);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
@ -281,7 +281,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_help_text(&mut self, help_text: Text) -> &mut Self {
|
pub fn alter_help_text(&mut self, help_text: L10n) -> &mut Self {
|
||||||
self.help_text.set(help_text);
|
self.help_text.set(help_text);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ pub enum HeadingDisplay {
|
||||||
Subtitle,
|
Subtitle,
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeadingText = OneComponent<Text>;
|
type HeadingText = OneComponent<L10n>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
@ -80,37 +80,37 @@ impl ComponentTrait for Heading {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Heading {
|
impl Heading {
|
||||||
pub fn h1(text: Text) -> Self {
|
pub fn h1(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H1)
|
.with_heading_type(HeadingType::H1)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn h2(text: Text) -> Self {
|
pub fn h2(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H2)
|
.with_heading_type(HeadingType::H2)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn h3(text: Text) -> Self {
|
pub fn h3(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H3)
|
.with_heading_type(HeadingType::H3)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn h4(text: Text) -> Self {
|
pub fn h4(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H4)
|
.with_heading_type(HeadingType::H4)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn h5(text: Text) -> Self {
|
pub fn h5(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H5)
|
.with_heading_type(HeadingType::H5)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn h6(text: Text) -> Self {
|
pub fn h6(text: L10n) -> Self {
|
||||||
Heading::new()
|
Heading::new()
|
||||||
.with_heading_type(HeadingType::H6)
|
.with_heading_type(HeadingType::H6)
|
||||||
.with_text(text)
|
.with_text(text)
|
||||||
|
|
@ -149,7 +149,7 @@ impl Heading {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_text(&mut self, text: Text) -> &mut Self {
|
pub fn alter_text(&mut self, text: L10n) -> &mut Self {
|
||||||
self.text.set(text);
|
self.text.set(text);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,11 @@ impl ModuleTrait for Menu {
|
||||||
MODULE_MENU
|
MODULE_MENU
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
_t("module_name", Locale::From(&LOCALE_MENU))
|
L10n::t("module_name", &LOCALE_MENU)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
Some(_t("module_description", Locale::From(&LOCALE_MENU)))
|
L10n::t("module_description", &LOCALE_MENU)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ impl ModuleTrait for Node {
|
||||||
MODULE_NODE
|
MODULE_NODE
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
_t("module_name", Locale::From(&LOCALE_NODE))
|
L10n::t("module_name", &LOCALE_NODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
Some(_t("module_description", Locale::From(&LOCALE_NODE)))
|
L10n::t("module_description", &LOCALE_NODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
|
fn configure_service(&self, cfg: &mut server::web::ServiceConfig) {
|
||||||
|
|
@ -41,7 +41,7 @@ impl ModuleTrait for Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn node(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
async fn node(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
||||||
Page::new(request).with_title(Text::n("Nodo")).render()
|
Page::new(request).with_title(L10n::text("Nodo")).render()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn before_render_page(page: &mut Page) {
|
fn before_render_page(page: &mut Page) {
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,12 @@ impl ModuleTrait for User {
|
||||||
MODULE_USER
|
MODULE_USER
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
_t("module_name", Locale::From(&LOCALE_USER))
|
L10n::t("module_name", &LOCALE_USER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
Some(_t("module_description", Locale::From(&LOCALE_USER)))
|
L10n::t("module_description", &LOCALE_USER)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dependencies(&self) -> Vec<ModuleStaticRef> {
|
fn dependencies(&self) -> Vec<ModuleStaticRef> {
|
||||||
|
|
@ -42,7 +42,7 @@ impl ModuleTrait for User {
|
||||||
|
|
||||||
async fn login(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
async fn login(request: server::HttpRequest) -> ResultPage<Markup, FatalError> {
|
||||||
Page::new(request)
|
Page::new(request)
|
||||||
.with_title(Text::n("Identificación del usuario"))
|
.with_title(L10n::text("Identificación del usuario"))
|
||||||
.with_this_in(
|
.with_this_in(
|
||||||
"region-content",
|
"region-content",
|
||||||
Container::new()
|
Container::new()
|
||||||
|
|
@ -58,9 +58,9 @@ fn form_login() -> Form {
|
||||||
.with_element(
|
.with_element(
|
||||||
form_element::Input::textfield()
|
form_element::Input::textfield()
|
||||||
.with_name("name")
|
.with_name("name")
|
||||||
.with_label(Text::t("username", &LOCALE_USER))
|
.with_label(L10n::t("username", &LOCALE_USER))
|
||||||
.with_help_text(
|
.with_help_text(
|
||||||
Text::t("username_help", &LOCALE_USER)
|
L10n::t("username_help", &LOCALE_USER)
|
||||||
.with_arg("app", config::SETTINGS.app.name.to_owned()),
|
.with_arg("app", config::SETTINGS.app.name.to_owned()),
|
||||||
)
|
)
|
||||||
.with_autofocus(true),
|
.with_autofocus(true),
|
||||||
|
|
@ -68,8 +68,8 @@ fn form_login() -> Form {
|
||||||
.with_element(
|
.with_element(
|
||||||
form_element::Input::password()
|
form_element::Input::password()
|
||||||
.with_name("pass")
|
.with_name("pass")
|
||||||
.with_label(Text::t("password", &LOCALE_USER))
|
.with_label(L10n::t("password", &LOCALE_USER))
|
||||||
.with_help_text(Text::t("password_help", &LOCALE_USER)),
|
.with_help_text(L10n::t("password_help", &LOCALE_USER)),
|
||||||
)
|
)
|
||||||
.with_element(form_element::Button::submit(Text::t("login", &LOCALE_USER)))
|
.with_element(form_element::Button::submit(L10n::t("login", &LOCALE_USER)))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,5 @@ pub(crate) use all::common_components;
|
||||||
mod renderable;
|
mod renderable;
|
||||||
pub use renderable::{IsRenderable, Renderable};
|
pub use renderable::{IsRenderable, Renderable};
|
||||||
|
|
||||||
mod basic;
|
mod l10n;
|
||||||
pub use basic::{Html, COMPONENT_HTML};
|
pub use l10n::{L10n, COMPONENT_L10N};
|
||||||
pub use basic::{Text, COMPONENT_TEXT};
|
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
use crate::core::component::{AnyComponent, ComponentTrait, RenderContext};
|
|
||||||
use crate::html::{html, Markup, PreEscaped};
|
|
||||||
use crate::locale::{translate, Locale, Locales};
|
|
||||||
use crate::{define_handle, fn_builder, paste, Handle};
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
macro_rules! basic_components {
|
|
||||||
( $($COMPONENT_HANDLE:ident: $Component:ty => $TypeValue:ty),* ) => { $( paste! {
|
|
||||||
|
|
||||||
define_handle!($COMPONENT_HANDLE);
|
|
||||||
|
|
||||||
pub enum [< $Component Op >] {
|
|
||||||
None,
|
|
||||||
Value($TypeValue),
|
|
||||||
Translated(&'static str, &'static Locales),
|
|
||||||
Escaped(&'static str, &'static Locales),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct $Component {
|
|
||||||
op: [< $Component Op >],
|
|
||||||
args: HashMap<&'static str, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for $Component {
|
|
||||||
fn default() -> Self {
|
|
||||||
$Component {
|
|
||||||
op: [< $Component Op >]::None,
|
|
||||||
args: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ComponentTrait for $Component {
|
|
||||||
fn new() -> Self {
|
|
||||||
$Component::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle(&self) -> Handle {
|
|
||||||
$COMPONENT_HANDLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
|
|
||||||
match self.op() {
|
|
||||||
[< $Component Op >]::None => html! {},
|
|
||||||
[< $Component Op >]::Value(value) => html! { (value) },
|
|
||||||
[< $Component Op >]::Translated(key, locales) => html! {
|
|
||||||
(translate(
|
|
||||||
key,
|
|
||||||
Locale::Using(
|
|
||||||
rcx.langid(),
|
|
||||||
locales,
|
|
||||||
&self.args().iter().fold(HashMap::new(), |mut args, (key, value)| {
|
|
||||||
args.insert(key.to_string(), value.to_owned().into());
|
|
||||||
args
|
|
||||||
})
|
|
||||||
)
|
|
||||||
))
|
|
||||||
},
|
|
||||||
[< $Component Op >]::Escaped(key, locales) => html! {
|
|
||||||
(PreEscaped(translate(
|
|
||||||
key,
|
|
||||||
Locale::Using(
|
|
||||||
rcx.langid(),
|
|
||||||
locales,
|
|
||||||
&self.args().iter().fold(HashMap::new(), |mut args, (key, value)| {
|
|
||||||
args.insert(key.to_string(), value.to_owned().into());
|
|
||||||
args
|
|
||||||
})
|
|
||||||
)
|
|
||||||
)))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_ref_any(&self) -> &dyn AnyComponent {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $Component {
|
|
||||||
pub fn n(value: $TypeValue) -> Self {
|
|
||||||
$Component {
|
|
||||||
op: [< $Component Op >]::Value(value),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn t(key: &'static str, locales: &'static Locales) -> Self {
|
|
||||||
$Component {
|
|
||||||
op: [< $Component Op >]::Translated(key, locales),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn e(key: &'static str, locales: &'static Locales) -> Self {
|
|
||||||
$Component {
|
|
||||||
op: [< $Component Op >]::Escaped(key, locales),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// $Component BUILDER.
|
|
||||||
|
|
||||||
#[fn_builder]
|
|
||||||
pub fn alter_op(&mut self, op: [< $Component Op >]) -> &mut Self {
|
|
||||||
self.op = op;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
#[fn_builder]
|
|
||||||
pub fn alter_arg(&mut self, arg: &'static str, value: String) -> &mut Self {
|
|
||||||
self.args.insert(arg, value);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear_args(&mut self) -> &mut Self {
|
|
||||||
self.args.drain();
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
// $Component GETTERS.
|
|
||||||
|
|
||||||
pub fn op(&self) -> &[< $Component Op >] {
|
|
||||||
&self.op
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn args(&self) -> &HashMap<&str, String> {
|
|
||||||
&self.args
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} )* };
|
|
||||||
}
|
|
||||||
|
|
||||||
basic_components!(
|
|
||||||
COMPONENT_HTML: Html => Markup,
|
|
||||||
COMPONENT_TEXT: Text => &'static str
|
|
||||||
);
|
|
||||||
141
pagetop/src/core/component/l10n.rs
Normal file
141
pagetop/src/core/component/l10n.rs
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
use crate::core::component::{AnyComponent, ComponentTrait, RenderContext};
|
||||||
|
use crate::html::{html, Markup, PreEscaped};
|
||||||
|
use crate::locale::Locales;
|
||||||
|
use crate::{define_handle, fn_builder, Handle};
|
||||||
|
|
||||||
|
use fluent_templates::Loader;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
define_handle!(COMPONENT_L10N);
|
||||||
|
|
||||||
|
pub enum L10nOp {
|
||||||
|
None,
|
||||||
|
Value(Markup),
|
||||||
|
Translated(&'static str, &'static Locales),
|
||||||
|
Escaped(&'static str, &'static Locales),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct L10n {
|
||||||
|
op: L10nOp,
|
||||||
|
args: HashMap<&'static str, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for L10n {
|
||||||
|
fn default() -> Self {
|
||||||
|
L10n {
|
||||||
|
op: L10nOp::None,
|
||||||
|
args: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ComponentTrait for L10n {
|
||||||
|
fn new() -> Self {
|
||||||
|
L10n::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle(&self) -> Handle {
|
||||||
|
COMPONENT_L10N
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_render(&self, rcx: &mut RenderContext) -> Markup {
|
||||||
|
match self.op() {
|
||||||
|
L10nOp::None => html! {},
|
||||||
|
L10nOp::Value(value) => html! { (value) },
|
||||||
|
L10nOp::Translated(key, locales) => html! {
|
||||||
|
(locales
|
||||||
|
.lookup_with_args(
|
||||||
|
rcx.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) => html! {
|
||||||
|
(PreEscaped(locales
|
||||||
|
.lookup_with_args(
|
||||||
|
rcx.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())
|
||||||
|
))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ref_any(&self) -> &dyn AnyComponent {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_any(&mut self) -> &mut dyn AnyComponent {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl L10n {
|
||||||
|
pub fn text(text: &'static str) -> Self {
|
||||||
|
L10n {
|
||||||
|
op: L10nOp::Value(html! { (text) }),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn html(html: Markup) -> Self {
|
||||||
|
L10n {
|
||||||
|
op: L10nOp::Value(html),
|
||||||
|
..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: String) -> &mut Self {
|
||||||
|
self.args.insert(arg, value);
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use super::ThemeStaticRef;
|
use super::ThemeStaticRef;
|
||||||
|
|
||||||
|
use crate::core::component::L10n;
|
||||||
use crate::core::hook::HookAction;
|
use crate::core::hook::HookAction;
|
||||||
use crate::util::single_type_name;
|
use crate::util::single_type_name;
|
||||||
use crate::{server, Handle};
|
use crate::{server, Handle};
|
||||||
|
|
@ -17,12 +18,12 @@ pub trait BaseModule {
|
||||||
pub trait ModuleTrait: BaseModule + Send + Sync {
|
pub trait ModuleTrait: BaseModule + Send + Sync {
|
||||||
fn handle(&self) -> Handle;
|
fn handle(&self) -> Handle;
|
||||||
|
|
||||||
fn name(&self) -> String {
|
fn name(&self) -> L10n {
|
||||||
self.single_name().to_owned()
|
L10n::text(self.single_name())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn description(&self) -> Option<String> {
|
fn description(&self) -> L10n {
|
||||||
None
|
L10n::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn theme(&self) -> Option<ThemeStaticRef> {
|
fn theme(&self) -> Option<ThemeStaticRef> {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
//! Localización (L10n).
|
//! Localización (L10n).
|
||||||
//!
|
//!
|
||||||
//! Proporciona soporte a [Fluent](https://www.projectfluent.org/), un conjunto de especificaciones
|
//! PageTop usa el conjunto de especificaciones [Fluent](https://www.projectfluent.org/) para la
|
||||||
//! para la localización de aplicaciones, así como implementaciones y buenas prácticas originalmente
|
//! localización de aplicaciones.
|
||||||
//! desarrolladas por Mozilla.
|
|
||||||
//!
|
|
||||||
//!
|
//!
|
||||||
//! # Sintaxis Fluent (FTL)
|
//! # Sintaxis Fluent (FTL)
|
||||||
//!
|
//!
|
||||||
|
|
@ -72,43 +70,23 @@
|
||||||
//!
|
//!
|
||||||
//! # Cómo aplicar la localización en tu código
|
//! # Cómo aplicar la localización en tu código
|
||||||
//!
|
//!
|
||||||
//! Una vez hayas creado tu directorio de recursos FTL, sólo tienes que usar la poderosa macro
|
//! Una vez hayas creado tu directorio de recursos FTL usa la macro
|
||||||
//! [`define_locale!`](crate::define_locale) para integrarlos en tu módulo o aplicación.
|
//! [`define_locale!`](crate::define_locale) para integrarlos en tu módulo o aplicación.
|
||||||
//!
|
//!
|
||||||
//! Y podrás usar las funciones globales [`_t()`] o [`_e()`] para traducir tus textos:
|
|
||||||
//!
|
|
||||||
//! ```
|
//! ```
|
||||||
//! use pagetop::prelude::*;
|
//! use pagetop::prelude::*;
|
||||||
//!
|
//!
|
||||||
//! define_locale!(LOCALE_SAMPLE, "static/locales");
|
//! define_locale!(LOCALE_SAMPLE, "static/locales");
|
||||||
//!
|
|
||||||
//! fn demo() {
|
|
||||||
//! println!("* {}", _t("hello-world", Locale::From(&LOCALE_SAMPLE)));
|
|
||||||
//! println!("* {}", _t("hello-user", Locale::With(&LOCALE_SAMPLE, &args!["userName" => "Julia"])));
|
|
||||||
//!
|
|
||||||
//! let args = args![
|
|
||||||
//! "userName" => "Roberto",
|
|
||||||
//! "photoCount" => 3,
|
|
||||||
//! "userGender" => "male"
|
|
||||||
//! ];
|
|
||||||
//! println!("* {}\n", _t("shared-photos", Locale::With(&LOCALE_SAMPLE, &args)));
|
|
||||||
//! }
|
|
||||||
//! ```
|
//! ```
|
||||||
//! Aunque preferirás usar normalmente los componentes básicos [Text](crate::core::component::Text)
|
//! Y utiliza el componente [L10n](crate::core::component::L10n) para incluir, en respuestas a las
|
||||||
//! y [Html](crate::core::component::Html) para incluir, en respuestas a las peticiones web, textos
|
//! peticiones web, textos y contenidos opcionalmente traducibles según el contexto de renderizado.
|
||||||
//! y contenidos opcionalmente traducibles según el contexto de renderizado.
|
|
||||||
|
|
||||||
use crate::html::{Markup, PreEscaped};
|
|
||||||
use crate::{args, config, trace, LazyStatic};
|
use crate::{args, config, trace, LazyStatic};
|
||||||
|
|
||||||
pub(crate) use unic_langid::{langid, LanguageIdentifier};
|
|
||||||
|
|
||||||
pub use fluent_templates;
|
pub use fluent_templates;
|
||||||
|
|
||||||
pub(crate) use fluent_templates::StaticLoader as Locales;
|
pub(crate) use fluent_templates::StaticLoader as Locales;
|
||||||
|
pub(crate) use unic_langid::{langid, LanguageIdentifier};
|
||||||
use fluent_templates::fluent_bundle::FluentValue;
|
|
||||||
use fluent_templates::Loader;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
@ -127,7 +105,7 @@ static FALLBACK_LANGID: LazyStatic<LanguageIdentifier> = LazyStatic::new(|| lang
|
||||||
/// Almacena el Identificador de Idioma Unicode
|
/// Almacena el Identificador de Idioma Unicode
|
||||||
/// ([Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier))
|
/// ([Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier))
|
||||||
/// global para la aplicación a partir de `SETTINGS.app.language`.
|
/// global para la aplicación a partir de `SETTINGS.app.language`.
|
||||||
pub static DEFAULT_LANGID: LazyStatic<&LanguageIdentifier> =
|
pub(crate) static DEFAULT_LANGID: LazyStatic<&LanguageIdentifier> =
|
||||||
LazyStatic::new(|| langid_for(config::SETTINGS.app.language.as_str()));
|
LazyStatic::new(|| langid_for(config::SETTINGS.app.language.as_str()));
|
||||||
|
|
||||||
pub fn langid_for(language: &str) -> &LanguageIdentifier {
|
pub fn langid_for(language: &str) -> &LanguageIdentifier {
|
||||||
|
|
@ -144,31 +122,3 @@ pub fn langid_for(language: &str) -> &LanguageIdentifier {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Locale<'a> {
|
|
||||||
From(&'a Locales),
|
|
||||||
With(&'a Locales, &'a HashMap<String, FluentValue<'a>>),
|
|
||||||
Using(
|
|
||||||
&'a LanguageIdentifier,
|
|
||||||
&'a Locales,
|
|
||||||
&'a HashMap<String, FluentValue<'a>>,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _t(key: &str, locale: Locale) -> String {
|
|
||||||
translate(key, locale)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _e(key: &str, locale: Locale) -> Markup {
|
|
||||||
PreEscaped(translate(key, locale))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn translate(key: &str, locale: Locale) -> String {
|
|
||||||
match locale {
|
|
||||||
Locale::From(locales) => locales.lookup(&DEFAULT_LANGID, key),
|
|
||||||
Locale::With(locales, args) => locales.lookup_with_args(&DEFAULT_LANGID, key, args),
|
|
||||||
Locale::Using(langid, locales, args) => locales.lookup_with_args(langid, key, args),
|
|
||||||
}
|
|
||||||
.unwrap_or(key.to_string())
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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::core::component::Text;
|
use crate::core::component::L10n;
|
||||||
use crate::response::{page::Page, ResponseError};
|
use crate::response::{page::Page, ResponseError};
|
||||||
use crate::server::http::{header::ContentType, StatusCode};
|
use crate::server::http::{header::ContentType, StatusCode};
|
||||||
use crate::server::{HttpRequest, HttpResponse};
|
use crate::server::{HttpRequest, HttpResponse};
|
||||||
|
|
@ -32,7 +32,7 @@ impl fmt::Display for FatalError {
|
||||||
FatalError::AccessDenied(request) => {
|
FatalError::AccessDenied(request) => {
|
||||||
let error_page = Page::new(request.clone());
|
let error_page = Page::new(request.clone());
|
||||||
if let Ok(page) = error_page
|
if let Ok(page) = error_page
|
||||||
.with_title(Text::n("Error FORBIDDEN"))
|
.with_title(L10n::text("Error FORBIDDEN"))
|
||||||
.with_this_in("region-content", error403::Error403)
|
.with_this_in("region-content", error403::Error403)
|
||||||
.with_template("error")
|
.with_template("error")
|
||||||
.render()
|
.render()
|
||||||
|
|
@ -46,7 +46,7 @@ impl fmt::Display for FatalError {
|
||||||
FatalError::NotFound(request) => {
|
FatalError::NotFound(request) => {
|
||||||
let error_page = Page::new(request.clone());
|
let error_page = Page::new(request.clone());
|
||||||
if let Ok(page) = error_page
|
if let Ok(page) = error_page
|
||||||
.with_title(Text::n("Error RESOURCE NOT FOUND"))
|
.with_title(L10n::text("Error RESOURCE NOT FOUND"))
|
||||||
.with_this_in("region-content", error404::Error404)
|
.with_this_in("region-content", error404::Error404)
|
||||||
.with_template("error")
|
.with_template("error")
|
||||||
.render()
|
.render()
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ use unic_langid::CharacterDirection;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
type PageTitle = OneComponent<Text>;
|
type PageTitle = OneComponent<L10n>;
|
||||||
type PageDescription = OneComponent<Text>;
|
type PageDescription = OneComponent<L10n>;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub struct Page {
|
pub struct Page {
|
||||||
|
|
@ -60,13 +60,13 @@ impl Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_title(&mut self, title: Text) -> &mut Self {
|
pub fn alter_title(&mut self, title: L10n) -> &mut Self {
|
||||||
self.title.set(title);
|
self.title.set(title);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
#[fn_builder]
|
#[fn_builder]
|
||||||
pub fn alter_description(&mut self, description: Text) -> &mut Self {
|
pub fn alter_description(&mut self, description: L10n) -> &mut Self {
|
||||||
self.description.set(description);
|
self.description.set(description);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue