Skip to content

feat: interfaz bilingüe ES/EN con español por defecto #66

Open

Description

@egdev6

Objetivo y motivo

Mostrar la interfaz de Quorb en español o inglés, con español por defecto y
selección persistente en la ventana Ajustes existente.

Alcance

Incluye UI React, bandeja/notificaciones Rust, accesibilidad, formatos y errores
propios. Sin roles/panel nuevo, autodetección del SO, idiomas adicionales ni
traducción de contenido del usuario, nombres de modelos o errores externos crudos.

Dependencias y decisiones

Sin dependencia del port macOS. Elegir diccionarios tipados frente a librería y
política de fallback durante L0; ambas decisiones pendientes, no bloquear Windows
por validación Mac. Valores de locale ausentes/no soportados saneados a es.

Criterios de aceptación

  • Inventario completo de textos React/Rust y decisión de traducción/fallback.
  • Locale es|en persistido; arranque limpio y configuración antigua usan es.
  • Selector en Ajustes actualiza todas las ventanas y textos nativos.
  • Formatos coherentes por locale sin cambiar cantidades ni contenido externo.
  • No pérdida de configuración, historial, credenciales ni sesión al cambiar.
  • Tests deterministas y auditoría funcional Windows con evidencia; Mac
    coordinado cuando el port esté disponible, sin bloquear Windows.

Orientación y comprobaciones

Entradas: src/Settings.tsx, src/lib/format.ts, src-tauri/src/config.rs y
src-tauri/src/lib.rs (config-changed). Validar npm test,
npm run typecheck, npm run build, cargo test en src-tauri y prueba manual
Windows. Son comprobaciones planificadas, no ejecutadas.

Plan ODD cercano

Fase Resultado Dependencia Validación y salida
Observar/decidir L0 Inventario trazable y decisión catálogos/librería/fallback Ninguna Contraste path:line; decisiones registradas y aceptadas
Desarrollar L1 Locale persistido L0 Tests primero: es/en/ausente/inválido/recarga preservando datos
Desarrollar L2/L3 Catálogos y selector global L1 Tests de claves/fallback/sincronización y selección persistente
Desarrollar L4 Formatos y errores propios L2 Casos por locale, sin alterar valores ni errores externos
Verificar L5 Auditoría completa L3/L4 Suite y prueba Windows reales; pendientes Mac explícitos

Coordinación y entrega

Primer objetivo nuevo recomendado; planificada, no lista hasta cerrar L0.
Sin assignee inicial. Antes de empezar, revisar dependencias, comentarios,
assignees y PR; asignar solo ante inicio explícito. Tests y docs con su unidad;
seguir CONTRIBUTING, pedir autorización antes de diffs sobredimensionados.
Crear issue no autoriza implementar, abrir PR ni fusionar.

