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

# Les messages traduits

> Répondre à chaque personne dans sa langue avec une déclaration par langue, comprendre quelle langue parle un message, et traduire ce que le bot dit de lui-même

Un bot qui parle plusieurs langues ne met pas un `if` sur la langue dans chaque fichier : il déclare ses textes une fois par langue, et chaque fonction reçoit `t`, qui choisit le bon. Cette page donne deux langues à votre bot, et fait répondre `/ping` avec `t('pong')`.

## Une déclaration par langue

Une langue se déclare avec `language()` : `locale` dit laquelle, `texts` contient les textes du bot par clé. Créez un fichier par langue dans `src/messages/` :

```ts src/messages/en-US.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { language } from 'chapterjs';

export default language({
  locale: 'en-US',
  default: true,
  texts: {
    pong: 'Pong!',
    welcome: 'Welcome {name}, you are member #{count}!',
    next: 'Page {page}',
    members: { one: '{count} member', other: '{count} members' },
  },
});
```

```ts src/messages/fr.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { language } from 'chapterjs';

export default language({
  locale: 'fr',
  texts: {
    pong: 'Pong !',
    welcome: 'Bienvenue {name}, tu es le membre n°{count} !',
    next: 'Page {page}',
    members: { one: '{count} membre', other: '{count} membres' },
  },
});
```

* **`locale` est la langue**, comme l’écrit Discord : `'en-US'`, `'en-GB'`, `'fr'`, `'de'`, `'es-ES'`, `'pt-BR'`, `'ja'`... Un mot que Discord ne connaît pas est souligné, et refusé quand le fichier se charge, avec la liste.
* **`default: true`** marque la langue utilisée quand celle demandée n’est pas là. Exactement un fichier le dit : avec `chapterjs dev` lancé, deux fichiers qui le disent sont soulignés tous les deux dans l’éditeur.
* **Un paramètre** est un nom entre accolades : `{name}`, `{count}`. Il prend un texte ou un nombre, et un nombre est écrit comme la langue écrit les nombres (`1,234` en anglais, `1 234` en français).
* **Un pluriel** a une forme par quantité (`one`, `other`, et `zero`, `two`, `few`, `many` pour les langues qui en ont besoin). `count` choisit la forme selon les règles de la langue.

La langue par défaut a tous les textes, et les autres langues peuvent n’en avoir qu’une partie : ce qui manque vient de la langue par défaut. Un texte qu’une autre langue a mais que la langue par défaut n’a pas, ou un `{name}` devenu `{nom}`, est signalé sur ce fichier, et cette langue est mise de côté jusqu’à ce qu’elle corresponde.

## t : un texte dans la bonne langue

Chaque fonction de votre projet (commandes, événements, boutons, formulaires, tâches) reçoit `t`. Changez l’accueil du chapitre sur les événements pour l’utiliser :

```ts src/events/hello.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { event } from 'chapterjs';

export default event({
  name: 'memberJoin',
  async run({ member, guild, t }) {
    const channel = guild.systemChannelId ? guild.channels.get(guild.systemChannelId) : undefined;
    if (!channel?.isTextBased()) return;
    await channel.send(t('welcome', { name: member.displayName, count: guild.memberCount ?? 1 }));
  },
});
```

Tapez `t('` dans votre éditeur : il propose `pong`, `welcome`, `next`, `members`, les clés de la langue par défaut. Choisissez `welcome`, et le second argument demande `name` et `count` : les paramètres du texte, lus dans le fichier. Oubliez `count`, et la ligne est soulignée. Les types viennent du fichier de langue lui-même, à chaque frappe, sans rien générer à partir de son contenu.

Un pluriel prend son `count` de la même façon :

```ts src/commands/members.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { command } from 'chapterjs';

export default command({
  name: 'members',
  description: 'Compte les membres de ce serveur',
  async run({ interaction, guild, t }) {
    await interaction.reply(t('members', { count: guild.memberCount ?? 0 }));
  },
});
```

## Quelle langue parle t

Voici la partie subtile, et la raison pour laquelle `t` existe plutôt qu’un `if (interaction.locale === 'fr')`. Un message est envoyé **une fois**, et tout le monde dans le salon lit le même texte : Discord ne le traduit pas pour chaque lecteur. Alors `t` parle la langue de **ceux qui liront** ce que vous envoyez, pas de la personne qui a utilisé la commande :

| Ce que vous envoyez | La langue |
| - | - |
| Une réponse que seule la personne voit (`ephemeral: true` sur la commande, le bouton ou le formulaire), ou un formulaire | Celle de la personne |
| Un message privé | Celle de la personne |
| Un message public sur un serveur | Celle du serveur, quand Discord la connaît |
| L’événement `ready`, une tâche | Celle par défaut |

Discord ne connaît la langue que d’un serveur **Communauté** (un réglage du serveur). Ailleurs, il dit `en-US` quelle que soit la langue des membres, donc un message public y utilise votre langue par défaut. Un bot dans une seule langue met cette langue par défaut et n’y pense plus jamais ; un bot dans plusieurs suit les grands serveurs, qui règlent la leur.

`t.locale` dit quelle langue a été prise, et `t.in('fr', 'welcome', { ... })` donne un texte dans une autre langue, pour un message destiné à quelqu’un d’autre. Quand la langue exacte n’est pas dans vos fichiers, `t` prend la plus proche (`en-GB` lit les textes `en-US`), et celle par défaut sinon.

