diff --git a/docs/04-pages-and-records.md b/docs/04-pages-and-records.md index 4137556..27c6795 100644 --- a/docs/04-pages-and-records.md +++ b/docs/04-pages-and-records.md @@ -162,9 +162,9 @@ En sitios multiidioma las traducciones NO viven en la fila del registro: se guar - Para leer un registro ya traducido, pasa `lang: ""` a `get_record` o `list_table_records`. - El campo `identificador` de `textos_generales` (los literales del filtro Twig `| translate`) se traduce por su campo `texto`. -### Regla dura: nunca traduzcas `enlace` +### El `enlace` traducido lo define el usuario -El campo `enlace` NUNCA se traduce a mano — lo mantiene el motor CocoEnlace. La action PHP rechaza cualquier intento de traducir `enlace`. No lo incluyas en `set_record_translations`. +El `enlace` traducido es editable con `set_record_translations` (formato: path absoluto con prefijo de idioma, p.ej. `/en/contact/` para la página base `/contacto/`). Solo hazlo si el usuario lo pide; ten en cuenta que al cambiar el `enlace` base, CocoEnlace regenera automáticamente las filas de enlace por idioma (formato `/`) y puede pisar la personalización. ## Patrón canónico — Detalle de registro diff --git a/docs/09-mcp-tools-reference.md b/docs/09-mcp-tools-reference.md index 2e81aa1..f8e9b0f 100644 --- a/docs/09-mcp-tools-reference.md +++ b/docs/09-mcp-tools-reference.md @@ -161,7 +161,7 @@ Las webs multiidioma guardan las traducciones en la tabla central `cms_traduccio |------|--------|-------| | `list_web_languages` | Lista los idiomas activos del sitio (`settings.dat.php [idiomas]`) | Devuelve `prefix`/`urlPrefix`/`isDefault`. `prefix="www"` = idioma base (URLs sin prefijo); otro prefix (p.ej. `en`) = idioma bajo `/en/...` | | `get_record_translations` | Lee traducciones de uno o varios registros | Por `tableName` (sin `cms_`) + `recordNums`. Opcional `fields` y `prefix`. Devuelve `{recordNum:{prefix:{fieldName:valor}}}` ya decodificado | -| `set_record_translations` | Escribe traducciones de un registro + idioma | `tableName`+`recordNum`+`prefix`+`fields`. `''` borra la traducción. **`enlace` prohibido** (lo mantiene CocoEnlace) | +| `set_record_translations` | Escribe traducciones de un registro + idioma | `tableName`+`recordNum`+`prefix`+`fields`. `''` borra la traducción. `enlace`: path absoluto con prefijo (`/en/...`); CocoEnlace lo regenera si cambia el enlace base | Además, las tools de lectura `list_table_records` y `get_record` aceptan el parámetro opcional `lang` (prefix, p.ej. `'en'`): devuelven los valores ya traducidos de los campos traducibles (el motor CocoDB aplica la traducción en lectura). diff --git a/docs/11b-rules-cheat-sheet.md b/docs/11b-rules-cheat-sheet.md index 300dba9..eb65283 100644 --- a/docs/11b-rules-cheat-sheet.md +++ b/docs/11b-rules-cheat-sheet.md @@ -92,7 +92,7 @@ Resumen ejecutable de reglas críticas, tipos de campo, filtros y formatos de da | Regla | Detalle | |-------|---------| | Prefix `www` = idioma base | URLs sin prefijo. Otro prefix (p.ej. `en`) sirve bajo `/en/...` — lista con `list_web_languages` | -| Nunca traducir `enlace` | Lo mantiene CocoEnlace; la action PHP lo rechaza | +| Traducir `enlace` con cuidado | Es editable por idioma (path absoluto, p.ej. `/en/contact/`); si cambia el enlace base, CocoEnlace lo regenera | | Valor `''` borra la traducción | `set_record_translations` con `''` elimina la fila y cae al idioma base | | Base64 transparente | El valor se guarda Base64 en `cms_traducciones`; tú siempre pasas/recibes texto plano | | `multitext` = JSON completo | Se traduce el JSON serializado entero en una sola fila, no item por item | diff --git a/mcp-server/tools/helpers/ACAI_ENDPOINTS.md b/mcp-server/tools/helpers/ACAI_ENDPOINTS.md index 8ec7360..701c688 100644 --- a/mcp-server/tools/helpers/ACAI_ENDPOINTS.md +++ b/mcp-server/tools/helpers/ACAI_ENDPOINTS.md @@ -384,7 +384,7 @@ Notas: `prefix === "www"` es el idioma base (URLs sin prefijo, `urlPrefix === "" } ``` **Respuesta**: `{ success: true, updated: number, deleted: number }` -**Errores**: `{ error: { message: string, code: string } }` — p.ej. si se intenta traducir `enlace` (prohibido: lo mantiene CocoEnlace). +**Errores**: `{ error: { message: string, code: string } }` — p.ej. campos de sistema (`num`, `builder`, `controlador`). `enlace` SÍ es traducible: debe ser un path absoluto (se normaliza la barra inicial); al cambiar el enlace base, CocoEnlace regenera las traducciones. Notas: - Solo campos traducibles: `textfield`, `textbox`, `wysiwyg`, `codigo`, `multitext` (el multitext se traduce como el JSON serializado completo en una fila). diff --git a/mcp-server/tools/languages/setRecordTranslations.js b/mcp-server/tools/languages/setRecordTranslations.js index eb4f392..94f1ec1 100644 --- a/mcp-server/tools/languages/setRecordTranslations.js +++ b/mcp-server/tools/languages/setRecordTranslations.js @@ -17,7 +17,7 @@ Four usage scenarios: Rules: - An EMPTY STRING ('') as a value DELETES that translation (falls back to base language at runtime). -- The 'enlace' field is NEVER translated by hand — the CocoEnlace engine maintains it; the PHP rejects it. +- 'enlace' IS translatable: absolute path with the language prefix (e.g. '/en/contact/'). Note: when the base 'enlace' changes, CocoEnlace regenerates per-language rows and may overwrite it. - multitext fields are translated as the full serialized JSON string in a single row (translate the whole JSON value, not individual items). - prefix is the language code from list_web_languages (e.g. 'en'); do NOT write to prefix 'www' (base language is edited via normal record fields, not translations). @@ -30,7 +30,7 @@ Params: tableName: z.string().describe("Table name without 'cms_' prefix (e.g. 'apartados', 'builder_custom', 'textos_generales')"), recordNum: z.number().describe("Record 'num' primary key to translate"), prefix: z.string().describe("Target language prefix from list_web_languages (e.g. 'en'). Never 'www' (base language)."), - fields: z.record(z.string()).describe("Map { fieldName: translatedValue }. Empty string '' deletes the translation. 'enlace' is forbidden."), + fields: z.record(z.string()).describe("Map { fieldName: translatedValue }. Empty string '' deletes the translation. 'enlace' must be an absolute path (e.g. '/en/contact/')."), }), { readOnlyHint: false, destructiveHint: false }, withAuth(async ({ tableName, recordNum, prefix, fields }, extra) => {