El modelo anterior (N documentos independientes por idioma) permitia que la
ESTRUCTURA divergiera: borrar un bloque en un idioma no lo borraba en los
demas. Requisito del usuario: la estructura es unica; solo el TEXTO es por
idioma. Rehecho a UN solo documento con el contenido por-idioma en el bloque.
Modelo (correcto por construccion):
- `block.i18n?: Record<LangCode, Inline[]>` guarda el contenido de los idiomas
INACTIVOS; `block.children` = el activo. Hay UN arbol → las ops estructurales
(borrar/insertar/mover/tipo/tabla) aplican a TODOS los idiomas gratis, y el
undo es automatico (el i18n vive en el doc). `doc.activeLang` registra cual
esta en `children` (normalize lo preserva como `scheme`). El `i18n` sobrevive
normalize + ops via spread (validate no rechaza props extra).
- Cambiar de idioma = swap `children <-> i18n` en el arbol (switchDocumentLanguage).
- Solo el texto INLINE es por idioma; alt/caption de imagen, code.language y
callout.title quedan COMPARTIDOS en v1.
Contrato: `value` vuelve a `PalabrasDocument` (uno solo, no un mapa). Helpers
`foldPalabrasLanguages` (construye el doc desde docs-gemelos por idioma) y
`projectPalabrasLanguage` (extrae un idioma para render/export). El switcher y
la ubicacion (chunks 2-3) intactos.
engine/i18n.ts NUEVO. Provider reworkeado (fuera langHistories/map). Tests
reescritos: incluye el test CLAVE (borrar aplica a todos los idiomas) + insertar
= vacio-a-traducir en los demas + project round-trip. 60/60 provider · 570/570
motor · 0 errores de tipo. Verificado Playwright: borrar 1 bloque en es (4->3) →
en tambien 3, contenido es<->en distinto, 0 errores de consola.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>