Files
collective-lists/plan/fase-20-euskera-locale.md
Oier Bravo Urtasun 427fe33c9c docs(plan): v1.0 cycle — fases 17–20 (versioning + list flow + emojis + euskera)
Four planned-fase docs for the first tagged release.

- Fase 17 — semver git tags + CHANGELOG.md (Keep-a-Changelog, [new]/
  [fix]/[tweak] prefixes), one big v0.0.0-beta backfill block covering
  Fases 0–16, About-modal in /settings rendering bundled CHANGELOG via
  ?raw import, deploy-script tag check + tag column in .deploys.log.
- Fase 18 — shopping list flow: required title (client + DB tighten),
  per-collective per-prefix #N auto-numbering parsed from typed title,
  collectives.default_list_title, collective_list_titles catalog + admin
  RPCs, autocomplete union (catalog + last-10). Migration 027.
- Fase 19 — EMOJI_CATALOG with faces/food/animals/objects categories
  (~280 codepoints, Unicode 14 baseline for iOS<17 compat), new
  EmojiPicker.svelte replacing the 8-emoji hardcoded selector at 4
  sites. No migration.
- Fase 20 — Euskera locale: messages/eu.json via machine-translate
  seed flagged with [needs review], users.language check constraint
  extended to ('en','es','eu'), accept-language parser + selector in
  /settings. Migration 028. v1.0.0 tag lands at the end of this fase.

README + CLAUDE.md updated with the v1.0 cycle pointers.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 01:01:34 +02:00

7.4 KiB
Raw Permalink Blame History

Fase 20 — Euskera locale (eu)

v1.0 · 4/4. Última fase del ciclo v1.0. Tras cerrarla, se taggea v1.0.0.

Estado: 📋 Planificada. Añadir Euskera (Basque, ISO 639-1 eu) como tercer idioma soportado, sumándose a en y es. Tras esta fase la app está disponible para los hogares vasco-parlantes.

Estado actual (auditado 2026-05-19):

  • Paraglide en apps/web/messages/{en,es}.json. Compile-time tree-shaken por idioma.
  • Selector de idioma actual: users.language text (probablemente en | es por check constraint o convención). Auto-detect ya en Fase 10.8.
  • ~300+ keys en cada locale (estimado por el tamaño actual).

Decisiones clave:

  • Machine-translate seed + flag for review (opción B): generar messages/eu.json con traducción automática (DeepL-formatted-text o GPT-class) marcando cada valor con sufijo [needs review] para que la persona euskera-hablante pueda repasar y borrar el marcador.
  • Soporte de idiomas declarados en la lista canónica: apps/web/src/lib/i18n/supported.ts (verificar nombre exacto, puede que viva en paraglide config). Añadir 'eu'.
  • users.language accept 'eu' en el check constraint (si existe). Si no hay constraint, añadirlo ahora con 3 valores.
  • Auto-detect (Fase 10.8): reconocer eu / eu-ES / eu-FR en accept-language.
  • Selector visible: /settings ya tiene un control de idioma. Añadir opción "Euskera".

20.1 Migración: language check

Fichero: supabase/migrations/028_users_language_eu.sql.

-- Drop the existing check (if it exists; some seeds may not have it).
alter table public.users
    drop constraint if exists users_language_check;

-- Re-add with eu allowed.
alter table public.users
    add constraint users_language_check
    check (language in ('en','es','eu'));

Tareas:

  • 20.1.1 Migración 028.
  • 20.1.2 Tests pgTAP supabase/tests/020_users_language_eu.sql:
    • update a 'eu' accepted.
    • update a 'fr' rejected by check.
  • 20.1.3 just db-types.

20.2 Locale file

Fichero: nuevo apps/web/messages/eu.json.

  • 20.2.1 Pipeline de generación (manual, una vez):
    1. Tomar messages/es.json como source-of-truth (lengua romance + base traductor más fiable hacia euskera que en).
    2. Traducir cada valor con DeepL API o GPT con prompt "Translate to Euskera (Basque), keep ICU placeholders intact, preserve punctuation, formal register".
    3. Marcar cada valor traducido con sufijo [needs review] antes del cierre de la string. Excepción: las keys con placeholders ICU ({name}, {count}) llevan también el sufijo pero la review debe verificar que los placeholders no se hayan movido a posiciones gramaticalmente raras para euskera (SOV order vs SVO).
  • 20.2.2 Validar el JSON: misma key set que en.json y es.json. Script scripts/check-locales.mjs que diff las keys y falla si faltan o sobran.
  • 20.2.3 Bundle Paraglide rebuild: pnpm --filter @colectivo/web exec paraglide-compile (o cualquiera que sea el comando — verificar en package.json).

20.3 Wiring

