
Ce guide s'appuie sur le [guide souris](./06-mouse.md). Le [guide de préparation](./00-setup.md) a déjà installé le fichier CSV, et on a déclaré les constantes `TEXT_*` dès le [guide composition](./02-composition.md). Ici, on explique comment le code lit ce CSV, on ajoute un helper pour garder les appels courts, et on remplace notre dernière chaîne en dur.

## Principe

Tout texte visible par le joueur doit venir d'un fichier CSV -- ne jamais coder de chaînes en dur dans Ruby. Le système i18n de PSDK choisit la colonne correspondant à la langue courante du jeu :

- Chaque fichier CSV a un identifiant numérique unique (`TEXT_FILE_ID`).
- Chaque ligne correspond à un index : la première ligne de données est l'ID 0, la suivante l'ID 1, etc.
- Les cellules vides retombent sur la valeur anglaise (`en`), donc une traduction incomplète affiche quand même l'anglais.
- On lit une ligne avec `ext_text(file_id, index_ligne)`.

## Le CSV et ses constantes

Le CSV vit dans `Data/Text/Dialogs/311125.csv` (installé dans le guide de préparation). Son nom de fichier correspond à `TEXT_FILE_ID = 311_125`. Chaque ligne correspond à une constante `TEXT_*` de `001 Constants.rb` :

| Constante              | Ligne | Texte anglais          |
| ---------------------- | ----- | ---------------------- |
| `TEXT_ENTER_CODE`      | 0     | Enter Code             |
| `TEXT_QUIT`            | 1     | Quit                   |
| `TEXT_TITLE`           | 2     | Mystery Gift           |
| `TEXT_PROMPT`          | 3     | Enter your gift code   |
| `TEXT_INVALID`         | 4     | Invalid code!          |
| `TEXT_ALREADY_CLAIMED` | 5     | Gift already claimed!  |
| `TEXT_RECEIVED`        | 6     | You received %s!       |
| `TEXT_NO_GIFTS`        | 7     | No gifts claimed yet   |
| `TEXT_CONFIRM`         | 8     | Claim this gift?       |
| `TEXT_GIFT_RECEIVED`   | 9     | Gift received!         |
| `TEXT_YES`             | 10    | Yes                    |
| `TEXT_NO`              | 11    | No                     |

On en utilise déjà deux : la Composition lit `ext_text(TEXT_FILE_ID, TEXT_TITLE)` pour le titre et `TEXT_NO_GIFTS` pour le message vide. Le reste est utilisé au fil de la construction des dialogues.

## Un helper pour raccourcir les appels

Écrire `ext_text(TEXT_FILE_ID, id)` partout est verbeux. Ajoutez un helper privé à la scène. Modifiez `scripts/20 MysteryGift/003 GamePlay/001 Main.rb` -- ajoutez cette méthode (le `include UI::MysteryGift` en haut de la classe rend les constantes `TEXT_*` disponibles) :

```ruby
# Shortcut to access Mystery Gift text
# @param id [Integer] the text row index
# @return [String]
def gift_text(id)
  return ext_text(TEXT_FILE_ID, id)
end
```

- `gift_text(TEXT_QUIT)` est bien plus clair que `ext_text(311_125, 1)`.
- Elle renvoie le texte déjà dans la langue courante du jeu.

La Composition est dans le module `UI::MysteryGift` et appelle `ext_text` directement ; la scène utilise ce raccourci `gift_text`. Les deux atteignent le même CSV.

## Localiser les boutons

Dans le guide de la scène, on avait codé `'Quit'` en dur dans `button_texts`. Remplacez-le par la valeur du CSV. Modifiez `button_texts` dans `001 Main.rb` :

```ruby
# Return the button texts for the ctrl buttons [A, X, Y, B]
# @return [Array<String, nil>]
def button_texts
  return [nil, nil, nil, gift_text(TEXT_QUIT)]
end
```

- Le bouton B lit maintenant son libellé depuis le CSV : « Quit » en anglais, « Quitter » en français.
- Le bouton A reste caché (`nil`) pour l'instant. On le révèle -- avec son libellé `gift_text(TEXT_ENTER_CODE)` -- dans le [guide dialogues](./08-dialogs.md), en même temps que l'`action_a` qu'il déclenche. (Un bouton ctrl visible appelle son action au clic, donc il ne doit pas apparaître avant que son action existe.)

## Couleurs de texte

PSDK utilise une palette de couleurs indexées :

```ruby
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 0)   # black
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 1)   # blue
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 2)   # red
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 3)   # green
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 9)   # grey
add_text(0, 0, 200, 18, gift_text(TEXT_TITLE), color: 10)  # white
```

- Le paramètre `color:` est un index dans la palette de police. Les plus courants : 0 noir, 1 bleu, 2 rouge, 3 vert, 9 gris, 10 blanc.

Pour une couleur RGB exacte absente de la palette, omettez `color:` et assignez `fill_color`/`outline_color` directement :

```ruby
title = add_text(0, 0, 200, 18, gift_text(TEXT_TITLE))
title.fill_color = Color.new(0, 255, 136)
title.outline_color = Color.new(0, 85, 45)
```

- Une astuce courante pour le contour est de diviser chaque canal du remplissage par 3 : un remplissage `(0, 255, 136)` s'accompagne d'un contour `(0, 85, 45)`.

## Texte dynamique avec format

Quand une ligne contient un spécificateur de format (`%s` pour une chaîne, `%d` pour un entier), `format` de Ruby le remplit :

```ruby
# "You received Rare Candy!" / "Vous avez recu Rare Candy !"
message = format(gift_text(TEXT_RECEIVED), gift_name)
```

- `gift_text(TEXT_RECEIVED)` renvoie « You received %s! » ; `format(template, gift_name)` remplace `%s`. On l'utilise dans le guide dialogues pour annoncer le cadeau réclamé.
- Le nom du cadeau vient de la base de données, qui n'est pas traduite ici.

## Essayez

Passez le jeu en français (ou regardez le bouton B) : le bouton du bas affiche maintenant « Quitter » au lieu d'un « Quit » codé en dur, et le titre reste localisé.

## Conclusion

- Tout texte visible par le joueur passe par un CSV identifié par `TEXT_FILE_ID` ; lisez-le avec `ext_text(file_id, index_ligne)`.
- Les constantes `TEXT_*` (déclarées dans `001 Constants.rb`) nomment les lignes du CSV -- pas de nombres magiques.
- Ajoutez un helper `gift_text` dans la scène pour raccourcir les appels `ext_text` ; la Composition utilise `ext_text` directement.
- Ne codez jamais de chaînes destinées au joueur en dur -- on a remplacé la dernière (`'Quit'`).
- Utilisez `color:` indexé pour les couleurs de palette, ou `fill_color`/`outline_color` pour du RGB exact.
- Utilisez `format` avec `%s`/`%d` pour du texte paramétré.
