HitKeep Dashboard Localization and Translation Guide
Deze inhoud is nog niet vertaald.
The HitKeep dashboard is fully translated into English, German, Spanish, French, Italian, Dutch, and Portuguese out of the box. No plugins are required. The selected language is stored in the database and follows the user across sessions and devices.
If you use an AI assistant for dashboard copy work, install the HitKeep Agent Skills and invoke hitkeep-i18n. That public skill points the assistant at the current locale files, Transloco patterns, PrimeNG locale sync, and checks.
Related implementation details live in the main repository under frontend/dashboard/public/i18n/ and frontend/dashboard/src/app/core/i18n/. For product behavior, see Facts and Limits and Teams and Data Isolation.
Supported Languages
Section titled “Supported Languages”| Language | Code | Translation file |
|---|---|---|
| English | en |
frontend/dashboard/public/i18n/en.json |
| German | de |
frontend/dashboard/public/i18n/de.json |
| Spanish | es |
frontend/dashboard/public/i18n/es.json |
| French | fr |
frontend/dashboard/public/i18n/fr.json |
| Italian | it |
frontend/dashboard/public/i18n/it.json |
| Dutch | nl |
frontend/dashboard/public/i18n/nl.json |
| Portuguese | pt |
frontend/dashboard/public/i18n/pt.json |
How Language Selection Works
Section titled “How Language Selection Works”Users change the interface language in Settings → Preferences. The selected locale is saved to user_preferences.default_locale in the database — it is not a browser-only cookie, so the choice persists when the user logs in from a different device.
Switching language is instant: the dashboard re-renders without a page reload, powered by Transloco.
Numbers and dates automatically reformat to match the locale (e.g. 1.234,56 in German, 1,234.56 in English) via @jsverse/transloco-locale.
Translation File Format
Section titled “Translation File Format”Each locale is a single JSON file with nested keys. en.json is the reference — all other files must contain the same key structure with translated values.
{ "nav": { "dashboard": "Dashboard", "utm": "UTM", "utmBuilder": "UTM Builder" }, "common": { "actions": { "save": "Save", "cancel": "Cancel", "clearAll": "Clear all" } }, "dashboard": { "title": "Dashboard", "noData": "No data for this period." }}The top-level namespaces map to feature areas:
| Namespace | Contents |
|---|---|
admin |
Admin panel: users, sites, IP exclusions |
common |
Shared buttons, column headers, empty states, filters |
dashboard |
Dashboard page and chart labels |
funnels |
Funnel analytics |
goals |
Goal tracking |
integration |
API clients and API reference pages |
login |
Login and setup screens |
nav |
Sidebar navigation labels and ARIA strings |
preferences |
Language and theme settings |
settings |
Profile, security (2FA, passkeys), email reports |
share |
Public shared dashboard |
sites |
Site management |
utm |
UTM analytics page |
utmBuilder |
UTM link builder tool |
Interpolation
Section titled “Interpolation”Some strings contain runtime variables wrapped in {{ }}. Leave the variable names exactly as-is — translate only the surrounding text.
// ✅ Correct"filters": { "referrer": "Referred by {{ value }}"}
// ❌ Wrong — variable name changed"filters": { "referrer": "Verwiesen von {{ wert }}"}Pluralisation
Section titled “Pluralisation”Transloco uses ICU-style plural rules for strings that differ by count. When present, they look like:
"itemCount": "{ count, plural, =0 {No items} =1 {One item} other {# items} }"Translate the label text inside each plural branch; keep the count, plural, branch keys, and # placeholder unchanged.
Contributing a Translation
Section titled “Contributing a Translation”Adding a New Language
Section titled “Adding a New Language”1. Fork and clone the repository.
git clone https://github.com/pascalebeier/hitkeep.gitcd hitkeep2. Copy the English reference file.
cp frontend/dashboard/public/i18n/en.json \ frontend/dashboard/public/i18n/{lang}.jsonReplace {lang} with a BCP 47 base tag, for example sv for Swedish or ja for Japanese.
3. Translate all values.
Open {lang}.json in your editor and translate every string value. Keep all keys unchanged.
"save": "Save"
// sv.json"save": "Spara"4. Register the language in app.config.ts.
Add the new code to both availableLangs and langToLocaleMapping:
provideTransloco({ config: { availableLangs: ['en', 'de', 'es', 'fr', 'it', 'nl', 'pt', 'sv'], // add 'sv' defaultLang: 'en', // ... },}),provideTranslocoLocale({ langToLocaleMapping: { // existing entries … sv: 'sv-SE', 'sv-SE': 'sv-SE', }}),A locale string maps to a standard IETF locale used by Intl APIs to format numbers and dates correctly.
5. Test locally.
cd frontend/dashboardnpm installnpm startOpen the dashboard, navigate to Settings → Preferences, and switch to your new language. Verify labels, number formats, and date formats all look correct.
6. Submit a pull request.
Include both the new {lang}.json file and the app.config.ts change in your PR. The title should follow Conventional Commits:
feat(i18n): add Swedish (sv) translationFixing an Existing Translation
Section titled “Fixing an Existing Translation”Found a mistranslation or an untranslated key?
- Locate the key in
en.jsonto confirm the English source. - Edit the same key in the target locale file.
- Submit a PR with title
fix(i18n): correct <lang> translation for <key>.
You do not need to rebuild anything — translation files are loaded at runtime as static JSON.
Keeping Translations in Sync
Section titled “Keeping Translations in Sync”When a new HitKeep feature ships, new keys are added to en.json first. Existing locale files become incomplete until a contributor translates the additions.
To check required locale content, run:
cd frontend/dashboardnpm run i18n:checkIf locale shape drift is suspected, run the sync script and review the resulting diff before keeping it:
cd frontend/dashboardnode scripts/sync-i18n-locales.mjsTech Stack
Section titled “Tech Stack”| Layer | Library | Role |
|---|---|---|
| Translation strings | Transloco | Load JSON files, switch language at runtime |
| Number & date formatting | @jsverse/transloco-locale | Localises Intl.NumberFormat / Intl.DateTimeFormat to the active lang |
| Persistence | user_preferences.default_locale in DuckDB |
Stores the user’s choice server-side across sessions |