Internationalization

Bilingual (German/English) support using i18next + react-i18next. German is the primary language; English is fully supported. All user-facing text must be translatable.

Configuration

ItemPath
i18n setupfrontend/src/i18n.ts
German translationsfrontend/src/locales/de/
English translationsfrontend/src/locales/en/
Shared typeshared/types.tsLocalizedText

LocalizedText Pattern

Database fields storing bilingual text use the LocalizedText type:

// shared/types.ts
type LocalizedText = { de: string; en: string };
LayerPattern
Database (Drizzle)jsonb('name').$type<LocalizedText>().notNull()
Zod validationsanitizedLocalizedText(100) / optionalSanitizedLocalizedText(1000)
Frontend displayResolve by current i18n.language

Never use flat columns (nameDe/nameEn). Always use a single jsonb column typed as LocalizedText.

See Validation Pattern for sanitization helpers, Shared Layer for the type definition.

Translation Files

Namespace-based JSON files in each locale directory. The pre-commit hook enforces parity between de/ and en/ — missing keys in either locale fail the commit.

Changelog Fragments

Bilingual changelogs are required for app-code PRs:

LanguagePath
Germanfrontend/changelog/de/<branch-name>.md
Englishfrontend/changelog/en/<branch-name>.md

Exempt branch prefixes: chore-, docs-, test-, refactor-.

See Git Workflow for changelog enforcement, CI-CD Workflows for the changelog-check job.

Usage in Components

import { useTranslation } from 'react-i18next';
 
function MyComponent() {
  const { t } = useTranslation();
  return <h1>{t('buildings.title')}</h1>;
}

All string literals in components must use t() for translation.

Naming Rules

  • English only in code — All identifiers, DB columns, JSON keys, enum values, API paths must be English
  • Exceptions: Translation fields (nameDe/nameEn only in legacy contexts), i18n display text, German proper nouns in comments/data values

See Coding Guidelines for the full naming convention.