From caa4cf6096ceac5496d6c7729328f2438db375d6 Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Wed, 10 Dec 2025 15:18:07 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=9A=20Renombra=20`LangMatch`=20por=20`?= =?UTF-8?q?Locale`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/base/extension/welcome.rs | 6 +-- src/core/component/context.rs | 8 ++-- src/html/attr_l10n.rs | 6 +-- src/locale.rs | 72 +++++++++++++++++------------------ tests/locale.rs | 10 ++--- 5 files changed, 51 insertions(+), 51 deletions(-) diff --git a/src/base/extension/welcome.rs b/src/base/extension/welcome.rs index d4a78547..c4f8b07f 100644 --- a/src/base/extension/welcome.rs +++ b/src/base/extension/welcome.rs @@ -28,7 +28,7 @@ impl Extension for Welcome { } async fn home_page(request: HttpRequest) -> ResultPage { - let language = LangMatch::from_request(Some(&request)); + let language = Locale::from_request(Some(&request)); home(request, &language) } @@ -36,9 +36,9 @@ async fn home_lang( request: HttpRequest, path: service::web::Path, ) -> ResultPage { - let language = LangMatch::resolve(path.into_inner()); + let language = Locale::resolve(path.into_inner()); match language { - LangMatch::Found(_) => home(request, &language), + Locale::Found(_) => home(request, &language), _ => Err(ErrorPage::NotFound(request)), } } diff --git a/src/core/component/context.rs b/src/core/component/context.rs index 74290569..01b329c1 100644 --- a/src/core/component/context.rs +++ b/src/core/component/context.rs @@ -4,7 +4,7 @@ use crate::core::theme::{ChildrenInRegions, RegionRef, TemplateRef, ThemeRef}; use crate::core::TypeInfo; use crate::html::{html, Markup}; use crate::html::{Assets, Favicon, JavaScript, StyleSheet}; -use crate::locale::{LangId, LangMatch, LanguageIdentifier}; +use crate::locale::{LangId, LanguageIdentifier, Locale}; use crate::service::HttpRequest; use crate::{builder_fn, util}; @@ -65,7 +65,7 @@ pub enum ContextError { /// # use pagetop::prelude::*; /// # use pagetop_aliner::Aliner; /// fn prepare_context(cx: C) -> C { -/// cx.with_langid(&LangMatch::resolve("es-ES")) +/// cx.with_langid(&Locale::resolve("es-ES")) /// .with_theme(&Aliner) /// .with_template(&DefaultTemplate::Standard) /// .with_assets(ContextOp::SetFavicon(Some(Favicon::new().with_icon("/favicon.ico")))) @@ -169,7 +169,7 @@ pub trait Contextual: LangId { /// fn new_context(request: HttpRequest) -> Context { /// Context::new(Some(request)) /// // Establece el idioma del documento a español. -/// .with_langid(&LangMatch::resolve("es-ES")) +/// .with_langid(&Locale::resolve("es-ES")) /// // Establece el tema para renderizar. /// .with_theme(&Aliner) /// // Asigna un favicon. @@ -229,7 +229,7 @@ impl Context { /// recursos cargados. #[rustfmt::skip] pub fn new(request: Option) -> Self { - let langid = LangMatch::from_request(request.as_ref()).langid(); + let langid = Locale::from_request(request.as_ref()).langid(); Context { request, langid, diff --git a/src/html/attr_l10n.rs b/src/html/attr_l10n.rs index 6323701c..aa18f6c2 100644 --- a/src/html/attr_l10n.rs +++ b/src/html/attr_l10n.rs @@ -14,18 +14,18 @@ use crate::{builder_fn, AutoDefault}; /// /// // Español disponible. /// assert_eq!( -/// hello.lookup(&LangMatch::resolve("es-ES")), +/// hello.lookup(&Locale::resolve("es-ES")), /// Some("¡Hola mundo!".to_string()) /// ); /// /// // Japonés no disponible, traduce al idioma de respaldo (`"en-US"`). /// assert_eq!( -/// hello.lookup(&LangMatch::resolve("ja-JP")), +/// hello.lookup(&Locale::resolve("ja-JP")), /// Some("Hello world!".to_string()) /// ); /// /// // Uso típico en un atributo: -/// let title = hello.value(&LangMatch::resolve("es-ES")); +/// let title = hello.value(&Locale::resolve("es-ES")); /// // Ejemplo: html! { a title=(title) { "Link" } } /// ``` #[derive(AutoDefault, Clone, Debug)] diff --git a/src/locale.rs b/src/locale.rs index ba037491..1a644e66 100644 --- a/src/locale.rs +++ b/src/locale.rs @@ -86,8 +86,8 @@ //! include_locales!(LOCALES_SAMPLE from "ruta/a/las/traducciones"); //! ``` //! -//! Y *voilà*, sólo queda operar con los idiomas soportados por PageTop usando [`LangMatch`] y -//! traducir textos con [`L10n`]. +//! Y *voilà*, sólo queda operar con los idiomas soportados por PageTop usando [`Locale`] y traducir +//! textos con [`L10n`]. use crate::html::{Markup, PreEscaped}; use crate::service::HttpRequest; @@ -129,9 +129,9 @@ static FALLBACK_LANGID: LazyLock = LazyLock::new(|| langid!( // // Se resuelve a partir de [`global::SETTINGS.app.language`](global::SETTINGS). Si el identificador // de idioma no es válido o no está disponible, se deja sin definir (`None`) y se delega en -// [`LangMatch::default()`] o [`LangId::langid()`] la aplicación del idioma de respaldo. +// [`Locale::default()`] o [`LangId::langid()`] la aplicación del idioma de respaldo. pub(crate) static DEFAULT_LANGID: LazyLock> = LazyLock::new(|| { - LangMatch::resolve(global::SETTINGS.app.language.as_deref().unwrap_or("")).as_option() + Locale::resolve(global::SETTINGS.app.language.as_deref().unwrap_or("")).as_option() }); /// Representa la fuente de idioma (`LanguageIdentifier`) asociada a un recurso. @@ -144,7 +144,7 @@ pub trait LangId { /// Operaciones con los idiomas soportados por PageTop. /// -/// Utiliza [`LangMatch`] para transformar un identificador de idioma en un [`LanguageIdentifier`] +/// Utiliza [`Locale`] para transformar un identificador de idioma en un [`LanguageIdentifier`] /// soportado por PageTop. /// /// # Ejemplos @@ -152,20 +152,20 @@ pub trait LangId { /// ```rust /// # use pagetop::prelude::*; /// // Coincidencia exacta. -/// let lang = LangMatch::resolve("es-ES"); +/// let lang = Locale::resolve("es-ES"); /// assert_eq!(lang.langid().to_string(), "es-ES"); /// /// // Coincidencia parcial (retrocede al idioma base si no hay variante regional). -/// let lang = LangMatch::resolve("es-EC"); +/// let lang = Locale::resolve("es-EC"); /// assert_eq!(lang.langid().to_string(), "es-ES"); // Porque "es-EC" no está soportado. /// /// // Idioma no especificado. -/// let lang = LangMatch::resolve(""); -/// assert_eq!(lang, LangMatch::Unspecified); +/// let lang = Locale::resolve(""); +/// assert_eq!(lang, Locale::Unspecified); /// /// // Idioma no soportado. -/// let lang = LangMatch::resolve("ja-JP"); -/// assert_eq!(lang, LangMatch::Unsupported("ja-JP".to_string())); +/// let lang = Locale::resolve("ja-JP"); +/// assert_eq!(lang, Locale::Unsupported("ja-JP".to_string())); /// ``` /// /// Con la siguiente instrucción siempre se obtiene un [`LanguageIdentifier`] válido, ya sea porque @@ -175,11 +175,11 @@ pub trait LangId { /// ```rust /// # use pagetop::prelude::*; /// // Idioma por defecto o de respaldo si no resuelve. -/// let lang = LangMatch::resolve("it-IT"); +/// let lang = Locale::resolve("it-IT"); /// let langid = lang.langid(); /// ``` #[derive(Clone, Debug, Eq, PartialEq)] -pub enum LangMatch { +pub enum Locale { /// Cuando el identificador de idioma es una cadena vacía. Unspecified, /// Si encuentra un [`LanguageIdentifier`] en la lista de idiomas soportados por PageTop que @@ -190,15 +190,15 @@ pub enum LangMatch { Unsupported(String), } -impl Default for LangMatch { +impl Default for Locale { /// Resuelve al idioma por defecto y, si no está disponible, al idioma de respaldo (`"en-US"`). fn default() -> Self { - LangMatch::Found(DEFAULT_LANGID.unwrap_or(&FALLBACK_LANGID)) + Locale::Found(DEFAULT_LANGID.unwrap_or(&FALLBACK_LANGID)) } } -impl LangMatch { - /// Resuelve `language` y devuelve la variante [`LangMatch`] apropiada. +impl Locale { + /// Resuelve `language` y devuelve la variante [`Locale`] apropiada. pub fn resolve(language: impl AsRef) -> Self { let language = language.as_ref().trim(); @@ -224,15 +224,15 @@ impl LangMatch { Self::Unsupported(language.to_string()) } - /// Crea un [`LangMatch`] a partir de una petición HTTP. + /// Crea un [`Locale`] a partir de una petición HTTP. /// /// El orden de resolución del idioma es el siguiente: /// /// 1. Idioma por defecto de la aplicación, si se ha definido en la configuración global /// ([`global::SETTINGS.app.language`]). /// 2. Si no hay idioma por defecto válido, se intenta extraer el idioma de la cabecera HTTP - /// `Accept-Language` usando [`LangMatch::resolve`]. - /// 3. Si no hay cabecera o el valor no es legible, se devuelve [`LangMatch::Unspecified`]. + /// `Accept-Language` usando [`Locale::resolve`]. + /// 3. Si no hay cabecera o el valor no es legible, se devuelve [`Locale::Unspecified`]. /// /// Este método **no aplica** idioma de respaldo. Para obtener siempre un [`LanguageIdentifier`] /// válido (aplicando idioma por defecto y, en último término, el de respaldo), utiliza @@ -240,21 +240,21 @@ impl LangMatch { pub fn from_request(request: Option<&HttpRequest>) -> Self { // 1) Se usa `DEFAULT_LANGID` si la aplicación tiene un idioma por defecto válido. if let Some(default) = *DEFAULT_LANGID { - return LangMatch::Found(default); + return Locale::Found(default); } // 2) Sin idioma por defecto, se evalúa la cabecera `Accept-Language` de la petición HTTP. request .and_then(|req| req.headers().get("Accept-Language")) .and_then(|value| value.to_str().ok()) // Aplica `resolve()` para devolver `Found`, `Unspecified` o `Unsupported`. - .map(LangMatch::resolve) + .map(Locale::resolve) // 3) Si no hay cabecera o no puede leerse, se considera no especificado. - .unwrap_or(LangMatch::Unspecified) + .unwrap_or(Locale::Unspecified) } /// Devuelve el [`LanguageIdentifier`] si el idioma fue reconocido. /// - /// Solo retorna `Some` si la variante es [`LangMatch::Found`]. En cualquier otro caso (por + /// Solo retorna `Some` si la variante es [`Locale::Found`]. En cualquier otro caso (por /// ejemplo, si el identificador es vacío o no está soportado), devuelve `None`. /// /// Este método es útil cuando se desea acceder directamente al idioma reconocido sin aplicar el @@ -264,33 +264,33 @@ impl LangMatch { /// /// ```rust /// # use pagetop::prelude::*; - /// let lang = LangMatch::resolve("es-ES").as_option(); + /// let lang = Locale::resolve("es-ES").as_option(); /// assert_eq!(lang.unwrap().to_string(), "es-ES"); /// - /// let lang = LangMatch::resolve("ja-JP").as_option(); + /// let lang = Locale::resolve("ja-JP").as_option(); /// assert!(lang.is_none()); /// ``` #[inline] pub fn as_option(&self) -> Option<&'static LanguageIdentifier> { match self { - LangMatch::Found(l) => Some(l), + Locale::Found(l) => Some(l), _ => None, } } } -/// Permite a [`LangMatch`] actuar como proveedor de idioma. +/// Permite a [`Locale`] actuar como proveedor de idioma. /// -/// Devuelve el [`LanguageIdentifier`] si la variante es [`LangMatch::Found`]; en caso contrario, +/// Devuelve el [`LanguageIdentifier`] si la variante es [`Locale::Found`]; en caso contrario, /// devuelve el idioma por defecto de la aplicación y, si tampoco está disponible, el idioma de /// respaldo ("en-US"). /// -/// Resulta útil para usar un valor de [`LangMatch`] como fuente de traducción en [`L10n::lookup()`] +/// Resulta útil para usar un valor de [`Locale`] como fuente de traducción en [`L10n::lookup()`] /// o [`L10n::using()`]. -impl LangId for LangMatch { +impl LangId for Locale { fn langid(&self) -> &'static LanguageIdentifier { match self { - LangMatch::Found(l) => l, + Locale::Found(l) => l, _ => DEFAULT_LANGID.unwrap_or(&FALLBACK_LANGID), } } @@ -367,7 +367,7 @@ enum L10nOp { /// /// ```rust,ignore /// // Traducción con clave, conjunto de traducciones y fuente de idioma. -/// let bye = L10n::t("goodbye", &LOCALES_CUSTOM).lookup(&LangMatch::resolve("it")); +/// let bye = L10n::t("goodbye", &LOCALES_CUSTOM).lookup(&Locale::resolve("it")); /// ``` #[derive(AutoDefault, Clone)] pub struct L10n { @@ -436,7 +436,7 @@ impl L10n { /// let text = L10n::l("greeting").with_arg("name", "Manuel").get(); /// ``` pub fn get(&self) -> Option { - self.lookup(&LangMatch::default()) + self.lookup(&Locale::default()) } /// Resuelve la traducción usando la fuente de idioma proporcionada. @@ -451,7 +451,7 @@ impl L10n { /// /// impl LangId for ResourceLang { /// fn langid(&self) -> &'static LanguageIdentifier { - /// LangMatch::resolve("es-MX").langid() + /// Locale::resolve("es-MX").langid() /// } /// } /// @@ -488,7 +488,7 @@ impl L10n { /// /// ```rust /// # use pagetop::prelude::*; - /// let html = L10n::l("welcome.message").using(&LangMatch::resolve("es")); + /// let html = L10n::l("welcome.message").using(&Locale::resolve("es")); /// ``` pub fn using(&self, language: &impl LangId) -> Markup { PreEscaped(self.lookup(language).unwrap_or_default()) diff --git a/tests/locale.rs b/tests/locale.rs index 91829e62..e15d4f75 100644 --- a/tests/locale.rs +++ b/tests/locale.rs @@ -13,7 +13,7 @@ async fn translation_without_args() { let _app = service::test::init_service(Application::new().test()).await; let l10n = L10n::l("test_hello_world"); - let translation = l10n.lookup(&LangMatch::resolve("es-ES")); + let translation = l10n.lookup(&Locale::resolve("es-ES")); assert_eq!(translation, Some("¡Hola mundo!".to_string())); } @@ -22,7 +22,7 @@ async fn translation_with_args() { let _app = service::test::init_service(Application::new().test()).await; let l10n = L10n::l("test_hello_user").with_arg("userName", "Manuel"); - let translation = l10n.lookup(&LangMatch::resolve("es-ES")); + let translation = l10n.lookup(&Locale::resolve("es-ES")); assert_eq!(translation, Some("¡Hola, Manuel!".to_string())); } @@ -35,7 +35,7 @@ async fn translation_with_plural_and_select() { ("photoCount", "3"), ("userGender", "male"), ]); - let translation = l10n.lookup(&LangMatch::resolve("es-ES")).unwrap(); + let translation = l10n.lookup(&Locale::resolve("es-ES")).unwrap(); assert!(translation.contains("añadido 3 nuevas fotos de él")); } @@ -44,7 +44,7 @@ async fn check_fallback_language() { let _app = service::test::init_service(Application::new().test()).await; let l10n = L10n::l("test_hello_world"); - let translation = l10n.lookup(&LangMatch::resolve("xx-YY")); // Retrocede a "en-US". + let translation = l10n.lookup(&Locale::resolve("xx-YY")); // Retrocede a "en-US". assert_eq!(translation, Some("Hello world!".to_string())); } @@ -53,6 +53,6 @@ async fn check_unknown_key() { let _app = service::test::init_service(Application::new().test()).await; let l10n = L10n::l("non-existent-key"); - let translation = l10n.lookup(&LangMatch::resolve("en-US")); + let translation = l10n.lookup(&Locale::resolve("en-US")); assert_eq!(translation, None); }