♻️ (locale): Renombra L10n a Lc

Simplifica el nombre del tipo de localización. Actualiza todas las
referencias en el crate principal, extensiones, ejemplos y tests.
This commit is contained in:
Manuel Cillero 2026-08-12 22:56:09 +02:00
parent 3198b74399
commit be10dd28a1
65 changed files with 612 additions and 621 deletions

View file

@ -14,14 +14,14 @@ use crate::prelude::*;
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// let item = form::check::Item::new("apple", L10n::n("Apple")).with_checked(true);
/// let item = form::check::Item::new("apple", Lc::n("Apple")).with_checked(true);
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Item {
/// Devuelve el valor enviado al servidor cuando la casilla está marcada.
value: AttrValue,
/// Devuelve la etiqueta de la casilla.
label: L10n,
label: Lc,
/// Devuelve si la casilla debe aparecer marcada por defecto.
checked: bool,
/// Devuelve si la casilla está deshabilitada.
@ -30,7 +30,7 @@ pub struct Item {
impl Item {
/// Crea una nueva casilla con el valor y la etiqueta indicados.
pub fn new(value: impl AsRef<str>, label: L10n) -> Self {
pub fn new(value: impl AsRef<str>, label: Lc) -> Self {
Self {
value: AttrValue::new(value),
label,
@ -70,10 +70,10 @@ impl Item {
///
/// let interests = form::check::Field::new()
/// .with_name("interests")
/// .with_label(L10n::n("Areas of interest"))
/// .with_item(form::check::Item::new("art", L10n::n("Art")))
/// .with_item(form::check::Item::new("tech", L10n::n("Technology")))
/// .with_item(form::check::Item::new("science", L10n::n("Science")).with_checked(true));
/// .with_label(Lc::n("Areas of interest"))
/// .with_item(form::check::Item::new("art", Lc::n("Art")))
/// .with_item(form::check::Item::new("tech", Lc::n("Technology")))
/// .with_item(form::check::Item::new("science", Lc::n("Science")).with_checked(true));
/// ```
///
/// El navegador envía una entrada por cada casilla marcada, todas bajo la misma clave (por ejemplo,
@ -101,9 +101,9 @@ pub struct Field {
/// Devuelve el nombre compartido por todas las casillas del grupo.
name: AttrName,
/// Devuelve la etiqueta del grupo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del grupo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve las casillas del grupo.
items: Vec<Item>,
/// Devuelve si todo el grupo está deshabilitado.
@ -207,14 +207,14 @@ impl Field {
/// Establece o elimina la etiqueta visible del grupo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del grupo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}

View file

@ -16,12 +16,12 @@ use crate::prelude::*;
///
/// let accept_terms = form::Checkbox::new()
/// .with_name("terms_accepted")
/// .with_label(L10n::n("I accept the terms and conditions"))
/// .with_label(Lc::n("I accept the terms and conditions"))
/// .with_required(true);
///
/// let notifications = form::Checkbox::switch()
/// .with_name("notifications_enabled")
/// .with_label(L10n::n("Receive email notifications"))
/// .with_label(Lc::n("Receive email notifications"))
/// .with_checked(true);
/// ```
///
@ -46,7 +46,7 @@ pub struct Checkbox {
/// Devuelve el nombre del campo.
name: AttrName,
/// Devuelve la etiqueta del control.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve si el control debe estar marcado/activo por defecto.
checked: bool,
/// Devuelve si el control recibe el foco automáticamente al cargar la página.
@ -123,7 +123,7 @@ impl Component for Checkbox {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -184,7 +184,7 @@ impl Checkbox {
/// Establece o elimina la etiqueta visible del control (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}

View file

@ -24,22 +24,22 @@ use crate::base::component::form;
/// .with_child(
/// form::input::Field::email()
/// .with_name("email")
/// .with_label(L10n::n("Email"))
/// .with_label(Lc::n("Email"))
/// .with_required(true),
/// )
/// .with_child(
/// form::input::Field::password()
/// .with_name("password")
/// .with_label(L10n::n("Password"))
/// .with_label(Lc::n("Password"))
/// .with_required(true),
/// )
/// .with_child(
/// form::Checkbox::check()
/// .with_name("remember")
/// .with_label(L10n::n("Remember me")),
/// .with_label(Lc::n("Remember me")),
/// )
/// .with_child(
/// Button::submit(L10n::n("Sign in"))
/// Button::submit(Lc::n("Sign in"))
/// );
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]

View file

@ -17,19 +17,19 @@ use crate::prelude::*;
/// use pagetop::prelude::*;
///
/// let personal_data = form::Fieldset::new()
/// .with_legend(L10n::n("Personal data"))
/// .with_description(L10n::n("Enter your full name and contact email."))
/// .with_child(form::input::Field::text().with_name("name").with_label(L10n::n("Full name")))
/// .with_child(form::input::Field::email().with_name("email").with_label(L10n::n("Email")));
/// .with_legend(Lc::n("Personal data"))
/// .with_description(Lc::n("Enter your full name and contact email."))
/// .with_child(form::input::Field::text().with_name("name").with_label(Lc::n("Full name")))
/// .with_child(form::input::Field::email().with_name("email").with_label(Lc::n("Email")));
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Fieldset {
/// Devuelve identificador, clases CSS, atributos HTML y valores extra del componente.
props: Props,
/// Devuelve la leyenda del `fieldset`.
legend: Attr<L10n>,
legend: Attr<Lc>,
/// Devuelve la descripción del `fieldset`.
description: Attr<L10n>,
description: Attr<Lc>,
/// Devuelve si el `fieldset` está deshabilitado.
disabled: bool,
/// Devuelve la lista de componentes del `fieldset`.
@ -86,14 +86,14 @@ impl Fieldset {
/// Establece o elimina la leyenda del `fieldset` (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_legend(mut self, legend: impl Into<Option<L10n>>) -> Self {
pub fn with_legend(mut self, legend: impl Into<Option<Lc>>) -> Self {
self.legend.alter_opt(legend.into());
self
}
/// Establece o elimina la descripción del `fieldset` (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_description(mut self, description: impl Into<Option<L10n>>) -> Self {
pub fn with_description(mut self, description: impl Into<Option<Lc>>) -> Self {
self.description.alter_opt(description.into());
self
}

View file

@ -135,8 +135,8 @@ impl fmt::Display for Mode {
///
/// let email = form::input::Field::email()
/// .with_name("email")
/// .with_label(L10n::n("Email address"))
/// .with_placeholder(L10n::n("user@example.com"))
/// .with_label(Lc::n("Email address"))
/// .with_placeholder(Lc::n("user@example.com"))
/// .with_autocomplete(Some(form::Autocomplete::email()))
/// .with_required(true);
/// ```
@ -161,15 +161,15 @@ pub struct Field {
/// Devuelve el valor inicial del campo.
value: AttrValue,
/// Devuelve la etiqueta del campo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del campo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve la longitud mínima permitida en caracteres.
minlength: Attr<u16>,
/// Devuelve la longitud máxima permitida en caracteres.
maxlength: Attr<u16>,
/// Devuelve el texto indicativo del campo.
placeholder: Attr<L10n>,
placeholder: Attr<Lc>,
/// Devuelve la configuración de autocompletado del campo.
autocomplete: Attr<form::Autocomplete>,
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
@ -238,7 +238,7 @@ impl Component for Field {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -420,14 +420,14 @@ impl Field {
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}
@ -449,9 +449,9 @@ impl Field {
/// Establece o elimina el texto indicativo del campo (`None` para quitarlo).
///
/// Este texto aparece en el mismo campo y desaparece en cuanto el usuario empieza a escribir.
/// Al ser texto visible para el usuario se acepta [`L10n`] para poder localizarlo.
/// Al ser texto visible para el usuario se acepta [`Lc`] para poder localizarlo.
#[builder_fn]
pub fn with_placeholder(mut self, placeholder: impl Into<Option<L10n>>) -> Self {
pub fn with_placeholder(mut self, placeholder: impl Into<Option<Lc>>) -> Self {
self.placeholder.alter_opt(placeholder.into());
self
}

View file

@ -13,7 +13,7 @@ use crate::prelude::*;
///
/// let quantity = form::Number::new()
/// .with_name("quantity")
/// .with_label(L10n::n("Quantity"))
/// .with_label(Lc::n("Quantity"))
/// .with_min(Some(1))
/// .with_max(Some(100))
/// .with_value(Some(1));
@ -37,9 +37,9 @@ pub struct Number {
/// Devuelve el valor inicial del campo.
value: Attr<u64>,
/// Devuelve la etiqueta del campo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del campo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve el valor mínimo permitido.
min: Attr<u64>,
/// Devuelve el valor máximo permitido.
@ -89,7 +89,7 @@ impl Component for Number {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -153,14 +153,14 @@ impl Number {
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}

View file

@ -15,14 +15,14 @@ use crate::prelude::*;
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// let item = form::radio::Item::new("monthly", L10n::n("Monthly")).with_checked(true);
/// let item = form::radio::Item::new("monthly", Lc::n("Monthly")).with_checked(true);
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Item {
/// Devuelve el valor enviado al servidor cuando la opción está seleccionada.
value: AttrValue,
/// Devuelve la etiqueta de la opción.
label: L10n,
label: Lc,
/// Devuelve si la opción debe aparecer seleccionada por defecto.
checked: bool,
/// Devuelve si la opción está deshabilitada.
@ -31,7 +31,7 @@ pub struct Item {
impl Item {
/// Crea una nueva opción con el valor y la etiqueta indicados.
pub fn new(value: impl AsRef<str>, label: L10n) -> Self {
pub fn new(value: impl AsRef<str>, label: Lc) -> Self {
Self {
value: AttrValue::new(value),
label,
@ -77,9 +77,9 @@ impl Item {
///
/// let plan = form::radio::Field::new()
/// .with_name("plan")
/// .with_label(L10n::n("Subscription plan"))
/// .with_item(form::radio::Item::new("monthly", L10n::n("Monthly")))
/// .with_item(form::radio::Item::new("annual", L10n::n("Annual")).with_checked(true))
/// .with_label(Lc::n("Subscription plan"))
/// .with_item(form::radio::Item::new("monthly", Lc::n("Monthly")))
/// .with_item(form::radio::Item::new("annual", Lc::n("Annual")).with_checked(true))
/// .with_required(true);
/// ```
///
@ -99,9 +99,9 @@ pub struct Field {
/// Devuelve el nombre compartido por todos los botones de opción del grupo.
name: AttrName,
/// Devuelve la etiqueta del grupo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del grupo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve las opciones del grupo.
items: Vec<Item>,
/// Devuelve si la selección de alguna opción del grupo es obligatoria.
@ -150,7 +150,7 @@ impl Component for Field {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -227,14 +227,14 @@ impl Field {
/// Establece o elimina la etiqueta visible del grupo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del grupo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}

View file

@ -13,7 +13,7 @@ use crate::prelude::*;
///
/// let volume = form::Range::new()
/// .with_name("volume")
/// .with_label(L10n::n("Volume"))
/// .with_label(Lc::n("Volume"))
/// .with_min(Some(0.0))
/// .with_max(Some(100.0))
/// .with_step(Some(5.0))
@ -38,9 +38,9 @@ pub struct Range {
/// Devuelve el valor inicial del campo.
value: Attr<f64>,
/// Devuelve la etiqueta del campo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del campo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve el valor mínimo permitido.
min: Attr<f64>,
/// Devuelve el valor máximo permitido.
@ -141,14 +141,14 @@ impl Range {
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}

View file

@ -18,14 +18,14 @@ use crate::prelude::*;
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// let item = form::select::Item::new("es", L10n::n("Spanish")).with_selected(true);
/// let item = form::select::Item::new("es", Lc::n("Spanish")).with_selected(true);
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Item {
/// Devuelve el valor enviado al servidor cuando se selecciona el elemento.
value: AttrValue,
/// Devuelve la etiqueta visible del elemento.
label: L10n,
label: Lc,
/// Devuelve si el elemento debe aparecer seleccionado por defecto.
selected: bool,
/// Devuelve si el elemento está deshabilitado.
@ -34,7 +34,7 @@ pub struct Item {
impl Item {
/// Crea un nuevo elemento con el valor y la etiqueta indicados.
pub fn new(value: impl AsRef<str>, label: L10n) -> Self {
pub fn new(value: impl AsRef<str>, label: Lc) -> Self {
Self {
value: AttrValue::new(value),
label,
@ -74,14 +74,14 @@ impl Item {
/// ```rust,no_run
/// use pagetop::prelude::*;
///
/// let group = form::select::Group::new(L10n::n("Europe"))
/// .with_item(form::select::Item::new("es", L10n::n("Spanish")))
/// .with_item(form::select::Item::new("fr", L10n::n("French")));
/// let group = form::select::Group::new(Lc::n("Europe"))
/// .with_item(form::select::Item::new("es", Lc::n("Spanish")))
/// .with_item(form::select::Item::new("fr", Lc::n("French")));
/// ```
#[derive(AutoDefault, Clone, Debug, Getters)]
pub struct Group {
/// Devuelve la etiqueta visible del grupo de elementos.
label: L10n,
label: Lc,
/// Devuelve los elementos del grupo.
items: Vec<Item>,
/// Devuelve si el grupo de elementos está deshabilitado.
@ -90,7 +90,7 @@ pub struct Group {
impl Group {
/// Crea un nuevo grupo con la etiqueta indicada.
pub fn new(label: L10n) -> Self {
pub fn new(label: Lc) -> Self {
Self {
label,
..Self::default()
@ -149,17 +149,17 @@ pub enum Entry {
///
/// let idioma = form::select::Field::new()
/// .with_name("language")
/// .with_label(L10n::n("Language"))
/// .with_item(form::select::Item::new("", L10n::n("— Choose —")).with_selected(true))
/// .with_label(Lc::n("Language"))
/// .with_item(form::select::Item::new("", Lc::n("— Choose —")).with_selected(true))
/// .with_group(
/// form::select::Group::new(L10n::n("Europe"))
/// .with_item(form::select::Item::new("es", L10n::n("Spanish")))
/// .with_item(form::select::Item::new("fr", L10n::n("French"))),
/// form::select::Group::new(Lc::n("Europe"))
/// .with_item(form::select::Item::new("es", Lc::n("Spanish")))
/// .with_item(form::select::Item::new("fr", Lc::n("French"))),
/// )
/// .with_group(
/// form::select::Group::new(L10n::n("Americas"))
/// .with_item(form::select::Item::new("en", L10n::n("English")))
/// .with_item(form::select::Item::new("pt", L10n::n("Portuguese"))),
/// form::select::Group::new(Lc::n("Americas"))
/// .with_item(form::select::Item::new("en", Lc::n("English")))
/// .with_item(form::select::Item::new("pt", Lc::n("Portuguese"))),
/// )
/// .with_required(true);
/// ```
@ -193,9 +193,9 @@ pub struct Field {
/// Devuelve el nombre del campo.
name: AttrName,
/// Devuelve la etiqueta del campo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del campo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve las entradas de la lista (elementos individuales y grupos de elementos).
entries: Vec<Entry>,
/// Devuelve si la lista permite selección múltiple.
@ -246,7 +246,7 @@ impl Component for Field {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -331,14 +331,14 @@ impl Field {
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}

View file

@ -15,10 +15,10 @@ use crate::prelude::*;
///
/// let descripcion = form::Textarea::new()
/// .with_name("description")
/// .with_label(L10n::n("Description"))
/// .with_label(Lc::n("Description"))
/// .with_rows(Some(8))
/// .with_maxlength(Some(500))
/// .with_placeholder(L10n::n("Write here..."))
/// .with_placeholder(Lc::n("Write here..."))
/// .with_required(true);
/// ```
///
@ -40,9 +40,9 @@ pub struct Textarea {
/// Devuelve el valor inicial del área de texto.
value: AttrValue,
/// Devuelve la etiqueta del campo.
label: Attr<L10n>,
label: Attr<Lc>,
/// Devuelve el texto de ayuda del campo.
help_text: Attr<L10n>,
help_text: Attr<Lc>,
/// Devuelve el número de filas visibles del área de texto.
rows: Attr<u16>,
/// Devuelve la longitud mínima permitida en caracteres.
@ -50,7 +50,7 @@ pub struct Textarea {
/// Devuelve la longitud máxima permitida en caracteres.
maxlength: Attr<u16>,
/// Devuelve el texto indicativo del área de texto.
placeholder: Attr<L10n>,
placeholder: Attr<Lc>,
/// Devuelve la configuración de autocompletado del campo.
autocomplete: Attr<form::Autocomplete>,
/// Devuelve si el campo recibe el foco automáticamente al cargar la página.
@ -99,7 +99,7 @@ impl Component for Textarea {
@if *self.required() {
span
class="form-required"
title=[L10n::l("field_required").lookup(cx)]
title=[Lc::l("field_required").lookup(cx)]
{
"*"
}
@ -168,14 +168,14 @@ impl Textarea {
/// Establece o elimina la etiqueta visible del campo (basta pasar `None` para quitarla).
#[builder_fn]
pub fn with_label(mut self, label: impl Into<Option<L10n>>) -> Self {
pub fn with_label(mut self, label: impl Into<Option<Lc>>) -> Self {
self.label.alter_opt(label.into());
self
}
/// Establece o elimina el texto de ayuda del campo (basta pasar `None` para quitarlo).
#[builder_fn]
pub fn with_help_text(mut self, help_text: impl Into<Option<L10n>>) -> Self {
pub fn with_help_text(mut self, help_text: impl Into<Option<Lc>>) -> Self {
self.help_text.alter_opt(help_text.into());
self
}
@ -207,9 +207,9 @@ impl Textarea {
/// Establece o elimina el texto indicativo del área de texto (`None` para quitarlo).
///
/// Este texto aparece en el área de texto y desaparece en cuanto el usuario empieza a escribir.
/// Al ser texto visible para el usuario se acepta [`L10n`] para poder localizarlo.
/// Al ser texto visible para el usuario se acepta [`Lc`] para poder localizarlo.
#[builder_fn]
pub fn with_placeholder(mut self, placeholder: impl Into<Option<L10n>>) -> Self {
pub fn with_placeholder(mut self, placeholder: impl Into<Option<Lc>>) -> Self {
self.placeholder.alter_opt(placeholder.into());
self
}