Skip to content

Internationalisation

Wouter Meetsma edited this page May 31, 2026 · 4 revisions

Internationalisation

Rubric Maker uses i18next and react-i18next for UI translations. The active language is auto-detected from the browser and can be changed in the application's Settings page.


Supported languages

Language File Status
English src/locales/en.json Complete
Dutch src/locales/nl.json Complete
French src/locales/fr.json Complete
German src/locales/de.json Complete

Adding a new language

  1. Copy the English locale file:

    cp src/locales/en.json src/locales/<lang-code>.json
    # e.g. cp src/locales/en.json src/locales/de.json
  2. Translate the values in the new file. Keys must stay identical to en.json; only the values change.

  3. Register the locale in src/i18n.ts. Import the new JSON file and add it to the resources object:

    import de from './locales/de.json';
    
    i18next.init({
      resources: {
        en: { translation: en },
        nl: { translation: nl },
        de: { translation: de },   // add this line
      },
      // ...
    });
  4. Add the language to the Settings UI so users can select it. Look for the language selector in src/pages/SettingsPage.tsx.

  5. Test by switching the language in Settings and verifying all pages render correctly without missing keys.


Using translations in components

import { useTranslation } from 'react-i18next';

function MyComponent() {
  const { t } = useTranslation();

  return <h1>{t('myComponent.title')}</h1>;
}

Add the corresponding key to both en.json and nl.json (and any other locale files) at the same time as writing the component, so keys never go missing.


Nested keys

The locale files use nested JSON objects to group related strings:

{
  "rubricBuilder": {
    "title": "Rubric Builder",
    "addCriterion": "Add criterion",
    "scoringMode": {
      "totalPoints": "Total Points",
      "weighted": "Weighted Score"
    }
  }
}

Access nested keys with dot notation: t('rubricBuilder.scoringMode.totalPoints').


Missing keys

If a translation key is missing in a locale file, i18next falls back to the en locale. Missing keys in the en locale are returned as the key string itself. Check the browser console for i18next::translator: missingKey warnings during development.


Date and number formatting

i18next does not handle date/number formatting directly. Use the browser's built-in Intl API:

const formatted = new Intl.NumberFormat(i18n.language).format(score);
const date = new Intl.DateTimeFormat(i18n.language).format(new Date());

Clone this wiki locally