Internacionalización (i18n)
CÉNIT soporta tres locales — español, inglés y portugués — vía
next-intl 4.9.1. El español es la fuente de verdad y está al 100%.
El inglés está completamente traducido. El portugués tiene ~471
keys con el texto idéntico al español: el archivo existe y el
locale funciona, pero un usuario lusoparlante hoy ve mayormente
castellano. Está identificado y hay tooling para resolverlo.
Cómo lo usa el staff
Sección titulada «Cómo lo usa el staff»Player surface: transparente. El jugador hereda el locale de su sesión y ve la app en su idioma sin opción explícita salvo por su perfil.
Acceso y permisos
Sección titulada «Acceso y permisos»Todos los roles ven el selector de idioma en su perfil. El locale se persiste en dos lugares:
- Cookie
locale— fuente inmediata para el render del próximo request. user_profiles.locale— fuente de verdad persistente.
Un componente LocaleSync en el layout detecta desajustes entre
cookie y DB, escribe db_locale y el middleware redirige al usuario
con la cookie corregida.
Flujo de uso
Sección titulada «Flujo de uso»- Cliente (Client Components):
useTranslations('namespace'). - Server (Server Components / Actions):
getTranslations('namespace'). - Regla absoluta: toda string visible al usuario va por
t(). No hardcodear en JSX.
Estado de cobertura por idioma
Sección titulada «Estado de cobertura por idioma»| Locale | Cobertura real |
|---|---|
es | 100% — fuente de verdad. |
en | 100% — traducido y revisado. |
pt | ~471 keys idénticas al ES. Existe el locale, falta traducir. |
20 keys están intencionalmente bilingues y no cuentan como gap
(ej: nav.brand, siglas como HMLD, ACWR).
Datos y métricas
Sección titulada «Datos y métricas»Archivos
Sección titulada «Archivos»messages/es.json— fuente de verdad.messages/en.json— traducido humano.messages/pt.json— incompleto, requiere traducción humana.
Tooling para traducción (PR #54)
Sección titulada «Tooling para traducción (PR #54)»tsx scripts/i18n-detect-untranslated.ts --out=untranslated.csv— extrae todas las keys dept.jsonque son idénticas ales.json(excluyendo la lista de bilingues intencionales).tsx scripts/i18n-merge-translations.ts <csv>— re-importa el CSV después de que un humano lo complete.
El loop esperado es: detectar → CSV a traductor → recibir CSV traducido → merge → commit.
Excepciones
Sección titulada «Excepciones»- Wellness tokenizado (
/w/[token]) — tiene strings hardcodeadas en español. Es un formulario público simple, legacy para Nacional; no pasa por next-intl. No se traducirá salvo decisión explícita. - Mensajes del staff al jugador — el texto libre del mensaje no se traduce. Lo que se traduce son las strings de la UI alrededor.
Integraciones
Sección titulada «Integraciones»- Multi-tenant — el locale es por-usuario, no por-organización. Una org con staff multilingüe funciona naturalmente.
- Middleware — el bloque “Locale sync” en
middleware.tsresuelve los desajustes cookie/DB con un redirect en GET.
Limitaciones / roadmap
Sección titulada «Limitaciones / roadmap»- pt.json traducción humana — bloqueado por contratar traductor PT-BR/PT-PT. Tooling listo.
- Decisión PT-BR vs PT-PT — pendiente. Vender a clubes brasileños o portugueses puede requerir locales separados.
- Wellness tokenizado en otros idiomas — solo si un cliente lo pide; no es prioridad.