Ficheros:

  • apps/web/src/lib/i18n/* (configuración de Paraglide — locales soportados).
  • apps/web/src/lib/utils/accept-language.ts (Fase 10.8 — añadir 'eu' al set conocido).
  • apps/web/src/routes/(app)/settings/+page.svelte (selector de idioma).

Tareas:

  • 20.3.1 Añadir 'eu' al array de idiomas en la config de Paraglide (project.inlang/settings.json u otro fichero del plugin).
  • 20.3.2 accept-language.ts parser: reconocer eu, eu-ES, eu-FR'eu'.
  • 20.3.3 Selector de idioma en /settings: nueva opción "Euskera". Label en cada idioma:
    • en: "Basque"
    • es: "Euskera"
    • eu: "Euskera"
  • 20.3.4 Cambiar idioma a eu recarga Paraglide tags sin reload de página (setLanguageTag('eu')) + escribe users.language = 'eu'.

20.4 Tests

  • 20.4.1 Vitest unit apps/web/src/lib/utils/accept-language.test.ts (extender):
    • LANG-U-EU-01 eu'eu'.
    • LANG-U-EU-02 eu-ES'eu'.
    • LANG-U-EU-03 eu-FR;q=0.5,en'eu' (preferencia primaria).
  • 20.4.2 Vitest integración language-bootstrap.test.ts (extender):
    • LANG-INT-EU-01 user setea language=eu, update OK.
    • LANG-INT-EU-02 user intenta language='fr' → check constraint violation.
  • 20.4.3 Playwright tests/e2e/euskera.test.ts:
    • EU-01 Ana cambia idioma a Euskera en /settings → strings nav cambian (Listas → "Erosketak", o lo que diga el JSON), sin reload.
    • EU-02 Eva (usuario nuevo) con header Accept-Language: eu → onboarding renderiza en Euskera.

20.5 Review checklist (post-translation)

Antes del v1.0.0 release, abrir issue/asignar tarea para alguien euskera-hablante:

  • 20.5.1 Repasar messages/eu.json, eliminar el sufijo [needs review] de cada string corregido.
  • 20.5.2 Para keys con plurales (item_count_one, item_count_other si existen), verificar que ambos son correctos (euskera no distingue como inglés/español; puede ser una sola forma).
  • 20.5.3 Términos del dominio: "colectivo", "lista", "tarea", "nota", "compra". Acordar la traducción con el cliente (no asumir que la máquina la acertó).

20.Z Verificación + cierre

  • 20.Z.1 just test-all verde. Suma esperada: +2 pgTAP + 3 unit + 2 integración + 2 e2e = +9.
  • 20.Z.2 Smoke manual: rotar las 3 pantallas top-level (/lists, /tasks, /notes) en cada idioma. Ninguna debe mostrar la key cruda (__SKIPPED__ o el id).
  • 20.Z.3 Bundle-size check: el chunk de eu es lazy-loaded por Paraglide; verificar que solo se carga cuando el user lo elige. No debe pesar más que es.json.
  • 20.Z.4 Entrada en CHANGELOG: [new] Euskera (Basque) locale (Fase 20). Machine-translated seed pending native review.
  • 20.Z.5 Documentar en docs/history/fase-20-euskera-locale.md.

20.ZZ v1.0.0 release

  • 20.ZZ.1 Bump package.json version → 1.0.0.
  • 20.ZZ.2 Editar CHANGELOG.md: mover entradas de [Unreleased] a ## [v1.0.0] — YYYY-MM-DD. Incluir resumen de las 4 fases del ciclo (1720).
  • 20.ZZ.3 git tag -a v1.0.0 -m "v1.0.0 — versioning + shopping list flow + emoji avatars + euskera".
  • 20.ZZ.4 Deploy desde el tag. Smoke en prod.
  • 20.ZZ.5 Anuncio interno + nota sobre euskera review.

Riesgos / notas

  • Calidad de la traducción automática: euskera no es un idioma soportado de primera por DeepL (verificar fecha actual). GPT-4 class lo hace pero con errores. El sufijo [needs review] es explícito para no shipear texto incorrecto sin marcar.
  • ICU placeholders en euskera: el orden de palabras (SOV) puede empujar {name} a posiciones no naturales en inglés/español. Revisar.
  • Selector ya soporta system (auto-detect): por la Fase 10.8 ya hay lógica de fallback. Asegurar que eu propaga por todo el árbol.
  • Test fixture users: si los seeds (Ana, Borja, …) tienen language='es' hardcoded, ningún test rompe — solo los nuevos.

Scope explícito fuera

  • Galego, Català, Português, Francés. Solo Euskera en este release.
  • Pluralización ICU avanzada (one/two/few/many/other) — euskera usa pluralización simple.
  • Traducción de los strings de Keycloak (login screen). Ese es el operador del Keycloak externo.
  • Localización del CHANGELOG. Solo en inglés.
  • Localización de los nombres de los emojis (Fase 19). Aria-label sigue siendo el codepoint name CLDR en inglés.