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

137 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 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`.
```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.