A CLI traduz dezoito formatos de arquivo. O formato é inferido pela extensão do arquivo; defina format em uma entrada files[] para substituí-lo — ou nos três formatos que sempre exigem isso (yaml-openapi, yaml-root-key, android).
| Formato | Extensões | Valor de format | Observações |
|---|---|---|---|
| JSON | .json | json | Chave/valor. Compatível com controles de chave. |
| JSONC | .jsonc | jsonc | JSON com comentários. Os comentários são preservados e também funcionam como notas para tradutores. |
| YAML | .yaml, .yml | yaml | YAML genérico. Todos os valores de string são traduzidos; chaves e estrutura são preservadas. |
| OpenAPI YAML | .yaml, .yml | yaml-openapi | Especificações OpenAPI. Defina format explicitamente — .yaml puro é detectado automaticamente como yaml. |
| Chave raiz de idioma em YAML | .yaml, .yml | yaml-root-key | O idioma é a chave raiz do YAML (Rails config/locales). A chave raiz é reescrita para o idioma de destino. Defina format explicitamente. |
| Markdown | .md | md | O texto é traduzido; o frontmatter é opt-in. |
| MDX | .mdx | mdx | Markdown + JSX. Props de componentes são opt-in. |
| Markdoc | .mdoc | markdoc | Markdown + tags. Frontmatter + atributos de tags. |
| TypeScript | .ts, .mts, .cts | typescript | Módulos de idioma (export default { … }). Literais de string são traduzidos; o código é preservado. |
| Gettext PO | .po | po | msgstr é traduzido; msgid, comentários e cabeçalhos são preservados. |
| Flutter ARB | .arb | flutter | Valores de string são traduzidos; metadados @ e {placeholders} são preservados. |
| Android | .xml | android | strings.xml. Defina format explicitamente — .xml não é detectado automaticamente. |
| Xcode strings | .strings | xcode-strings | Os valores são traduzidos; as chaves são preservadas. |
| Xcode String Catalog | .xcstrings | xcode-xcstrings | Um único arquivo reúne todos os idiomas — os destinos são gravados de volta no mesmo arquivo (veja abaixo). |
| Xcode stringsdict | .stringsdict | xcode-stringsdict | Strings no plural são traduzidas; as chaves de controle de formato são preservadas. |
| XLIFF | .xlf, .xliff | xliff | <source> é mantido, <target> é gravado por unidade. Versões 1.2 e 2.0. |
| SubRip | .srt | srt | O texto das legendas é traduzido; índices e timecodes permanecem intactos. |
| PHP | .php | php | return [ … ] do Laravel. Valores de string são traduzidos; chaves, números e estrutura são preservados. |
Veja tudo em ação
O projeto de demonstração é um pequeno Sandbox com os formatos de documentos e dados — JSON, JSONC, Markdown, MDX, Markdoc e OpenAPI YAML — cada um com a configuração exata de que precisa. Faça o clone com npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo e execute um push. Os formatos de app e framework não estão incluídos nele — nesses casos, os projetos de exemplo trazem um repositório completo para cada framework, e os trechos por formato abaixo mostram a configuração.
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demoJSON e JSONC#
Tradução simples de chave/valor. Todo valor de string é traduzido, a menos que um controle de chave diga o contrário.
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }O JSONC também preserva comentários, que o engine usa como contexto — veja notas para tradutores.
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }Markdown, MDX e Markdoc#
O texto do corpo é traduzido por padrão. Frontmatter e componentes embutidos não são traduzidos, a menos que você ative isso.
Frontmatter#
Liste com translateFrontmatterFields os campos de frontmatter que devem ser traduzidos:
{
"pattern": "content/en/guide.md",
"translateFrontmatterFields": ["title", "description"]
}Props de componentes MDX#
No MDX, traduza props específicas de componentes específicos com translateComponentProps:
{
"pattern": "content/en/landing.mdx",
"translateFrontmatterFields": ["title"],
"translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}Isso traduz as props title e body em <Hero> e <Callout> e deixa todas as outras props intactas.
Markdoc#
O Markdoc funciona como o Markdown, com frontmatter e atributos de tags preservados:
{
"pattern": "content/en/changelog.mdoc",
"translateFrontmatterFields": ["title"]
}YAML#
O YAML genérico é detectado automaticamente a partir de .yaml/.yml — todo valor de string é traduzido, com chaves e estrutura preservadas:
{ "pattern": "content/en/strings.yaml" }Especificações OpenAPI são um caso especial: elas usam a extensão .yaml, mas exigem um format explícito para que o engine traduza apenas os campos voltados ao usuário (resumos, descrições) e mantenha intactos as chaves de schema, os paths e os IDs de operação:
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }Arquivos de idioma no estilo Rails são o outro caso especial: o idioma é a chave raiz do YAML (en:) e o arquivo de destino deve ter o idioma de destino como raiz (es:). Defina format explicitamente nesses casos também:
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }Formatos de apps e frameworks#
PO, Flutter ARB, Xcode .strings, Xcode .stringsdict, módulos de idioma em TypeScript, XLIFF, SubRip e PHP seguem a mesma regra: o texto traduzível é traduzido; tudo o que é estrutural é preservado (chaves, IDs, metadados, placeholders, timecodes, código, formatação). Cada formato é detectado automaticamente pela extensão — basta apontar um padrão para o arquivo de origem:
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }Um deles exige format explícito porque sua extensão é ambígua demais para detecção automática:
{ "pattern": "res/values/strings.xml", "format": "android" }Xcode String Catalogs#
Um arquivo .xcstrings (String Catalog) reúne todos os idiomas em um único arquivo. Não há caminho de saída por idioma — o CLI lê o idioma de origem e grava cada destino de volta no mesmo arquivo:
{ "pattern": "Localizable.xcstrings" }As strings marcadas com "shouldTranslate": false no catálogo são ignoradas — a CLI as mantém sem tradução e inalteradas.
Caminhos de saída#
O padrão define o nome do arquivo de origem; todos os caminhos de destino são derivados dele. Quatro regras se aplicam, nesta ordem:
- Um segmento inteiro do caminho ou um nome de arquivo que seja o idioma — o caso mais comum.
content/en/app.json→content/de/app.json,locales/en.json→locales/de.json. - Um idioma no fim de um segmento ou nome de arquivo, para layouts que usam esse formato — Android, Xcode
.strings/.stringsdict, Flutter eyaml-root-key.res/values-en/→res/values-de/,app_en.arb→app_de.arb,devise.en.yml→devise.de.yml. - O nome reservado de uma plataforma para o idioma padrão, sem nenhum idioma no caminho. O
res/values/do Android virares/values-de/, e oBase.lprojdo Xcode virade.lproj. - O String Catalog, em que o caminho de destino é o caminho de origem, porque um único arquivo reúne todos os idiomas.
Android é a única plataforma cujos caminhos de destino não seguem o BCP 47: a CLI grava o qualificador de recurso que o Android realmente usa, então pt-BR vai para values-pt-rBR/ e zh-Hans para values-b+zh+Hans/.
Se nenhuma das regras se aplicar — ou seja, se o idioma de origem não aparecer em nenhum ponto do caminho — a CLI cria como fallback um diretório <locale>/ ao lado do arquivo, e lingo push avisa que foi uma suposição. Trate esse aviso como um sinal de que o padrão está errado. Consulte Configuration.
Vindo do CLI legado?#
A maioria dos formatos do CLI legado já chegou ao CLI atual (PO, XLIFF, strings de Android/Xcode, Flutter ARB e mais — veja a tabela acima). Alguns formatos menos comuns (como CSV, HTML, MJML e .properties) ainda não têm suporte; até o seu entrar, a documentação do CLI legado cobre isso.