> [!WARNING]
>
> `t` est donné à votre fonction **avant** qu’elle ne tourne, pour le public que déclare le fichier. Une commande qui n’est pas `ephemeral` mais qui répond avec `ephemeral: true` au moment de l’appel garde la langue du serveur dans cette réponse. Quand les réponses d’une commande sont pour la personne, mettez `ephemeral: true` sur la commande : `t` parle alors sa langue, et c’est aussi la valeur par défaut de ses réponses.

## Les textes des boutons, menus et formulaires

Une étiquette s’écrit dans le fichier du composant, où il n’y a pas encore de `t` : le message n’est pas envoyé. Pour la traduire, faites-en une fonction de `t` et des données ; elle tourne au moment de l’envoi du message, pour qui le lira :

```ts src/components/next-page.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { button } from 'chapterjs';

const nextPage = button({
  label: ({ t, data }) => t('next', { page: data.page + 1 }),
  data: { page: 'number' },
  async run({ interaction, data }) {
    await interaction.update({ components: [nextPage({ page: data.page + 1 })] });
  },
});

export default nextPage;
```

Cela fonctionne pour le `label` d’un bouton, le `placeholder` d’un menu et ses options, le `title` d’un formulaire et les textes de ses champs.

## Ce que le bot répond de lui-même

Quand le bot ne peut pas lancer ce qui a été demandé (une commande utilisée au mauvais endroit, un bouton d’un vieux message, un `run` qui a levé une erreur), il répond de lui-même, en anglais. Ces phrases se traduisent dans `framework`, avec les mots pour une commande, un bouton, un menu et un formulaire, que remplace `{what}` :

```ts src/messages/fr.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { language } from 'chapterjs';

export default language({
  locale: 'fr',
  texts: {
    pong: 'Pong !',
    welcome: 'Bienvenue {name}, tu es le membre n°{count} !',
    next: 'Page {page}',
    members: { one: '{count} membre', other: '{count} membres' },
  },
  framework: {
    command: 'commande',
    button: 'bouton',
    guildOnly: "Cette {what} ne s'utilise que sur un serveur.",
    failed: "Quelque chose s'est mal passé avec cette {what}.",
  },
});
```

Une phrase reçoit sa réponse dans la langue de la personne ; une phrase qu’un fichier ne traduit pas reste en anglais. Chaque phrase, avec son texte anglais, est dans la [Référence](https://www.chapterjs.org/fr/reference/messages.md#frameworktexts).

## Les descriptions des commandes

Ce que Discord affiche d’une commande avant qu’elle ne soit utilisée (son nom, sa description, ses options) est enregistré, pas envoyé par le bot, donc cela ne peut pas passer par `t`. C’est la seule chose traduite par des données. Une commande peut laisser `description` hors de son fichier et l’avoir dans les fichiers de langue à la place, par le nom de la commande :

```ts src/messages/en-US.ts theme={"theme":{"light":"github-light","dark":"vesper"}}
import { language } from 'chapterjs';

export default language({
  locale: 'en-US',
  default: true,
  texts: {
    pong: 'Pong!',
    welcome: 'Welcome {name}, you are member #{count}!',
    next: 'Page {page}',
    members: { one: '{count} member', other: '{count} members' },
  },
  commands: {
    dice: {
      description: 'Rolls a die',
      options: { sides: { description: 'How many sides' } },
    },
  },
});
```

La langue par défaut donne la description que tout le monde voit ; les autres langues donnent leurs traductions (`name` aussi, quand la commande doit avoir un autre nom dans cette langue). Une commande a ses textes à un seul endroit : avec `description` dans son fichier, un fichier de langue qui la mentionne est une erreur ; sans elle, le fichier ne doit pas avoir de `locales`. Déplacez-y aussi la description de `/ping`, et retirez-la de son fichier : les modèles `tickets`, `music`, `community` et `moderation` le font pour chaque commande.

## Points d’attention

* **Les clés sont typées d’après le fichier par défaut.** Ajoutez un texte là d’abord, puis dans les autres ; l’éditeur et le chargeur le vérifient tous les deux.
* **Les accolades écrites telles quelles sont doublées** : `'{{name}}'` affiche `{name}`.
* **La langue d’un serveur est `en-US` sauf si c’est un serveur Communauté.** Ne soyez pas surpris qu’un message public sur un serveur français sorte dans la langue par défaut.
* **Sans langue, il n’y a pas de `t`** : il n’existe ni dans les types ni à l’exécution. Passez-vous des fichiers de langue si votre bot parle une seule langue et que vous préférez des textes simples.

## Récapitulatif

* `language({ locale, texts })` contient les textes d’une langue par clé ; l’une d’elles est `default: true`.
* `t('clé', { paramètres })` donne le texte dans la langue de qui le lira ; l’éditeur vérifie les clés et les paramètres.
* L’étiquette d’un composant est une fonction de `t` ; les phrases du bot vont dans `framework` ; les descriptions des commandes dans `commands`.

> [card] [Organiser un projet qui grandit](https://www.chapterjs.org/fr/tutorial/organising.md)
>
> Partager du code, stocker des données, et garder les fichiers courts.

> [card] [Guide : Messages traduits](https://www.chapterjs.org/fr/translated-messages.md)
>
> La même chose, en bref.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.