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

# Localization

> Choosing the language of API responses, and translating the text you supply

Nmbr supports English and French, so admins and employees can each work in the language they prefer, even when those preferences differ within a single employer.

## API response language

A response can contain user-facing text, such as a validation message. Send an `Accept-Language` header to choose its language.

```bash theme={null}
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/employees \
     --header 'Authorization: Bearer <access_token>' \
     --header 'Accept-Language: fr' \
     --header 'content-type: application/json' \
     --data '{ "first_name": "Kendall", "last_name": "Tremblay", "sin": "123456789" }'
```

Nmbr matches the header against the locales it supports and applies the best match. Every response carries a `Content-Language` header telling you which locale was used.

```
Content-Language: fr
```

Supported locales are `en` and `fr`. A request with no `Accept-Language` header, or one naming a locale Nmbr does not support, is answered in English.

The header changes two things: the messages Nmbr generates, and which translation is returned for [translatable attributes](#translatable-attributes).

**Response**

```json theme={null}
{
  "message": "Le numéro d'assurance sociale est correctement formaté, mais n'est pas un NAS valide.",
  "errors": {
    "sin": [
      "Le numéro d'assurance sociale est correctement formaté, mais n'est pas un NAS valide."
    ]
  }
}
```

Field names, object types, warning types, and identifiers are the same in every locale. Only the human-readable message text changes. See [Payroll Data Requirements](/guides/payroll-fundamentals/payroll-data-requirements#handling-validation-failures).

## Translatable attributes

Some values are customer-generated, such as a pay rate's title. These values can carry a translation for each supported locale, and Nmbr returns the one matching the request. `title`, `label`, `name`, and `description` are translatable where an endpoint offers them. Check the API reference for the endpoint you are working with.

Where an attribute is translatable, it appears three times in a response. Taking `title` on a pay rate as the example:

| Field                | Type                   | Writable |
| -------------------- | ---------------------- | -------- |
| `title`              | string                 | Yes      |
| `title_translations` | object keyed by locale | Yes      |
| `title_translated`   | string                 | No       |

`title` is the default, used when no translation matches the requested locale. `title_translations` holds a translation per locale. `title_translated` is resolved for you: Nmbr returns the translation matching the request locale, and falls back to `title` when there is none.

**Request**

```bash theme={null}
curl --request POST \
     --url https://sandbox.nmbr.co/services/payroll/pay_rates \
     --header 'Authorization: Bearer <access_token>' \
     --header 'content-type: application/json' \
     --data '{
        "work_assignment_id": "<work_assignment_id>",
        "title": "Weekend rate",
        "title_translations": {
          "fr": "Taux de fin de semaine"
        }
     }'
```

**Response** with `Accept-Language: fr`

```json theme={null}
{
  "title": "Weekend rate",
  "title_translations": {
    "fr": "Taux de fin de semaine"
  },
  "title_translated": "Taux de fin de semaine"
}
```

The same record requested with `Accept-Language: en`, or with no header, returns `"title_translated": "Weekend rate"`. There is no `en` translation, so `title` is used.

`title` and `title_translations` are independent, so set a translation only for the locales you care about. A locale present in `title_translations` does not have to match `title`, and you do not need an entry for the language `title` happens to be written in. Nmbr never derives one language from another: `title_translated` only ever returns a value you supplied, or `title`.

### Writing translations

Send the `_translations` object with a key for each locale you want to set. You do not have to supply every locale. Any locale you leave out falls back to the base attribute when read.

Nmbr rejects a `_translations` value that is not an object, contains a key that is not a supported locale, or has an empty or non-string value for any locale.

Sending `_translations` replaces the whole set. To remove a locale, send the object again without that locale. To clear every translation, send `null`.

Some translatable attributes are read-only Nmbr reference data rather than text you own. They follow the same three-field shape, and Nmbr supplies the translations.

**Response** from a bank account lookup, with `Accept-Language: fr`

```json theme={null}
{
  "institution_name": "Royal Bank of Canada",
  "institution_name_translations": {
    "en": "Royal Bank of Canada",
    "fr": "Banque Royale du Canada"
  },
  "institution_name_translated": "Banque Royale du Canada"
}
```

## Payee communications

A payee receives communications from Nmbr, such as pay stub emails and year-end forms, and each needs to be in their preferred language. That language comes from a stored setting, `preferred_locale`.

### Locale inheritance

Set `preferred_locale` at the level you want it to apply. Any level you leave unset inherits from the one above it. With nothing set at any level, communications default to English.

| Set it on                 | Applies to                                          | When to set it                                                      |
| ------------------------- | --------------------------------------------------- | ------------------------------------------------------------------- |
| Your partner account      | Everything below, unless overridden                 | A single default language for the whole account                     |
| A company                 | That company, its business entities, and its payees | A company operates in a different language from your default        |
| An employee or contractor | That person                                         | One person needs a different language from their company            |
| A business entity         | That business entity                                | Rarely: payees inherit from the company, not the entity (see below) |

Setting it on a business entity does not change the language for payees working there. Payees inherit from the company, because one person can hold work assignments at more than one business entity.

<Warning>
  A change takes effect immediately for everything below it that has no setting
  of its own, with no confirmation step. Switching your partner account from
  English to French means every company, business entity, and payee relying on
  that default starts receiving communications in French, including employees
  who have been getting English pay stubs until now.
</Warning>

Sending `Accept-Language: fr` does not change what an employee receives in their inbox. Setting `preferred_locale` to `fr` does not change the language of your API responses.