Activity

  1. added
    oddTrabajo coordinado mediante planificación ODD aprobada
    on Oct 11, 2026
  2. danielgap commented on Oct 19, 2026

    @danielgap
    Contributor

    @egdev6 ¿podemos arrancar con #66? Soy danielgap (cuenta autenticada con la que trabajaría; contribuyo asistido por agente con la skill ODD del repo).

    Revalidé antes de pedir la toma: issue sin assignees, sin comentarios de toma y sin PRs abiertas que la solapen. Sin dependencia del port macOS según el ODD vigente.

    Petición: no tengo permisos para autoasignarme. ¿Me asignás, o preferís acordar explícitamente la coordinación? No la considero tomada hasta tu confirmación.

    Entrada L0 que propongo ejecutar (según el ODD del issue):

    1. Inventario trazable de textos React/Rust con contraste path:line (src/Settings.tsx, src/lib/format.ts, src-tauri/src/config.rs, src-tauri/src/lib.rs como entradas).
    2. Propuesta de decisión: diccionarios tipados vs librería, y política de fallback con saneo a es de locales ausentes/inválidos.

    Sin implementación hasta que ambas decisiones estén registradas y aceptadas. Si ves solapamiento o preferís otro orden, lo coordino contigo.

  3. egdev6 commented on Oct 19, 2026

    @egdev6
    OwnerAuthor

    Adelante! toda tuya! si la tarea no está asignada a nadie está libre para su toma...dale candela @danielgap !!

  4. danielgap commented on Oct 19, 2026

    @danielgap
    Contributor

    L0 — Inventario y decisiones (propuesta) · @egdev6

    Cerré la entrada L0 del ODD, sin implementación aún. Inventario sobre main @ 3864613: ~700 literales en ~850 sitios con contraste path:line (React ~494 · Rust ~206: bandeja, diálogos nativos, errores de proveedores y labels de meters). El detalle acompaña al PR de L1 como documento.

    A · Catálogos tipados, sin librería i18n — es.ts/en.ts con contrato de tipos (clave faltante = error de compilación), enum de claves + match exhaustivo en Rust, e ids estables cruzando la frontera Rust→JS (hoy Meter.label se empareja por literal en shortLabel; con dos idiomas eso se rompe). Test de paridad de placeholders en vitest; Intl con mapa cerrado es→es-ES/en→en-US; plurales (2 casos) por ramificación. Evalué las alternativas vivas hoy (i18next 26, Lingui 6, Paraglide 2, Fluent, react-intl, rust-i18n): ninguna cubre la mitad Rust ni los textos que viajan como datos, y fluent-react lleva congelado desde 2022.

    B · Fallback saneando a es — locale: "es"|"en" en AppConfig: clave ausente o arranque limpio → es; valor no soportado → es tras normalizar; error de parseo → default existente; render e Intl nunca fallan abiertos. Sin migración: las configs actuales cargan igual. Bandeja y títulos se reconstruyen en runtime al cambiar idioma (verificado contra tauri 2.12).

    ¿Apruebas A y B para arrancar L1 (locale persistido)?

  5. egdev6 commented on Oct 20, 2026

    @egdev6
    OwnerAuthor

    @egdev6 @danielgap — revisé la propuesta L0 contra main @ 3864613. Veredicto: aprobados A y B para arrancar L1, con el documento de inventario como condición de revisión del PR.

    Claims verificados en código ✅

    El hallazgo del emparejamiento por literal es real y crítico — es el punto que justifica los ids estables:

    • src/lib/format.ts:42 — shortLabel() con mapa literal ('Semana · todos': 'Semana', …); con textos traducidos se cae silenciosamente al fallback ?? label.replace(...).
    • src/lib/alerts.ts:68 — el diff de alertas compara x.label === m.label entre reportes previos y nuevos: cambiar el idioma rompe la comparación (alertas fantasma o perdidas).
    • src/lib/meter-colors.ts:15-16 — regex sobre literales españoles (^semana\b, ^sesión\b) para elegir el color del anillo.
    • src-tauri/src/providers/codex.rs:147 — Rust emite "Semana" como dato, confirmando que textos Rust viajan como datos a JS.

    Los ids estables Rust→JS son, por tanto, prerrequisito de L1/L2 y no un refinamiento posterior. También verificable: fluent-react sigue congelado desde 2022, y ninguna librería viva cubre la mitad Rust ni los textos que viajan como datos — la decisión A (catálogos tipados + match exhaustivo + test de paridad de placeholders) me parece la correcta.

    B está alineada con la issue: locale: "es"|"en" en AppConfig con saneo a es es exactamente lo planificado, sin migración de configs existentes.

    Matices para el PR de L1 ⚠️

    1. El inventario (~700 literales / ~850 sitios) es inverificable hasta que llegue el PR — incluir el contraste path:line prometido como documento adjunto.
    2. Especificar el fallback para locale parseado pero null/vacío, no solo "clave ausente".
    3. Detallar los 2 casos de plurales que menciona.
    4. Asegurar que la migración no duplique textos: la UI actual ya está en español; es.ts debe nacer de los literales existentes, no de una retraducción.

    Con eso, adelante con L1 (locale persistido) con tests primero es/en/ausente/inválido/recarga preservando datos, según el plan ODD de la issue.

  6. egdev6 commented on Oct 21, 2026

    @egdev6
    OwnerAuthor

    Registro de avance del gate de L2 (fase ids estables Rust→JS) — cubierta y fusionada:

    Siguiente paso de L2/L3 (según lo anunciado en #159): catálogos y selector de medidores — el id estable ya está como base. Dos seguimientos heredados quedaron en #160 (test de contrato del inventario, ruido de diffs) y las coberturas de id sin test dedicado en providers async (anthropic_api, openai_api, copilot) pueden integrarse en ese mismo PR.

  7. 2 remaining items

  8. danielgap commented on Oct 29, 2026

    @danielgap
    Contributor

    @egdev6 sigo con C1 (paneles de suscripciones y editores de cuentas) sobre main 4f5fb48. Mide unos 190 textos, así que lo parto en dos PRs para que cada una se pueda revisar:

    Va primero C1a porque C1b usa CliConnect. Mismas reglas que en #199/#204: con es todo se ve igual, y marcas, rutas y comandos quedan literales. C2 (OpenRouter, NaN, 9Router y APIs) queda para después.

  9. egdev6 commented on Oct 29, 2026

    @egdev6
    OwnerAuthor

    @danielgap adelante con C1 tal como lo planteas: primero C1a y luego C1b. El orden encaja, porque C1b usa CliConnect, y partirlo en dos deja cada PR en un tamaño revisable. También recoge las notas 1, 3 y 4 de #204. La nota 2 (placeholders de SecretInput en inglés dentro de paneles en español) se resuelve sola al completar C1b y C2.

    Coordinación con Antigravity (#207)

    @eichhorn-micaela, para que lo tengas en cuenta: #207 añade un panel de suscripción nuevo (Antigravity) con sus textos en español literal: kicker, nota y pasos. Es el mismo caso que OpenCode Go en #201, así que aplicamos la misma regla:

    Mientras tanto, la revisión de C1a sigue su curso en #216.

  10. danielgap commented on Nov 7, 2026

    @danielgap
    Contributor

    @egdev6 retomo #66 con C2, último tramo del slice 2: paneles de APIs (OpenRouter, NaN Builders, 9Router, Anthropic API, OpenAI API) y las conexiones NanConnect/NanProbe/NineRouterConnect, sobre main 79ee3cd. Mide ~110 literales; mismo formato que C1a/C1b (catálogos ES/EN con es verbatim, tests SSR es/en, inventario regenerado).

    Notas:

    Con C2 cierra el slice 2; después queda el slice 3 (textos de Rust que llegan a la UI). Arranco C2 en local.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

oddTrabajo coordinado mediante planificación ODD aprobadatype:featureNew functionality

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions