A CLI suporta monorepos de forma nativa. Pode usar um único i18n.json na raiz com um glob recursivo ** para detetar automaticamente os pacotes, uma única configuração na raiz com caminhos explícitos por pacote, ou ficheiros i18n.json separados em cada pacote, combinados com uma GitHub Action com estratégia de matriz.
Quando usar cada padrão#
| Cenário | Padrão | Ficheiros de configuração | GitHub Action |
|---|---|---|---|
| Todos os pacotes partilham a mesma estrutura e os mesmos idiomas, e quer que novos pacotes sejam detetados automaticamente | Configuração única recursiva | Um i18n.json na raiz com um glob ** | Um passo, working-directory predefinido |
| Todos os pacotes partilham os idiomas de origem e de destino | Configuração única | Um i18n.json na raiz | Um passo, working-directory predefinido |
| Os pacotes precisam de idiomas de destino diferentes | Configurações por pacote | Um i18n.json por pacote | Estratégia de matriz com working-directory |
| Os pacotes precisam de motores diferentes (glossário, voz da marca) | Configurações por pacote + motores separados | Um i18n.json por pacote, cada um com o seu próprio engineId | Estratégia de matriz com working-directory |
Padrão 1: Configuração única recursiva#
Quando todos os pacotes seguem a mesma estrutura (por exemplo, apps/<name>/locales/[locale].json), use um glob recursivo ** num único i18n.json na raiz. Os novos pacotes são detetados automaticamente, desde que respeitem essa estrutura:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": ["apps/**/locales/[locale].json"]
}
}
}A CLI ignora node_modules, .git, dist, build, .next e .turbo por predefinição, pelo que os padrões recursivos não descem para árvores vendorizadas ou de build. Adicione as suas próprias entradas exclude para tudo o resto que queira ignorar.
A GitHub Action é idêntica à do Padrão 2 abaixo: um passo, com o diretório de trabalho predefinido.
Use este padrão quando todos os pacotes partilham o mesmo idioma de origem, os mesmos idiomas de destino, a mesma estrutura e o mesmo motor de localização, e não quer editar i18n.json sempre que adiciona um pacote.
Padrão 2: Configuração única, idiomas partilhados#
Um i18n.json na raiz do repositório. Os caminhos dos buckets apontam explicitamente para cada pacote:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": [
"apps/web/locales/[locale].json",
"apps/dashboard/locales/[locale].json"
]
},
"markdown": {
"include": ["packages/docs/content/[locale]/*.md"]
}
}
}GitHub Action — passo único padrão:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
translate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
pull-request: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Use este padrão quando todos os pacotes partilham o mesmo idioma de origem, os mesmos idiomas de destino e o mesmo motor de localização, mas as estruturas diferem o suficiente para que um glob recursivo seja demasiado abrangente.
Padrão 3: Configurações por pacote, idiomas diferentes#
Cada pacote tem o seu próprio i18n.json, com idiomas de destino independentes:
apps/web/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja", "ko", "zh-Hans"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
}
}
}apps/marketing/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
},
"markdown": {
"include": ["content/[locale]/*.md"]
}
}
}GitHub Action — estratégia de matriz com working-directory:
name: Translate
on:
push:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
translate:
runs-on: ubuntu-latest
strategy:
matrix:
package: [apps/web, apps/marketing]
steps:
- uses: actions/checkout@v4
- uses: lingodotdev/lingo.dev@main
with:
api-key: ${{ secrets.LINGODOTDEV_API_KEY }}
working-directory: ${{ matrix.package }}
pull-request: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Cada entrada da matriz executa a CLI no âmbito do i18n.json desse pacote. A action traduz apenas os ficheiros declarados por esse pacote.
Padrão 4: Configurações por pacote, motores separados#
A estrutura é a mesma do Padrão 3, mas cada pacote liga-se a um motor de localização diferente. Isto dá a cada pacote o seu próprio glossário, voz da marca e configuração de modelo.
apps/product/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr", "de", "ja"]
},
"buckets": {
"json": {
"include": ["locales/[locale].json"]
}
},
"engineId": "eng_ProductApp123"
}apps/docs/i18n.json:
{
"$schema": "https://lingo.dev/schema/i18n.json",
"version": "1.15",
"locale": {
"source": "en",
"targets": ["es", "fr"]
},
"buckets": {
"markdown": {
"include": ["content/[locale]/*.md"]
}
},
"engineId": "eng_DocsEngine456"
}O YAML da GitHub Action é idêntico ao do Padrão 3 — o engineId em cada i18n.json encaminha automaticamente as traduções para o motor correto.
Como funciona o lockfile#
Cada localização de i18n.json gera o seu próprio ficheiro i18n.lock no mesmo diretório. O lockfile regista que conteúdo de origem já foi traduzido, permitindo atualizações incrementais. Nos Padrões 1 e 2, há um lockfile na raiz. Nos Padrões 3 e 4, cada pacote tem o seu próprio lockfile.
FAQ#
Os novos pacotes são detetados automaticamente?
Só no Padrão 1 (com ** recursivo). Nos Padrões 3 e 4, adiciona uma nova entrada à lista matrix.package do workflow quando adiciona um pacote.
Posso ter idiomas diferentes por pacote?
Sim. Use o Padrão 3 ou 4. O i18n.json de cada pacote declara, de forma independente, o seu próprio array locale.targets.
Preciso de um ficheiro de workflow ou de vários?
Um único ficheiro de workflow com estratégia de matriz trata de todos os pacotes. Cada entrada da matriz é executada com um working-directory diferente, limitando a CLI à configuração desse pacote.
Os pacotes podem partilhar um glossário, mas ter idiomas diferentes?
Sim. Aponte ambos os pacotes para o mesmo engineId, mas configure locale.targets diferentes em cada i18n.json. O glossário do motor aplica-se aos pares de idiomas solicitados.
