Saltar a contenido

09 · i18n y locales

Estado del documento

Versión: 1.0 · 17-may-2026 Estado: ✅ completo Audiencia: Equipo de desarrollo

1. Para qué sirve este documento

El portal B2B Outlet sirve copy en tres idiomas (español, inglés, francés) y un cuarto canal de comunicación (los emails transaccionales) que ya se documenta en 08-emails-transaccionales. Todo el copy custom del theme — botones, formularios, errores, etiquetas de specs de producto, FAQs, mensajes del backoffice — vive en locales/*.json bajo el namespace ledsc4.*. Aquí se documenta cómo está estructurado, cómo se invoca desde Liquid, cuál es el mecanismo de fallback, y los gaps actuales de paridad ES/EN/FR.

No se cubre aquí: el copy de los emails transaccionales (vive en Shopify Email, no en locales/, ver 08 §3), ni las traducciones de productos/colecciones gestionadas por Shopify Translate & Adapt sobre metafields (ver §7), ni el routing de URLs por idioma (queda fuera del scope actual del theme — el portal B2B sirve todo bajo shop.ledsc4.com y la detección de idioma se hace con request.locale.iso_code).

Lectores principales: cualquier dev o IA que tenga que añadir, modificar o auditar copy en el theme. Hoy el corpus de claves ledsc4.* es de 261 keys, con paridad completa ES = EN = FR (ver §8); cualquier cambio de copy se hace aquí, no en Liquid hardcoded.

2. Inventario de locales

locales/ contiene 56 archivos: 28 pares .json + .schema.json correspondientes a 28 idiomas que vienen heredados de Dawn. De ellos, solo 3 idiomas están realmente activos en el theme del portal B2B:

Locale .json (runtime) .schema.json (Theme Editor) Estado Tamaño .json
es.default sí, completo Default activo (SoT) 43 KB
en sí, completo Activo, paridad 261/261 con ES (§8) 60 KB
fr sí, completo Activo, paridad 261/261 con ES (§8) 45 KB
25 idiomas Dawn vanilla sí, sin ledsc4.* sí en la mayoría Sin traducir, no activables sin trabajo 19–32 KB

Los 25 idiomas Dawn vanilla son: bg, cs, da, de, el, fi, hr, hu, id, it, ja, ko, lt, nb, nl, pl, pt-BR, pt-PT, ro, ru, sk, sl, sv, th, tr, vi, zh-CN, zh-TW. Todos contienen las keys nativas Dawn traducidas (cart, account, products, etc.) pero ninguno contiene el namespace ledsc4.*, que es donde vive el 100% del copy custom del portal B2B. Activarlos en un mercado nuevo implica añadir las ~230 keys de ledsc4.* al archivo, no solo encender el idioma en Markets.

Diferencia entre .json y .schema.json (convenio Dawn estándar):

  • nombre.json traduce strings que se renderizan en runtime vía el filtro 'key' | t. Es lo que ve el cliente final en el storefront.
  • nombre.schema.json traduce los settings del Theme Editor (labels y descripciones de campos en settings_schema.json y en {% schema %} de cada section). Es lo que ve el merchant en Admin → Online Store → Themes → Customize.
  • es.default.json y es.default.schema.json llevan el sufijo .default porque marcan el locale por defecto del theme. Solo un locale puede tener ese sufijo; el resto van sin él.

Para el portal B2B, el archivo crítico es es.default.json (fuente de verdad del copy custom). en.json y fr.json son traducciones de ese corpus que conviven con keys Dawn vanilla en inglés/francés. Los .schema.json son menos críticos porque el portal B2B no expone settings al merchant para que los traduzca.

3. Namespace ledsc4.* — el copy custom

Todo el copy custom del portal B2B vive bajo un único namespace raíz ledsc4.*, dividido en 13 sub-namespaces por dominio funcional. El namespace existe para mantener el copy custom limpiamente separado de las keys Dawn (que ocupan los namespaces general, products, sections, customer, etc.), facilitar auditoría de paridad entre idiomas (todo lo que falta empieza por ledsc4.), y permitir que dawn-sync.yml actualice las claves Dawn sin tocar lo nuestro.

Sub-namespace Propósito Section/snippet que lo consume
ledsc4.facets Filtro custom de stock mínimo en colecciones snippets/collection-sidebar-nav.liquid
ledsc4.common Compartido: CTAs, países, currency switcher, footer legal, greeting, eyebrows sections/footer.liquid, header, múltiples landings
ledsc4.product Specs de producto (~25 claves), tabs, documentos descargables snippets/product-specs-table.liquid, snippets/product-documents.liquid
ledsc4.acceso Landing /pages/acceso-profesional (hero, qué es, quién, cómo, FAQ, form de registro) sections/main-acceso-profesional.liquid
ledsc4.checkout Disclaimer legal del checkout (HTML largo) theme.liquid (gate)
ledsc4.collection Sidebar de categorías snippets/collection-sidebar-nav.liquid
ledsc4.portal Página de bienvenida pre-login (/pages/portal-b2b) section custom de portal
ledsc4.aprobado_home Dashboard del cliente aprobado snippets/b2b-dashboard-cards.liquid
ledsc4.registro_recibido Confirmación post-registro (/pages/registro-recibido) sections/main-registro-recibido.liquid
ledsc4.solicitudes Solicitudes de pedido: form, lista, detalle, estados, errores JS sections/b2b-*-solicitudes-*.liquid
ledsc4.cart CTA y disclaimer del carrito B2B section custom de cart
ledsc4.account Dashboard, revisión y rechazada (estados del cliente) sections/main-account.liquid y variantes
ledsc4.header Aria-labels del header (brand, menú, cart) sections/header.liquid

Algunas convenciones observables dentro del namespace:

  • Los sub-namespaces orientados a una pantalla (acceso, portal, registro_recibido, aprobado_home, account.dashboard) agrupan toda la copy de esa pantalla, incluyendo eyebrow + heading + lead + bloques de contenido + CTAs.
  • Los errores JS van en solicitudes.form.js_errors.*, solicitudes.lista.js_errors.*, solicitudes.detalle.js_errors.* y acceso.form.banner.*. Se pre-resuelven en Liquid y se pasan a JS por data-* attributes (ver §5).
  • Las claves con sufijo _html contienen HTML inline (typografía con <em>, <strong>, links). Cualquier locale que las traduzca debe preservar el HTML — Liquid renderiza el valor sin escapar cuando la key termina en _html.
  • Las claves con sufijo _aria son aria-labels para accesibilidad.
  • Las pluralizaciones usan la convención Dawn (one / other / many): por ejemplo solicitudes.dashboard_cards.producto.one y .other. Liquid las resuelve automáticamente con | t: count: n.
  • Algunas claves admiten variables: {{ year }} en common.footer.copyright_html, {{ count }} en pluralizaciones, {{ name }} en common.greeting.hola_name, {{ email }} en account.revision.correct_html. Se pasan al filtro t como named arguments.

4. Mecanismo i18n en Liquid

El theme usa el filtro estándar Shopify 'key.path' | t para resolver una clave del locale activo:

{{ 'ledsc4.common.cta.login' | t }}
{{ 'ledsc4.acceso.hero.heading_html' | t }}
{{ 'ledsc4.solicitudes.dashboard_cards.producto' | t: count: cart.item_count }}
{{ 'ledsc4.common.greeting.hola_name' | t: name: customer.first_name }}

El locale activo se determina por request.locale.iso_code, que viene del idioma seleccionado por el cliente vía el language switcher (que a su vez lee de localization.available_languages definido en Markets). No hay detección automática por Accept-Language ni cookies — es selección manual del cliente, persistida por Shopify entre visitas.

Comportamiento cuando una clave no existe en el locale activo:

  1. Shopify intenta resolver la clave en el locale activo.
  2. Si la clave no existe en ese locale, no hace fallback al locale default — devuelve el texto literal Translation missing: <locale>.<key.path>.
  3. Ese texto se renderiza tal cual en el storefront y es visible para el usuario final.

Esto es el comportamiento estándar Shopify y la razón por la que la paridad ES/EN/FR del namespace ledsc4.* importa. Una key sin traducir en en.json resulta en Translation missing: en.ledsc4.solicitudes.table.th_subtotal impreso en pantalla, no en el valor de es.default.json. Auditoría completa de gaps en §8.

Caso particular: cuando una key existe en el locale pero su valor es string vacío "", Shopify lo renderiza como vacío (no como "Translation missing"). Esto es peligroso porque un "" esconde el gap: el cliente ve una sección vacía en lugar de "Translation missing", y no salta en monitoreo automático que solo busca el literal "Translation missing". Históricamente esto ocultó gaps en fr.json (portal.*, checkout.disclaimers.body_html estaban a ""); se resolvieron en la remediación de 2026-05-16 (§8). Regla vigente: nunca dejar una key a "" como placeholder de "pendiente de traducir" — ver §10.

5. Patrón de cascade i18n para errores JS

Particularidad documentada también en 03 §5 y 08 §5: el portal B2B necesita pasar mensajes traducidos a código JavaScript (errores de validación de form, errores de red, mensajes de éxito). Shopify no expone | t en JS — solo en Liquid. El patrón usado es cascade Liquid → DOM → JS:

<form
  data-err-required="{{ 'ledsc4.acceso.form.err.required' | t }}"
  data-err-email="{{ 'ledsc4.acceso.form.err.email' | t }}"
  data-err-nif="{{ 'ledsc4.acceso.form.err.nif' | t }}"
  data-err-terms="{{ 'ledsc4.acceso.form.err.terms' | t }}"
  data-banner-config-missing="{{ 'ledsc4.acceso.form.banner.config_missing' | t }}"
  data-banner-network-error="{{ 'ledsc4.acceso.form.banner.network_error' | t }}"
>

Y desde JS:

const form = document.querySelector('[data-form-registro]');
const err = form.dataset.errRequired;       // Ya traducido
const banner = form.dataset.bannerNetworkError;

Regla crítica: la traducción | t se resuelve antes del cascade al DOM. Pasarle un string Liquid sin resolver (data-err="ledsc4.acceso.form.err.required") no traduce nada — el JS ve la key literal. El error histórico documentado en PR #B fue exactamente este: las claves se pasaban sin pre-resolver y los errores aparecían como ledsc4.acceso.form.err.required al usuario final.

Para placeholders con variables ({name}, {message}, {error} — sintaxis con llaves simples, no Liquid), el JS hace la sustitución después de recibir el string ya traducido. Por ejemplo en solicitudes.form.js_errors.network:

const tpl = form.dataset.errNetwork; 
// "Error de red al enviar la solicitud: {message}"
const msg = tpl.replace('{message}', errorObject.message);

Ese patrón se repite en solicitudes.lista.js_errors.api, solicitudes.detalle.js_errors.load, acceso.form.banner.email_exists_html con {{ login_url }}, etc. La validación NIF / CIF / NIE específica también se pre-resuelve (ver 05 §6).

6. Convenciones de claves

Reglas observables y aplicadas consistentemente en el corpus actual:

Sufijos en el nombre de la key

  • _html — el valor contiene HTML inline (links, énfasis, listas ordenadas). Liquid renderiza el valor sin escapar HTML cuando la key termina en _html. Aplicable a: terms_html, body_html, copyright_html, heading_html, paragraph_html, etc.
  • _aria — aria-label para accesibilidad. No se traduce en .schema.json sino en .json. Aplicable a: brand_aria_inicio, menu_aria, cart_aria, aria_legal.
  • _label, _placeholder, _hint — para campos de formulario. label es el texto visible, placeholder el texto dentro del input, hint la ayuda contextual debajo.
  • _loading — texto del botón mientras espera respuesta del servidor (submit_loading, loading).

Estructura jerárquica

  • Nivel 1: ledsc4 (raíz custom, separa de Dawn).
  • Nivel 2: dominio (acceso, solicitudes, common, product, etc.).
  • Nivel 3 en adelante: sub-bloque (form, hero, faq, status, table) y luego key concreta.
  • Las pantallas con bloques de contenido en grid (FAQ con varias preguntas, "cómo funciona" con steps, "qué hay dentro" con features) numeran con q1_summary / q1_body, step1_title / step1_desc, f1_title / f1_desc. No usar question_1 ni pregunta_uno — el corpus actual es consistente con el patrón qN_summary/qN_body y stepN_title/stepN_desc.

Variables

  • Liquid: {{ year }}, {{ name }}, {{ email }}, {{ count }}, {{ quantity }}, {{ price }}. Sintaxis de doble llave. Se pasan al filtro t como named arguments: | t: name: customer.first_name.
  • JavaScript: {name}, {message}, {error}, {email}. Sintaxis de llave simple para evitar que Liquid intente resolverla en server-side. El JS las sustituye con .replace('{var}', value) después de leer el string del DOM.

Idioma de los identificadores

Los nombres de keys están en español (acceso, solicitudes, registro_recibido, rechazada, aprobado_home, volumen, pais, instalador). Es deliberado y coherente con el origen español del proyecto: las keys son nombres internos para devs, los valores son lo que ve el usuario. Cambiar las keys a inglés implicaría tocar también el Liquid de todas las sections custom — fuera de scope. El convenio se mantiene.

7. Shopify Translate & Adapt

Separado del namespace ledsc4.*, los archivos en.json y fr.json contienen también bloques shopify.* y customer_accounts.* auto-generados por la app nativa Shopify Translate & Adapt. Ejemplo de en.json líneas 700+:

{
  "shopify": {
    "checkout": {
      "general": { ... },
      "stock": { ... },
      "order_summary": { ... },
      "shipping": { ... },
      ...
    }
  },
  "customer_accounts": { ... }
}

Estos bloques no se editan a mano. Son la capa de traducciones que Translate & Adapt usa para el checkout extension-based, el customer account hub, y otras superficies nativas Shopify (notificaciones, app de admin, etc.). El convenio Dawn los acepta dentro del mismo <locale>.json para que el theme pueda referenciar esas claves desde Liquid si las necesita, pero el flujo de creación/edición es la app, no edición manual del archivo. Tocarlos a mano corre el riesgo de ser sobrescrito en la próxima sincronización de Translate & Adapt.

Para el portal B2B esto importa porque:

  1. Cualquier diff sobre en.json o fr.json que toque líneas dentro de shopify.* o customer_accounts.* es ruido — debe revertirse antes de mergear.
  2. Si en algún momento Translate & Adapt re-genera estos bloques (por ejemplo tras actualizar la versión del checkout), el diff resultante puede ser grande pero es benigno. No requiere revisión línea a línea.
  3. El namespace propio ledsc4.* está aislado de estos bloques. No hay riesgo de colisión.

es.default.json no tiene bloques shopify.* ni customer_accounts.* (es el default, Shopify no necesita traducirlos). En en.json y fr.json están porque son traducciones objetivo.

8. Auditoría de paridad ES/EN/FR

Estado actual (2026-05-16): paridad completa. ES = EN = FR = 261 keys ledsc4.*. 0 ausentes, 0 strings vacíos, 0 traducciones rotas conocidas.

La auditoría de mayo 2026 detectó drift acumulado en en.json y fr.json (FR peor que EN: tenía áreas funcionales rotas, no solo cosméticas). Se remedió el 2026-05-16 vía edición directa de archivo (§9, vía 2b — no T&A, para no re-romper acrónimos y registro). El detalle de qué estaba mal y cómo se corrigió queda como registro abajo; no es trabajo pendiente.

Registro de remediación (2026-05-16)

en.json — 11 keys ausentes añadidas, 2 vacías rellenadas, 2 rotas corregidas:

  • Añadidas: common.country.pt/.ad, product.specs.material/.ip/.ik, acceso.form.label_email/.label_sector, solicitudes.table.th_subtotal, solicitudes.lista.th_ref, solicitudes.lista.js_errors.api, solicitudes.detalle.js_errors.api.
  • Rellenadas (estaban ""): collection.sidebar.categories_label → "Categories", solicitudes.form.comentario_hint.
  • Corregidas (machine-translation rota): solicitudes.table.th_uds "You (formal, plural)""Qty"; product.specs.cri "ICC""CRI"; product.specs.regulacion "Regulation""Dimming" (es dimming, no normativa); acceso.como.fast_tag "Express lane""Fast track".

fr.json — estado de partida peor; bloque account.* completo ausente, varios "" críticos:

  • Bloque ledsc4.account.* completo añadido (dashboard 8 keys + revision 3 + rechazada 4 = 15 keys). Era bloqueante para clientes FR aprobados/rechazados.
  • Añadidas: common.footer.copyright_html, common.country.pt, product.specs.cri, acceso.form.label_nif, solicitudes.detalle.cbm_total_label.
  • Rellenadas (estaban ""): checkout.disclaimers.body_html (tenía implicación legal — avisos de IVA/portes/no devoluciones no se mostraban al cliente FR), portal.heading_html/.lead/.f1_title/.f1_desc, collection.sidebar.categories_label, solicitudes.form.comentario_hint.
  • Corregidas (acrónimos rotos): product.specs.ip "PI""IP", .ik "OK""IK", .material "Matériel""Matériau", .regulacion "Réglementation""Gradation" (dimming, no normativa); solicitudes.table.th_uds "Vous.""Qté".
  • Corregido registro tuteo → vouvoiement: acceso.como.step1_title ("Tu t'inscris""Vous vous inscrivez"), acceso.ctas_lead.

Origen del drift: el bug th_uds ("Uds." → "You"/"Vous.") y regulacion → "Réglementation" sugieren que la traducción FR se generó desde EN (no desde ES) con auto-traducción que rompe acrónimos/abreviaturas. La remediación se hizo desde ES como SoT para cortar la propagación. Si en el futuro se vuelve a usar T&A sobre ledsc4.*, revisar a mano product.specs.* y solicitudes.table.* antes de publicar (§9).

Cómo mantener la paridad

No volver a editar ledsc4.* en EN/FR sin verificar paridad después. El check rápido (Node, robusto frente a la cabecera /* */ de los .json):

