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

# Internationalization

> Request translated response bodies with the x-language header

The Nudj APIs localise user-facing fields (challenge titles, reward descriptions, achievement copy, email templates, etc.) on the way out. Send the `x-language` header to control which language the API returns.

## The `x-language` header

```http theme={null}
x-language: en
```

* Header name is case-insensitive. `x-lang` is accepted as a shortcut.
* Value is a two-letter language code (`en`, `fr`, `de`, `es`, `ja`, `zh`, …) — the exact set supported by your organisation depends on the languages configured on your communities.
* If the header is missing, the API falls back to the organisation's default language.
* If the value is an unsupported language, the API falls back to the organisation's default language (no error).

## Which endpoints support it?

Both the Integration and Admin APIs respect `x-language` on every endpoint that returns translatable content — challenges, actions, rewards, achievements, emails, leaderboard configs, community rules, variable labels, and any custom copy written through the admin dashboard.

The Analytics API returns raw metrics and is not affected by `x-language`.

## Sending the header

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://{subdomain}.nudj.cx/api/v2/integration/challenges" \
    -H "Authorization: Bearer $NUDJ_API_TOKEN" \
    -H "x-language: fr"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    `https://${DOMAIN}/api/v2/integration/challenges`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.NUDJ_API_TOKEN}`,
        'x-language': userLanguage, // e.g. 'fr' from your user context
        'Content-Type': 'application/json',
      },
    }
  );
  ```

  ```python Python theme={null}
  import os, requests

  response = requests.get(
      f"https://{DOMAIN}/api/v2/integration/challenges",
      headers={
          "Authorization": f"Bearer {os.environ['NUDJ_API_TOKEN']}",
          "x-language": user_language,
      },
  )
  ```
</CodeGroup>

## Response shape

Translatable fields come back pre-resolved — a single string in the requested language — rather than a map of `{ en: …, fr: … }`. Your client doesn't need to do any client-side locale matching:

```json theme={null}
{
  "id": "…",
  "title": "Défi de la semaine",
  "description": "Complétez 3 actions pour gagner 100 XP"
}
```

If a specific field has no translation for the requested language, it falls back to the community's default language for that field, then to the organisation's default language.

## Best practices

1. **Send `x-language` from your user context.** In a widget or integration that has a user's locale preference, pass it through on every request — the API handles the fallback chain for you.
2. **Don't pin every request to the organisation default.** If you omit the header, you always get the org default. That's fine for backend-only jobs (e.g. generating a CSV export), but for user-facing flows, send the user's actual locale.
3. **Cache per-language.** If you cache API responses on your side, make `x-language` part of the cache key — the same endpoint will return different payloads for different languages.

## Managing translations

Translations themselves are managed in the admin dashboard. See [Questions & Variables](/admin-guide/settings/questions-variables) for the template system used across emails and community copy.

## Related

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Full auth header matrix (includes every supported request header).
  </Card>

  <Card title="Pagination" icon="list-ol" href="/api-reference/pagination">
    The `limit`/`skip` contract on list endpoints.
  </Card>
</CardGroup>
