Le CLI prend en charge les monorepos nativement. Utilisez un seul i18n.json à la racine avec un glob récursif ** pour détecter automatiquement les packages, une configuration racine unique avec des chemins explicites pour chaque package, ou des fichiers i18n.json distincts dans chaque package, combinés à une GitHub Action avec stratégie de matrice.
Quand utiliser chaque approche#
| Cas d’usage | Approche | Fichiers de configuration | GitHub Action |
|---|---|---|---|
| Tous les packages partagent la même structure et les mêmes langues, et vous voulez que les nouveaux packages soient détectés automatiquement | Configuration unique récursive | Un i18n.json à la racine avec un glob ** | Une étape, working-directory par défaut |
| Tous les packages partagent les mêmes langues source et cible | Configuration unique | Un i18n.json à la racine | Une étape, working-directory par défaut |
| Les packages ont besoin de langues cibles différentes | Configurations par package | Un i18n.json par package | Stratégie de matrice avec working-directory |
| Les packages ont besoin de moteurs différents (glossaire, voix de marque) | Configurations par package + moteurs distincts | Un i18n.json par package, chacun avec son propre engineId | Stratégie de matrice avec working-directory |
Approche 1 : configuration unique récursive#
Lorsque tous les packages suivent la même structure (par ex. apps/<name>/locales/[locale].json), utilisez un glob récursif ** dans un unique i18n.json à la racine. Les nouveaux packages sont détectés automatiquement tant qu’ils respectent cette structure :
{
"$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"]
}
}
}Le CLI ignore node_modules, .git, dist, build, .next et .turbo par défaut. Les motifs récursifs ne descendent donc pas dans les arborescences vendorisées ou de build. Ajoutez vos propres entrées exclude pour tout autre élément à exclure.
La GitHub Action est identique à l’approche 2 ci-dessous : une étape, avec le répertoire de travail par défaut.
À utiliser lorsque tous les packages partagent la même langue source, les mêmes langues cibles, la même structure et le même moteur de localisation, et que vous ne voulez pas modifier i18n.json à chaque ajout de package.
Approche 2 : configuration unique, langues partagées#
Un i18n.json à la racine du dépôt. Les chemins de bucket pointent explicitement vers chaque package :
{
"$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 – étape unique standard :
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 }}À utiliser lorsque tous les packages partagent la même langue source, les mêmes langues cibles et le même moteur de localisation, mais que leurs structures diffèrent suffisamment pour qu’un glob récursif soit trop large.
Approche 3 : configurations par package, langues différentes#
Chaque package possède son propre i18n.json avec des langues cibles indépendantes :
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 – stratégie de matrice avec 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 }}Chaque entrée de la matrice exécute le CLI dans le périmètre du i18n.json du package concerné. L’action traduit uniquement les fichiers déclarés par ce package.
Approche 4 : configurations par package, moteurs distincts#
Même structure que l’approche 3, mais chaque package se connecte à un moteur de localisation différent. Chaque package dispose ainsi de son propre glossaire, de sa propre voix de marque et de sa propre configuration de modèle.
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"
}Le YAML de la GitHub Action est identique à celui de l’approche 3 : le engineId dans chaque i18n.json achemine automatiquement les traductions vers le bon moteur.
Fonctionnement du lockfile#
Chaque emplacement de i18n.json génère son propre fichier i18n.lock dans le même répertoire. Le lockfile suit quel contenu source a déjà été traduit, ce qui permet des mises à jour incrémentielles. Dans les approches 1 et 2, il y a un seul lockfile à la racine. Dans les approches 3 et 4, chaque package a son propre lockfile.
FAQ#
Les nouveaux packages sont-ils détectés automatiquement ?
Oui, mais uniquement avec l’approche 1 (** récursif). Avec les approches 3 et 4, vous devez ajouter une nouvelle entrée à la liste matrix.package du workflow lorsque vous ajoutez un package.
Puis-je avoir des langues différentes selon le package ?
Oui. Utilisez l’approche 3 ou 4. Le i18n.json de chaque package déclare son propre tableau locale.targets de manière indépendante.
Faut-il un seul fichier de workflow ou plusieurs ?
Un seul fichier de workflow avec une stratégie de matrice suffit pour tous les packages. Chaque entrée de la matrice s’exécute avec un working-directory différent, ce qui limite le CLI à la configuration du package concerné.
Les packages peuvent-ils partager un glossaire tout en ayant des langues différentes ?
Oui. Pointez les deux packages vers le même engineId, mais configurez des locale.targets différents dans chaque i18n.json. Le glossaire du moteur s’applique à toutes les paires de langues demandées.
