💬 Muestra cada idioma en su propia lengua

This commit is contained in:
Manuel Cillero 2026-10-07 01:23:55 +02:00
parent 346714ab29
commit 03473b53e1
2 changed files with 42 additions and 28 deletions

View file

@ -3,8 +3,10 @@ use crate::prelude::*;
/// Componente para **elegir un idioma** de la lista de idiomas soportados por PageTop.
///
/// Ofrece un elemento por cada idioma de [`Locale::supported_languages()`], con su identificador
/// como valor (p. ej. `"es-ES"`) y su nombre traducido como etiqueta, ordenados por ese nombre en
/// el idioma de la página. Se renderiza como cualquier [`form::select::Field`].
/// como valor (p. ej. `"es-ES"`) y su nombre escrito en ese mismo idioma como etiqueta (p. ej.
/// *"Español (España)"* o *"English (United States)"*), sea cual sea el idioma de la página; así
/// cualquiera reconoce el suyo aunque no entienda el de la página. Se ordenan por ese nombre, sin
/// distinguir mayúsculas ni acentos. Se renderiza como cualquier [`form::select::Field`].
///
/// La primera opción, con valor vacío, depende de si el campo es obligatorio:
///
@ -46,8 +48,16 @@ impl Component for SelectLanguage {
async fn prepare(&self, cx: &mut Context) -> Result<Markup, ComponentError> {
let mut field = self.field().clone();
let mut languages = Locale::supported_languages();
languages.sort_by_cached_key(|(_, name)| name.collation_key(&*cx));
let mut languages: Vec<_> = Locale::supported_languages()
.into_iter()
.map(|(langid, name)| {
let own = name
.lookup(&Locale::Resolved(langid))
.unwrap_or_else(|| langid.to_string());
(langid, own)
})
.collect();
languages.sort_by_cached_key(|(_, name)| Lc::n(name.clone()).collation_key(&*cx));
let selected = Locale::resolve(self.selected()).as_option();
let known = selected.is_some();
@ -56,8 +66,7 @@ impl Component for SelectLanguage {
let default_name = languages
.iter()
.find(|(langid, _)| *langid == default_langid)
.and_then(|(_, name)| name.lookup(cx))
.unwrap_or_else(|| default_langid.to_string());
.map_or_else(|| default_langid.to_string(), |(_, name)| name.clone());
let label = Lc::l("select_language_site_default").with_arg("language", default_name);
field.alter_item(form::select::Item::new("", label).with_selected(!known));
} else if !known {
@ -66,7 +75,7 @@ impl Component for SelectLanguage {
}
for (langid, name) in languages {
let item = form::select::Item::new(langid.to_string(), name);
let item = form::select::Item::new(langid.to_string(), Lc::n(name));
field.alter_item(item.with_selected(selected == Some(langid)));
}
Ok(field.render(cx).await)

View file

@ -75,27 +75,32 @@ async fn unknown_selected_value_falls_back_to_the_empty_option() {
assert!(html.contains(r#"<option value="" selected>Choose a language...</option>"#));
}
// Languages are sorted by their own name, so the order is the same for every page language.
#[pagetop::test]
async fn languages_are_sorted_by_their_translated_name() {
async fn languages_are_sorted_by_their_own_name() {
let mut field = form::SelectLanguage::new();
let mut cx = Context::default().with_langid(&Locale::resolve("es-ES"));
for page in ["en-US", "es-ES"] {
let mut cx = Context::default().with_langid(&Locale::resolve(page));
let html = field.render(&mut cx).await.into_string();
let spanish = html
.find(">Español (España)</option>")
.expect("Spanish name");
let english = html
.find(">Inglés (Estados Unidos)</option>")
.expect("English name");
assert!(spanish < english);
let mut cx = Context::default().with_langid(&Locale::resolve("en-US"));
let html = field.render(&mut cx).await.into_string();
let spanish = html
.find(">Spanish (Spain)</option>")
.expect("Spanish name");
let english = html
.find(">English (United States)</option>")
.expect("English name");
let spanish = html
.find(">Español (España)</option>")
.expect("Spanish name");
assert!(english < spanish);
}
}
// Each language is labelled in its own language, whatever the language of the page.
#[pagetop::test]
async fn languages_are_labelled_in_their_own_language() {
for page in ["en-US", "es-ES"] {
let mut field = form::SelectLanguage::new();
let mut cx = Context::default().with_langid(&Locale::resolve(page));
let html = field.render(&mut cx).await.into_string();
assert!(html.contains(r#"<option value="es-ES">Español (España)</option>"#));
assert!(html.contains(r#"<option value="en-US">English (United States)</option>"#));
}
}