node -e '
const fs=require("fs");
const strip=s=>s.replace(/\/\*[\s\S]*?\*\//g,"");
const flat=(o,p="",a={})=>{for(const k in o){const v=o[k],n=p?p+"."+k:k;(v&&typeof v=="object")?flat(v,n,a):a[n]=v}return a};
const L=f=>flat(JSON.parse(strip(fs.readFileSync("locales/"+f,"utf8"))));
const es=L("es.default.json"),en=L("en.json"),fr=L("fr.json");
const K=o=>Object.keys(o).filter(k=>k.startsWith("ledsc4."));
const esK=K(es);
console.log("EN missing:",esK.filter(k=>!(k in en)));
console.log("FR missing:",esK.filter(k=>!(k in fr)));
console.log("EN empty:",K(en).filter(k=>en[k]===""));
console.log("FR empty:",K(fr).filter(k=>fr[k]===""));
'

Salida esperada: cuatro arrays vacíos. Pendiente automatizarlo en CI (§11).

9. Cómo añadir un idioma nuevo al portal

Pasos para activar un cuarto idioma (por ejemplo, alemán de) más allá de los 3 actuales:

  1. Asegurar el locale en Markets. Admin → Settings → Markets → mercado destino → Languages → añadir alemán. Esto activa el switcher y permite a Shopify resolver request.locale.iso_code == 'de'.

  2. Traducir el namespace ledsc4.* en de.json. El archivo Dawn de.json ya existe pero no contiene ledsc4.*. Hay dos caminos:

  3. Vía Translate & Adapt (recomendado para arranque rápido). La app lee es.default.json como source y permite traducir las claves ledsc4.* al alemán desde su UI. Genera commits sobre de.json. Limitación: traducción automática rompe acrónimos técnicos (IP, IK, CRI, NIF), tuteo vs vouvoiement, abreviaturas (Uds. → "ustedes"). Revisar a mano todo el bloque ledsc4.product.specs.* y ledsc4.solicitudes.table.* antes de publicar.

  4. Vía edición directa del archivo. Copiar ledsc4.* de es.default.json a de.json, traducir manualmente. Más lento pero sin las trampas de la traducción automática. Aplica también para los _html (preservar HTML inline).

  5. Verificar paridad. Comparar las claves de ledsc4.* en de.json contra es.default.json. Todas las keys deben existir, sin strings vacíos en pantallas visibles (portal, account, checkout). Auditoría manual recomendada antes de publicar.

  6. Añadir traducción de countries y currency. ledsc4.common.country.* lista los países objetivo del portal (ES, PT, FR, IT, DE, GB, NL, BE, AD, MA). Si el nuevo idioma cubre un país no listado, añadirlo.

  7. Revisar el patrón cascade de errores JS (§5). Las claves js_errors.* y banner.* deben estar todas presentes en el nuevo locale o los errores se mostrarán como Translation missing: de.ledsc4.solicitudes.form.js_errors.network al usuario en lugar del mensaje traducido.

  8. Email transaccional. Crear los 5 templates W1-acuse, W1-bienvenida, W2-aprobacion, W3-rechazo, W5-acuse en alemán y añadir la rama de condición de idioma en cada workflow de Flow (ver 08 §10). El namespace ledsc4.* no cubre los emails — viven en Shopify Email.

  9. Test E2E. Cliente nuevo simulado con locale = de, recorrido completo: portal → form de registro → email W1-acuse → dashboard revisión → tag aprobado → email W1-bienvenida o W2-aprobacion → catálogo → solicitud → email W5-acuse → ver solicitud en lista y detalle. Cualquier pantalla con Translation missing o strings vacíos es bloqueante.

10. Procedimientos comunes

Añadir una nueva key

  1. Definirla en es.default.json siguiendo las convenciones del §6 (sufijos _html/_aria, jerarquía, idioma español para el identificador).
  2. Añadir su traducción en en.json y fr.json con el mismo path. Si todavía no hay traducción, no añadirla con valor vacío "" (oculta el problema) ni omitirla (renderiza "Translation missing" en pantalla). Mejor poner el valor en español temporalmente como placeholder y documentar en commit que falta traducir.
  3. Usarla en Liquid con 'ledsc4.namespace.key' | t. Si se necesita en JS, pre-resolverla a un data-* attribute (§5).
  4. Si forma parte de un bloque ya existente (ledsc4.solicitudes.form.*), añadirla en el mismo bloque del JSON, no como key suelta.

Cambiar el copy de una key existente

  1. Editar es.default.json (SoT).
  2. Actualizar en.json y fr.json con la traducción correspondiente. Si solo se traduce uno, el otro queda con la versión vieja (no rompe, pero genera divergencia que el cliente percibe al cambiar idioma).
  3. Si la key contiene HTML inline (_html), preservar la estructura HTML en todos los locales. Cambiar el HTML solo en uno rompe la consistencia visual entre idiomas.
  4. Si la key tiene variables ({{ count }}, {{ name }}), preservarlas en todos los locales — Shopify no avisa si una traducción olvida la variable, simplemente no la interpola y muestra texto sin sustituir.

Auditar paridad EN/FR contra ES

A día de hoy no hay script committido en CI (pendiente, §11). Usar el check Node de §8 ("Cómo mantener la paridad"): lista keys ausentes y vacías en EN y FR de una pasada y es robusto frente a la cabecera /* */ de los .json (importante: jq falla al parsear estos archivos por esa cabecera, y el entorno Windows del proyecto no trae jq). Salida esperada tras cualquier cambio de copy: cuatro arrays vacíos.

Editar un bloque shopify.* o customer_accounts.*

No. Esos bloques los genera Translate & Adapt. Para cambiar copy ahí, editar desde Admin → Apps → Translate & Adapt. Cualquier edición manual será sobrescrita en la próxima sync de la app.

11. Pendientes

Los pendientes de paridad ES/EN/FR (bloque account.* FR, strings vacíos, traducciones rotas, tuteo/vouvoiement, country.pt/.ad) se resolvieron el 2026-05-16 — ver registro de remediación en §8. Lo que queda abierto:

  • Script de auditoría automática de paridad — añadir a .github/workflows/ un job que corra el check de §8 ("Cómo mantener la paridad") sobre los tres locales y falle el PR si algún array no está vacío. Hoy es manual; el drift remediado en mayo 2026 fueron varias semanas sin detección. Es la prioridad para que la paridad no vuelva a degradarse.

  • pt-PT y el parámetro ?locale= — al activar un cuarto idioma con variante regional (p. ej. pt-PT), verificar si la Customer Account API necesita mapeo BCP47 regional (pt-PTpt) en ?locale=. Deuda anotada; revisar antes de activar el idioma.

  • Decisión sobre los 25 locales Dawn vanillabg.json, cs.json, ..., zh-TW.json ocupan ~600 KB del repo sin aportar nada al portal B2B (no contienen ledsc4.* y no hay markets activos para esos idiomas). Tres opciones: (a) borrarlos para reducir ruido, (b) dejarlos como reserva para futuros mercados, (c) borrarlos y dejar solo los .schema.json correspondientes para mantener Dawn coherente. Recomendación: (a), borrar todos los .json Dawn vanilla y sus .schema.json correspondientes salvo es.default, en, fr. Si en el futuro se necesita alemán/italiano/holandés, recuperar el archivo de Dawn upstream y traducir ledsc4.* desde cero.

  • Documentar las variables disponibles por key — el corpus actual mezcla variables Liquid ({{ var }}) y JS ({var}) sin documentación inline. Posible mejora: añadir comentarios al .json (no estándar pero el header del archivo ya tiene un comentario /* ... */ que Shopify acepta).

  • ledsc4.* y dawn-sync.yml — verificar que el workflow dawn-sync solo actualiza las claves Dawn upstream (general, products, sections, customer, etc.) y nunca toca el namespace ledsc4.* ni los bloques shopify.* / customer_accounts.*. Cross-link a 13-github-actions cuando exista.

Cambios

  • v1.0 (17-may-2026): cabecera de estado añadida; documento ya estaba completo. Primera publicación del contenido: 16-may-2026.