Saltar al contenido

Guías

Trabajar con traductores

Tus catálogos son JSON normal, sin nada propietario que convertir. Eso te da tres formas de traducir: pasarle los ficheros a un TMS, ir y volver con ficheros de traductor usando 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) leen catálogos JSON de forma nativa. Apuntas la plataforma a locales/ y ya está: sin paso de exportación y sin formato propio. Las traducciones vuelven en los mismos ficheros, 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 las herramientas CAT lo abren directamente. Tus huecos y tus etiquetas viajan ahí como fichas protegidas con nombres con sentido, así que un traductor no las puede romper sin querer; las palabras de plural y de select se quedan editables, porque esas sí hay que traducirlas. Gettext PO funciona con Poedit y con cualquier herramienta de PO, y CSV es para todos los demás, editable en cualquier sitio. Todos los formatos dicen dónde vive cada texto en tu fuente, 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
npx verbaly import es.xlf --draft      # keep it as drafts until someone reads it

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. Se lee como uno de tus idiomas, así que el pt_BR de gettext llena tu pt-BR. Un idioma nuevo empieza su catálogo con el código bien escrito, salvo que tu config liste sus locales: entonces un idioma fuera de esa lista se salta con un aviso y código de salida 1, porque tu app nunca lo cargaría. Pasa --draft cuando nadie ha leído aún el archivo: lo que trae queda marcado como borrador hasta que alguien lo apruebe.

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 falla cuando la traducción no puede decir lo mismo, y cada build la lista. No hace falta que recuerdes estas reglas: si rompes una, el error te dice cuál y dónde.

Cuando alguien cambia un texto fuente, sus traducciones no se quedan como si nada hubiera pasado. Verbaly registra para qué texto fuente se escribió una traducción en el momento en que se escribe, ya sea un proveedor, un agente, Studio o un archivo importado, y la marca como desactualizada en cuanto ese texto cambia, hasta que se actualiza, o se mantiene con verbaly review --approve cuando sigue diciendo lo correcto. El archivo de un traductor trae el texto fuente del que partió, así que un archivo traducido de una versión anterior queda desactualizado en cuanto llega. Editar una traducción quita la marca sola.

npx verbaly status es el vistazo rápido: cuánto está traducido por idioma, cuánto espera revisión, cuánto está desactualizado 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 verbaly.lock, junto a tu config. Como el lockfile de un gestor de paquetes, Verbaly lo escribe, tú lo committeas con tus catálogos y nadie lo edita a mano, así nadie confunde la salida de la máquina con trabajo revisado. Si un merge lo deja con un conflicto, Verbaly conserva los borradores de los dos lados y el siguiente extract lo escribe entero: inclúyelo en el commit del merge. Borrarlo marcaría todos los borradores como revisados.

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. Tampoco le cuesta a nadie su trabajo: un mensaje que alguien guardó mientras la corrida estaba fuera conserva su texto, y el informe dice cuántos respetó.

verbaly review lista lo que espera, borradores de la máquina y traducciones escritas para un texto fuente anterior, cada uno con el texto que se publica al lado de su traducción. verbaly review --approve lo acepta después de leerlo, seguido de claves cuando quieres aceptar solo esas, 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, y --outdated mientras quede una traducción desactualizada.

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, también las traducciones que escriba él mismo.

↑↓para moverteEnterpara abrir
Copiado en el portapapeles