Saltar al contenido

Guías

Trabajar con traductores

Tus catálogos son JSON plano, sin nada propietario que convertir. Eso te da tres caminos para traducir: entregar los archivos a un TMS, hacer round-trip de archivos de traductor con export/import, o traducir a máquina con translate.

JSON plano, sin lock-in

La mayoría de los TMS (Crowdin, Lokalise, Phrase y compañía) ingieren JSON plano de forma nativa. Apunta la plataforma a locales/ y listo: sin paso de export, sin formato propio. Las traducciones vuelven como los mismos archivos, y cada cambio se revisa como un diff normal.

Export para humanos

Cuando no hay TMS (un traductor freelance, una agencia, un compañero con una hoja de cálculo), verbaly export escribe un fichero listo para traducir por idioma, con el texto original al lado de cada traducción. Si guardas tu catálogo por grupos, exporta una fila por mensaje, nombrada con su ruta completa, así que el traductor ve texto y nunca un grupo.

npx verbaly export                   # verbaly-export/es.xlf, pt.xlf (XLIFF 2.0)
npx verbaly export --format csv      # key,source,target,location (any spreadsheet)
npx verbaly export --format po       # es.po, pt.po (gettext, any PO editor)
npx verbaly export --missing         # only what's untranslated

XLIFF 2.0 es el formato de intercambio de la industria, así que los TMS y herramientas CAT lo abren directo, y tus placeholders y tags viajan en él como fichas protegidas con nombres con sentido, así que un traductor no puede romperlos por accidente (las palabras de plural y select siguen editables: esas sí se traducen). Gettext PO funciona con Poedit y cualquier herramienta PO. CSV es para todos los demás: editable en cualquier lado. Todos los formatos dicen dónde vive cada texto en tu código, así que el traductor ve el contexto en vez de adivinarlo.

Antes de exportar, verbaly status muestra cuánto falta por idioma: es: 45/48 translated (94%).

Import de vuelta, validado

verbaly import lee los archivos traducidos (XLIFF 2.0 o 1.2, CSV o gettext PO) y rellena tus catálogos. Cada entrada pasa la misma validación estructural que la traducción a máquina: placeholders, variantes de plural y tags deben sobrevivir intactos. Lo demás se rechaza y se reporta, nunca se escribe.

npx verbaly import verbaly-export/es.xlf
#   es: +42 imported
#   es: 1 rejected (params/tags not preserved): home.greeting
npx verbaly import es.csv --dry-run    # preview without writing
npx verbaly import es.xlf --overwrite  # replace existing translations

Las traducciones existentes se conservan salvo que pases --overwrite; las keys desconocidas se ignoran y se reportan. Las entradas que una herramienta PO marca como fuzzy cuentan como sin traducir. El idioma destino sale del propio archivo (o del nombre del archivo), y --locale gana sobre ambos.

La red de seguridad, en palabras simples

Editar locales/es.json a mano es una forma perfectamente válida de traducir, y recibe la misma protección que un archivo importado. verbaly check lee cada traducción al lado de su original y detiene el build cuando la traducción no puede decir lo mismo. No hace falta que recuerdes estas reglas: si rompes una, el error te dice cuál y dónde.

npx verbaly status es el vistazo rápido: cuánto está traducido por idioma, cuánto espera revisión y cuánto está roto.

Exportar para apps móviles

Los mismos catálogos pueden viajar a una app móvil hermana como recursos nativos: android-xml escribe carpetas strings.xml que puedes soltar en res/, y ios-strings escribe carpetas .lproj para Xcode.

npx verbaly export --format android-xml   # verbaly-export/values-es/strings.xml, values-pt-rBR/…
npx verbaly export --format ios-strings   # verbaly-export/es.lproj/Localizable.strings, …

Tu idioma fuente se vuelve el default de la plataforma (values/strings.xml, en.lproj), y las claves sin traducir se omiten para que la app haga fallback a él en vez de mostrar texto vacío. Las keys se adaptan a nombres de recurso válidos de Android, los valores conservan su sintaxis de parámetros intacta, y el flujo es de ida: las traducciones van de tus catálogos a la app.

¿Aún sin humanos disponibles?

La traducción a máquina llena los huecos con las mismas garantías estructurales, y todo lo que un provider o una persona haga mal lo atrapa verbaly check en CI.

La salida de la máquina llega marcada como borrador: translate registra lo que escribió en locales/.verbaly-drafts.json, committeado con tus catálogos y jamás editado a mano, así nadie lo confunde con trabajo revisado.

npx verbaly translate            # es: +12 translated (draft)
npx verbaly review               # list what's waiting for a human
npx verbaly review --approve     # accept after reading
npx verbaly check --drafts       # CI gate: fail while drafts remain

Antes de la primera corrida, escribe lo que no se traduce. Los nombres de tu producto, los de sus funciones y cualquier forma que ya hayas decidido van en translate.glossary, y cómo tratas al lector va en translate.instructions. Sale más barato que corregir la misma palabra a mano después de cada corrida.

Una corrida larga sobrevive a una mala conexión. Las peticiones que fallan por algo pasajero se reintentan, y si aun así una no vuelve, todo lo demás queda guardado y el informe nombra los mensajes que no pudo llenar. Volver a correr translate pide solo esos, así que una corrida cortada nunca te cuesta todo dos veces.

verbaly review lista lo que espera, verbaly review --approve lo acepta después de leerlo, y un archivo de traductor traído con import cuenta como revisión por sí solo. En CI, verbaly check --drafts sigue fallando mientras queden borradores sin revisar.

Un agente de código puede correr este mismo ciclo a través del servidor MCP: lo que traduzca sigue llegando como borrador detrás de la misma puerta de revisión.

Copiado en el portapapeles