✨ (pagetop): Mejora la elección de zona horaria

- Nuevas opciones `app.timezone_regions`, `app.timezone_order` y
  `app.timezone_per_user` para limitar y ordenar las regiones ofrecidas
  y decidir si cada usuario puede tener su propia zona horaria.
- Añade `TzRegion` y `TimezoneOrder`; `Timezone::supported_by_region()`
  devuelve ahora `TzRegion` y excluye los alias de la base IANA que
  repiten otra zona (tzdata 2025b).
- Añade `Timezone::is_supported_in()` para validar con otras regiones.
- `SelectTimezone` admite `with_regions()`, `with_order()` y
  `with_utc_offset()`, muestra nombres legibles y conserva la zona
  actual aunque ya no se ofrezca.
- `app.timezone` se resuelve sin distinguir mayúsculas.
- pagetop-user no ofrece idioma ni zona horaria si no se aplican y
  conserva lo guardado; acepta la zona actual aunque ya no se ofrezca.
This commit is contained in:
Manuel Cillero 2026-10-07 01:19:01 +02:00
parent f819181872
commit 346714ab29
19 changed files with 1257 additions and 131 deletions

View file

@ -14,7 +14,7 @@ use crate::component::admin::{
AdminPasswordForm, USER_ADMIN_FORM_ID, UserForm, UserFormMode, UserTable, status_key,
};
use crate::component::{language_name, multiline_text, theme_name};
use crate::config::SETTINGS;
use crate::config::{SETTINGS, user_language_applies, user_timezone_applies};
use crate::entity::{role, user};
use crate::error::AuthError;
use crate::handlers::admin::{back_link, frame, map_auth_error};
@ -589,17 +589,23 @@ async fn user_view_details(user: &user::Model, status: UserStatus, cx: &mut Cont
.with_cell(multiline_text(
user.about.clone().unwrap_or_else(|| "-".into()),
)),
)
.with_row(
);
// Sólo se muestran si se aplican, igual que en el formulario de edición.
if user_language_applies() {
table = table.with_row(
table::Row::new()
.with_cell(Lc::t("field-language", &LOCALES_USER))
.with_cell(language_name(user.language.as_deref())),
)
.with_row(
);
}
if user_timezone_applies() {
table = table.with_row(
table::Row::new()
.with_cell(Lc::t("field-timezone", &LOCALES_USER))
.with_cell(user.timezone.as_deref().unwrap_or("-")),
)
);
}
table = table
.with_row(
table::Row::new()
.with_cell(Lc::t("field-theme", &LOCALES_USER))