Skip to content

# Internationalization (i18n)

Built-in locale system with English, German, and French translations, localStorage persistence, and easy extensibility.

## Overview

Zenith Dashboard includes a lightweight i18n system built on React Context. It stores the active locale in localStorage (matching the pattern used for theme, density, and layout preferences) and provides a type-safe `useTranslations()` hook for accessing translation strings.

This approach was chosen over URL-based i18n libraries (like next-intl) because the project uses Next.js static export (`output: "export"`), which is incompatible with middleware-based locale routing.

## Architecture

File | Purpose
--- | ---
src/lib/i18n/config.ts | Locale list, default locale, message loader
src/lib/i18n/locale-context.tsx | LocaleProvider, useLocale(), useTranslations() hooks
src/lib/i18n/messages/en.json | English translations (~80 keys)
src/lib/i18n/messages/de.json | German translations
src/lib/i18n/messages/fr.json | French translations

## Using Translations

Import the `useTranslations` hook and call it with a dot-notation key:

    "use client";

    import { useTranslations } from "@dashboardpack/core/lib/i18n/locale-context";
    import type { Metadata } from "next";

    export const metadata: Metadata = {
      title: "Internationalization",
      description:
        "Add locales, translate messages, and use the translation hook.",
    };

    export default function MyComponent() {
      const t = useTranslations();

      return (
        <div>
          <h1>{t("dashboard.title")}</h1>
          <p>{t("dashboard.welcome")}</p>
        </div>
      );
    }

## Translated Areas

The following areas are translated out of the box as examples:

- Sidebar— All navigation group labels and item labels
- Header— Search placeholder, button labels, user menu items, notification text
- Dashboard Home— Welcome message, page title
- Common— Action labels (Save, Cancel, Delete, Edit, Search), filter labels

## Adding a New Locale

To add a new language (e.g., Spanish):

1. Copy `src/lib/i18n/messages/en.json` to `es.json` and translate the values
2. Add the locale to the `locales` array in `src/lib/i18n/config.ts`:

    export const locales = [
      { code: "en", label: "English", flag: "🇺🇸" },
      { code: "de", label: "Deutsch", flag: "🇩🇪" },
      { code: "fr", label: "Français", flag: "🇫🇷" },
      { code: "es", label: "Español", flag: "🇪🇸" },  // Add this
    ] as const;

The locale switcher in Settings and Theme Customizer will automatically show the new option.

## Adding Translation Keys

Add new keys to all JSON message files. Keys use dot-notation organized by feature area:

    // en.json
    {
      "reports": {
        "title": "Reports",
        "export": "Export PDF",
        "noData": "No reports found."
      }
    }

    // de.json
    {
      "reports": {
        "title": "Berichte",
        "export": "PDF exportieren",
        "noData": "Keine Berichte gefunden."
      }
    }

The `useTranslations` hook is type-safe — TypeScript will autocomplete valid keys and warn about missing ones thanks to the `NestedKeyOf` utility type.

## Locale Switcher

The locale can be switched from two places:

- Settings page— Appearance tab → Language section
- Theme Customizer — Language section (below Direction)

Both use the `useLocale()` hook which provides `locale` (current value) and `setLocale()` (setter that persists to localStorage).

## Next Steps

Learn how to add new pages with translation support, or browse the Components reference.