La CLI traduce dieciocho formatos de archivo. El formato se deduce por la extensión del archivo; configura format en una entrada de files[] para sobrescribirlo, o en los tres formatos que siempre lo requieren (yaml-openapi, yaml-root-key, android).
| Formato | Extensiones | Valor de format | Notas |
|---|---|---|---|
| JSON | .json | json | Clave-valor. Admite controles de clave. |
| JSONC | .jsonc | jsonc | JSON con comentarios. Los comentarios se conservan y también sirven como notas para traductores. |
| YAML | .yaml, .yml | yaml | YAML genérico. Se traduce cada valor de texto; las claves y la estructura se conservan. |
| OpenAPI YAML | .yaml, .yml | yaml-openapi | Especificaciones OpenAPI. Configura format explícitamente: .yaml simple se detecta automáticamente como yaml. |
| Clave raíz de idioma en YAML | .yaml, .yml | yaml-root-key | El idioma es la clave raíz de YAML (Rails config/locales). La clave raíz se reescribe al idioma de destino. Configura format explícitamente. |
| Markdown | .md | md | Se traduce la prosa; el frontmatter es opcional. |
| MDX | .mdx | mdx | Markdown + JSX. Las props de los componentes son opcionales. |
| Markdoc | .mdoc | markdoc | Markdown + etiquetas. Frontmatter + atributos de etiquetas. |
| TypeScript | .ts, .mts, .cts | typescript | Módulos de idioma (export default { … }). Se traducen los literales de texto; el código se conserva. |
| Gettext PO | .po | po | Se traduce msgstr; msgid, los comentarios y los encabezados se conservan. |
| Flutter ARB | .arb | flutter | Se traducen los valores de texto; los metadatos de @ y {placeholders} se conservan. |
| Android | .xml | android | strings.xml. Configura format explícitamente: .xml no se detecta automáticamente. |
| Strings de Xcode | .strings | xcode-strings | Se traducen los valores; las claves se conservan. |
| Catálogo de strings de Xcode | .xcstrings | xcode-xcstrings | Un solo archivo contiene todos los idiomas: los destinos se escriben de vuelta en ese mismo archivo (ver abajo). |
| stringsdict de Xcode | .stringsdict | xcode-stringsdict | Se traducen las cadenas en plural; las claves de control de formato se conservan. |
| XLIFF | .xlf, .xliff | xliff | Se conserva <source>; <target> se escribe por unidad. Versiones 1.2 y 2.0. |
| SubRip | .srt | srt | Se traduce el texto de los subtítulos; los índices y códigos de tiempo quedan intactos. |
| PHP | .php | php | return [ … ] de Laravel. Se traducen los valores de texto; las claves, los números y la estructura se conservan. |
Míralo de principio a fin
El proyecto de demostración es un Sandbox pequeño que incluye los formatos de documentos y datos — JSON, JSONC, Markdown, MDX, Markdoc y OpenAPI YAML — cada uno con la configuración exacta que necesita. Clónalo con npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo y haz un push. Los formatos de apps y frameworks no están incluidos ahí — para esos casos, Proyectos de ejemplo ofrece un repositorio completo por framework, y los fragmentos por formato que aparecen abajo cubren la configuración.
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demoJSON y JSONC#
Traducción simple de clave-valor. Se traduce cada valor de texto, a menos que un control de clave indique lo contrario.
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }JSONC además conserva los comentarios, que el motor usa como contexto; consulta notas para traductores.
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }Markdown, MDX y Markdoc#
La prosa del cuerpo se traduce por defecto. El frontmatter y los componentes incrustados no se traducen, a menos que los actives explícitamente.
Frontmatter#
Indica los campos de frontmatter que quieres traducir con translateFrontmatterFields:
{
"pattern": "content/en/guide.md",
"translateFrontmatterFields": ["title", "description"]
}Props de componentes MDX#
En MDX, puedes traducir props específicas de componentes específicos con translateComponentProps:
{
"pattern": "content/en/landing.mdx",
"translateFrontmatterFields": ["title"],
"translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}Esto traduce las props title y body en <Hero> y <Callout>, y deja intactas todas las demás props.
Markdoc#
Markdoc funciona como Markdown, con frontmatter y atributos de etiquetas preservados:
{
"pattern": "content/en/changelog.mdoc",
"translateFrontmatterFields": ["title"]
}YAML#
El YAML genérico se detecta automáticamente a partir de .yaml/.yml: se traduce cada valor de texto y se conservan las claves y la estructura:
{ "pattern": "content/en/strings.yaml" }Las especificaciones OpenAPI son un caso especial: comparten la extensión .yaml, pero necesitan un format explícito para que el motor traduzca solo los campos orientados a personas (resúmenes, descripciones) y deje intactas las claves de esquema, las rutas y los IDs de operación:
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }Los archivos de idioma al estilo Rails son el otro caso especial: el idioma es la clave raíz de YAML (en:) y el archivo de destino debe tener como raíz el idioma de destino (es:). Configura format explícitamente también en esos casos:
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }Formatos de apps y frameworks#
PO, Flutter ARB, .strings de Xcode, .stringsdict de Xcode, módulos de idioma de TypeScript, XLIFF, SubRip y PHP siguen la misma regla: se traduce el texto traducible y se conserva todo lo estructural (claves, IDs, metadatos, placeholders, códigos de tiempo, código, formato). Cada uno se detecta automáticamente por su extensión; solo apunta un patrón al archivo de origen:
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }Uno requiere un format explícito porque su extensión es demasiado ambigua para detectarse automáticamente:
{ "pattern": "res/values/strings.xml", "format": "android" }Catálogos de strings de Xcode#
Un archivo .xcstrings (String Catalog) contiene todos los idiomas en un solo archivo. No hay una ruta de salida por idioma: el CLI lee el idioma de origen y escribe cada destino de vuelta en ese mismo archivo:
{ "pattern": "Localizable.xcstrings" }Las cadenas marcadas con "shouldTranslate": false en el catálogo se omiten; la CLI las deja sin traducir y sin modificar.
Rutas de salida#
El patrón define el nombre de tu archivo de origen; a partir de él se deriva cada ruta de destino. Se aplican cuatro reglas, en este orden:
- Un segmento completo de la ruta o el nombre del archivo que corresponde al idioma — el caso más habitual.
content/en/app.json→content/de/app.json,locales/en.json→locales/de.json. - Un idioma al final de un segmento o nombre de archivo, para las estructuras que lo expresan así — Android, Xcode
.strings/.stringsdict, Flutter yyaml-root-key.res/values-en/→res/values-de/,app_en.arb→app_de.arb,devise.en.yml→devise.de.yml. - El nombre reservado de una plataforma para el idioma predeterminado, sin que aparezca ningún idioma en la ruta. El
res/values/sin sufijo de Android pasa a serres/values-de/, y elBase.lprojde Xcode pasa a serde.lproj. - El String Catalog, donde la ruta de destino es la ruta de origen, porque un solo archivo contiene todos los idiomas.
Android es la única plataforma cuyas rutas de destino no usan BCP 47: el CLI escribe el calificador de recursos que Android realmente interpreta, así que pt-BR va a values-pt-rBR/ y zh-Hans a values-b+zh+Hans/.
Si ninguna de las reglas coincide — el idioma de origen no aparece en ningún punto de la ruta — el CLI recurre a inventar un directorio <locale>/ junto al archivo, y lingo push te indica que fue una suposición. Toma esa advertencia como señal de que el patrón es incorrecto. Consulta Configuration.
¿Vienes del CLI anterior?#
La mayoría de los formatos del CLI anterior ya están disponibles en el CLI actual (PO, XLIFF, strings de Android/Xcode, Flutter ARB y más; consulta la tabla de arriba). Algunos formatos menos comunes (por ejemplo, CSV, HTML, MJML, .properties) todavía no son compatibles; hasta que el tuyo llegue, la documentación del CLI anterior lo cubre.
