A small TanStack Start app that demonstrates Tolgee i18n with English + German.
Branch workflow:
main(dev) andstaginguse two separate Tolgee projects. Managers edit copy onstaging; developers ship code onmain. Seedocs/WORKFLOW.mdfor the full guide.
docker compose up -d # http://localhost:8200
docker exec tolgee cat /data/initial.pwd # initial admin passwordLog in at http://localhost:8200 as admin, set a new password.
- Projects → Add a project — name
tolgee-poc, base language English (en). - Languages → Add language —
German(de). - Project settings — copy the Project ID (small integer).
- API keys → Create new — give it
adminscope (or at leasttranslations.*,keys.*,languages.view). Copy thetgpak_….
cd app
npm installEdit app/.tolgeerc.json — set projectId to yours.
Create app/.env:
VITE_APP_TOLGEE_API_URL=http://localhost:8200
VITE_APP_TOLGEE_API_KEY=tgpak_xxxxxxxxxxxxTOLGEE_API_KEY=tgpak_xxxxxxxxxxxx npm run i18n:pushUploads ~47 keys from app/src/i18n/{en,de}/*.json.
Always use the CLI, not the web Import. Tolgee's web import infers language from the filename, but our JSONs use folder-per-language (
en/dashboard.json) — the CLI takes language from.tolgeerc.jsonand avoids that ambiguity.
npm run dev # http://localhost:3000Log in with anything. Switch EN ↔ DE in the header. Hold Alt and click any text to edit translations in place — changes save to the Tolgee server.
| Task | Command |
|---|---|
| Push local JSON → Tolgee | TOLGEE_API_KEY= npm run i18n:push |
| Pull Tolgee → local JSON | TOLGEE_API_KEY= npm run i18n:pull |
| Run app | npm run dev |
Set TOLGEE_API_KEY in your shell profile to skip the prefix.
app/src/i18n/
├── en/{app,nav,header,language,common,login,dashboard,users}.json
└── de/(same)
Each file owns one top-level namespace, e.g. dashboard.json:
{ "dashboard": { "title": "...", "card": { "users": "..." } } }The Vite loader in app/src/lib/tolgee.ts discovers files via import.meta.glob, so adding a new namespace is just two new JSON files (one per language) — no registry changes.
import { useTranslate } from "@tolgee/react";
const { t } = useTranslate();
return <h1>{t("dashboard.title")}</h1>;Every user-facing string must come from t() — see .claude/rules/layout-styling.md.
- Create
app/src/i18n/en/<name>.jsonandapp/src/i18n/de/<name>.json. - Use
t('<name>.someKey')in components. npm run i18n:push.
If app/.env has no VITE_APP_TOLGEE_API_KEY, the app still works — it uses the bundled static JSON. DevTools / in-context editing simply turn off.