Un Tolgee auto-hébergé donne aux traducteurs un éditeur web complet, sur votre propre machine, sans confier vos libellés à un service tiers. Il se déploie en deux conteneurs avec Docker Compose. Pour qu’il reste un outil et ne devienne pas une dépendance, les fichiers de traduction du dépôt doivent rester la source de vérité : Tolgee est alimenté à la main, jamais lu par l’application ni par la CI.
Qu’est-ce que Tolgee ?
Tolgee est une plateforme de gestion des traductions (TMS, Translation Management System) open source. Elle organise les libellés d’une application en clés et en langues, affiche l’état « traduit / à traduire », propose une traduction automatique (DeepL, entre autres) et expose une API et une interface en ligne de commande pour échanger des fichiers avec un dépôt de code. Une personne qui ne développe pas peut ainsi proposer et corriger des traductions sans ouvrir un fichier JSON.
Pourquoi auto-héberger Tolgee plutôt qu’utiliser un TMS en ligne ?
L’auto-hébergement garde les libellés et leur historique sur votre infrastructure. Pour un socle multi-tenant qui tient ses données chez lui, c’est l’argument structurant : l’ADR du kit, après un essai de Crowdin sur le même catalogue, constate un import et un contexte équivalents des deux côtés, et retient la souveraineté des libellés comme seule différence décisive.
Le coût est connu d’avance : un service de plus à faire tourner. Il se limite ici à un poste de travail, car Tolgee n’est pas déployé avec l’application.
Comment déployer Tolgee avec Docker Compose ?
Il suffit d’un fichier Compose dédié, séparé de celui de l’application, avec sa propre base PostgreSQL. L’extrait ci-dessous reprend la structure du fichier livré avec le kit ; les identifiants locaux, écrits en clair dans le dépôt pour un usage sur poste, sont remplacés ici par des variables.
name: saas-core-tolgee
services:
tolgee-postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: tolgee
POSTGRES_PASSWORD: ${TOLGEE_DB_PASSWORD}
POSTGRES_DB: tolgee
volumes:
- tolgee_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U tolgee -d tolgee"]
interval: 5s
timeout: 3s
retries: 10
tolgee:
image: tolgee/tolgee:v3.230.0
depends_on:
tolgee-postgres:
condition: service_healthy
environment:
TOLGEE_POSTGRES_AUTOSTART_ENABLED: "false"
SPRING_DATASOURCE_URL: jdbc:postgresql://tolgee-postgres:5432/tolgee
SPRING_DATASOURCE_USERNAME: tolgee
SPRING_DATASOURCE_PASSWORD: ${TOLGEE_DB_PASSWORD}
TOLGEE_FRONTEND_URL: http://localhost:8087
TOLGEE_MACHINE_TRANSLATION_DEEPL_AUTH_KEY: ${DEEPL_AUTH_KEY:-}
ports:
- "127.0.0.1:8087:8080"
volumes:
- tolgee_data:/data
volumes:
tolgee_pgdata:
tolgee_data:
Quatre choix méritent d’être repris tels quels :
- un projet Compose distinct (
name:), pour démarrer et arrêter Tolgee sans toucher à la pile applicative ; - le PostgreSQL embarqué de Tolgee désactivé (
TOLGEE_POSTGRES_AUTOSTART_ENABLED: "false") au profit d’une base externe, sans port publié sur l’hôte, qui n’est jamais la base des tenants ; - une image épinglée sur une version précise, jamais
latest; - l’interface web publiée sur la seule boucle locale du poste, et une clé DeepL lue depuis un
.envnon suivi : absente, la ligne est inerte.
Le démarrage tient en une commande :
docker compose -f docker-compose.tolgee.yml up -d
Un envoi massif de clés, d’étiquettes et de captures déclenche la limite de débit par IP de Tolgee (HTTP 429). Le fichier du kit la laisse active par défaut et documente comment la lever le temps d’une synchronisation, puis la rétablir.
Faut-il activer l’édition en contexte ?
L’édition en contexte de Tolgee permet de cliquer sur un texte de l’application en cours d’exécution pour le traduire sur place. Elle suppose d’intégrer le SDK Tolgee dans le front. C’est confortable pendant le développement, mais cela fait entrer Tolgee dans le code livré.
Le kit a fait le choix inverse : aucun SDK Tolgee dans l’application, et un contexte généré depuis le code source puis poussé dans les champs natifs de Tolgee (description de clé, étiquettes, captures d’écran). L’ADR correspondant garde une porte ouverte : un SDK limité au mode développement, retiré du build de production, si des non-développeurs en ont un jour besoin.
Pourquoi le dépôt doit-il rester la source de vérité ?
Parce qu’un outil d’atelier ne doit jamais pouvoir arrêter le produit. Si l’application lisait ses traductions dans Tolgee, sa panne ou son remplacement toucheraient le service en production. Avec des fichiers JSON embarqués dans le build, Tolgee éteint ne change rien à l’exécution : seule l’édition est suspendue.
Ce modèle a un nom dans la documentation du kit, le « modèle A » : les traductions sont livrées avec le code. Une correction de libellé suit le même chemin qu’une correction de code (commit, CI, nouvelle version), et git trace chaque libellé publié. L’alternative, charger les traductions à chaud depuis un CDN ou une table en base, est documentée comme porte de sortie si le rythme des corrections le rendait nécessaire.
Le pont entre les deux mondes est un fichier .tolgeerc.json et deux gestes manuels :
{
"$schema": "https://tolgee.io/tolgeerc-schema.json",
"apiUrl": "http://localhost:8087",
"projectId": 2,
"format": "JSON_ICU",
"push": {
"files": [
{ "path": "packages/i18n/src/locales/en.json", "language": "en" },
{ "path": "packages/i18n/src/locales/fr.json", "language": "fr" }
],
"forceMode": "KEEP"
},
"pull": { "path": "packages/i18n/src/locales" }
}
pnpm i18n:pushenvoie le dépôt vers Tolgee.forceMode: "KEEP"n’écrase jamais une traduction déjà faite dans l’outil.pnpm i18n:pullrapatrie les traductions dans les JSON. Le résultat passe ensuite par une revue git et par les tests du catalogue, comme n’importe quel changement.
Le format JSON_ICU conserve la syntaxe ICU des messages, pluriels compris. La clé d’API Tolgee vit dans la variable TOLGEE_API_KEY, jamais dans le dépôt.
Comment donner du contexte aux traducteurs ?
Un traducteur qui voit une clé et une valeur sans savoir où elles s’affichent traduit à l’aveugle. Le kit fournit quatre niveaux de contexte, tous lancés hors bande :
| Niveau | Commande | Ce que voit le traducteur |
|---|---|---|
| Description déterministe | pnpm i18n:context | l’écran et le type d’élément déduits des appels t("clé") |
| Note rédigée | collect-context.mjs puis push-notes.mjs | une phrase sur le rôle du libellé et ses contraintes |
| Étiquettes | pnpm i18n:tags | domain:<namespace> pour filtrer par domaine, inherited:<locale> pour les clés volontairement identiques à l’anglais |
| Captures d’écran | pnpm i18n:screenshots:upload | l’écran réel, lié à chaque clé qui y apparaît |
pnpm i18n:sync enchaîne l’envoi, les étiquettes, les captures et leurs liaisons. Comme forceMode: "KEEP" ne supprime jamais rien, pnpm i18n:reconcile liste les dérives (clés présentes dans Tolgee mais absentes du code, traductions posées sur des clés héritées, étiquettes périmées) et ne les corrige qu’avec --apply.
Comment ajouter une langue ?
Ajouter une langue est un événement de code, suivi d’un déploiement :
pnpm i18n:add-locale es "Español" --dry-run
pnpm i18n:add-locale es "Español"
La commande crée le fichier JSON de la langue, vide au départ, donc entièrement hérité de l’anglais, et l’enregistre dans le registre des locales. Si TOLGEE_API_KEY est présente, elle crée aussi la langue dans le projet Tolgee ; --no-tolgee s’en abstient. On traduit ensuite dans Tolgee, puis pnpm i18n:pull remplit le fichier.
Comment saas-core l’intègre
docker-compose.tolgee.yml: projetsaas-core-tolgee, base PostgreSQL dédiée sans port hôte, PostgreSQL embarqué désactivé, image épinglée, interface sur le port local 8087, DeepL optionnel..tolgeerc.json: formatJSON_ICU,forceMode: "KEEP", fichiersen.jsonetfr.json.package.json:i18n:pusheti18n:pullpassent par le CLI Tolgee appelé vianpx, sans dépendance ajoutée à l’arbre ; les autres scriptsi18n:*pointent versscripts/i18n/.scripts/i18n/README.md: le flux complet, la cadence (« rien de tout ceci n’est dans la CI, le build ou le déploiement ») et la convention d’étiquettes.packages/i18n/src/index.ts: les catalogues sont importés statiquement, donc embarqués dans le build.packages/i18n/test/i18n.spec.ts: refuse une clé orpheline et une surcharge identique à la source, ce qui filtre unpullmal maîtrisé.- L’ADR
0026-tolgee-auto-hebergeet l’ADR0027-i18n-modele-a-et-contexte-autodanssaas-core-doc/decisionsconsignent le choix et ses conditions de réévaluation.
Une limite assumée : l’instance est mono-utilisateur et sa base n’est pas sauvegardée. Une traduction faite dans Tolgee et jamais rapatriée par pnpm i18n:pull peut se perdre. Une instance partagée entre plusieurs traducteurs exigerait une authentification sérieuse et une sauvegarde.
Les messages que Tolgee manipule sont au format ICU ; leur syntaxe (pluriels, arguments, dates) est détaillée dans ICU MessageFormat et pluriels dans un SaaS. Pour voir pourquoi aucun outil d’atelier n’apparaît dans la chaîne de livraison, consultez le pipeline CI/CD GitHub Actions du kit.
Le fichier Compose de Tolgee, la configuration du CLI et les scripts d’outillage i18n font partie du kit ; le détail de ce qui est inclus figure sur la page tarifs.