> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hr-easy.nlead.ch/llms.txt
> Use this file to discover all available pages before exploring further.

# Languages

> German, French and English — and the difference between UI chrome and authored content.

Swiss HR Easy ships in **German, French and English**. Every user picks their locale;
the default for an installation is set with `NEXT_PUBLIC_DEFAULT_LOCALE`.

There are two distinct kinds of translatable text, and they work differently.

## 1. UI chrome

Buttons, table headers, validation messages, menu labels — everything the product
itself says. These live in message files (`src/messages/de.json`, `fr.json`, `en.json`)
and are shipped with the product. Users do not edit them.

All three files carry the **same key tree**, enforced in CI. A key present in German
but missing in French is a runtime error for French users, so it fails the build
rather than reaching production.

## 2. Authored content

Anything a *person* reads that your organization wrote. This is edited in the product,
per locale, by HR:

<Columns cols={2}>
  <Card title="E-mail templates" icon="envelope">
    Pipeline stage mails, onboarding invitations, probation questionnaires, payslip dispatch.
  </Card>

  <Card title="Job ads" icon="briefcase">
    The public posting per locale, plus the SECO Job-Room submission.
  </Card>

  <Card title="Portal messages" icon="message">
    Notifications and instructions shown to applicants and employees.
  </Card>

  <Card title="Pipeline stage instructions" icon="list-check">
    What the stage asks the applicant or the hiring team to do.
  </Card>

  <Card title="Offer letters and contracts" icon="file-signature">
    Generated documents and their templates.
  </Card>

  <Card title="Survey and feedback questions" icon="clipboard-question">
    Question text and scale labels.
  </Card>
</Columns>

Authored content is stored in per-locale fields — `field`, `fieldEn`, `fieldFr` — so a
record carries all three versions at once. Each of these surfaces ships with a shared
**Translate** action that drafts the other locales from the one you wrote, which you
then review and edit before it goes out.

<Warning>
  A single-locale communication surface is not acceptable. If a new feature sends an applicant or an
  employee something they read, it must be authorable in all three languages.
</Warning>

## Which language a person receives

Outbound communication uses the **recipient's** locale, not the sender's. An HR staffer
working in German who sends a stage e-mail to a French-speaking applicant sends the
French version. Where a dispatch is recorded (probation questionnaires, payslip
mails), the wording actually used is snapshotted on the dispatch row, so the record
shows what the person received rather than what the template says today.

## Formats

Locale affects more than words:

* **Dates** follow the locale convention (`31.12.2026` in de/fr).
* **Currency** is CHF throughout, formatted per locale.
* **Numbers** use the locale's separators — this matters on payroll exports.

## For developers

Use `useTranslations('namespace')` in client components and `getTranslations` in
server components; namespace keys as `module.section.key`. Never hardcode a German,
French or English string in JSX or in a service return value that reaches the UI —
including error messages. The full rule set is in
[Internationalization](/development/i18n).
