> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/developers-guides/fr/integration-guides/wallet/templating-engine.md).

# Modélisation Liquid

Rendez les champs dynamiques de la Carte, formatez les valeurs et construisez le contenu de la Carte Wallet avec Liquid.

## Gabarit Liquid

Liquid combine du texte fixe avec des valeurs dynamiques provenant d'une Carte. The Wallet Crew utilise l'implémentation DotLiquid, ainsi que des filtres de date personnalisés et la `minify` balise.

Utilisez cette référence après avoir confirmé les chemins de données requis sur une vraie Carte.

<details>

<summary><strong>Exemples concrets</strong></summary>

* Une carte de fidélité affiche un solde de points sûr, entier.
* Une carte-cadeau affiche son identifiant, son montant et sa date d’expiration.
* Un billet d’événement transforme les données de siège en indications pour le lieu.

</details>

### Confirmer les données disponibles

Chaque rendu reçoit un contexte de données. Il peut contenir des données de Carte, des données supplémentaires et des valeurs renvoyées par les fournisseurs connectés.

Inspecter **Voir les données** sur une vraie Carte avant d’écrire un gabarit. Cette charge utile est la source de vérité pour les chemins de variables.

Les données supplémentaires conviennent au contenu visible de la Carte. Les métadonnées prennent en charge les opérations et la segmentation. Elles ne doivent pas être traitées comme une source d’affichage Wallet.

Pour le flux complet de mise à jour et de validation, voir [Mettre à jour les données de la Carte dans les gabarits](/developers-guides/fr/integration-guides/wallet/update-pass-data-in-templates.md).

Les chemins courants incluent :

| Données                | Exemples de chemins                                                       |
| ---------------------- | ------------------------------------------------------------------------- |
| Client                 | `firstName`, `lastName`, `address.city`                                   |
| Carte                  | `serialNumber`, `tenantId`, `publicUrl`, `authenticationToken`            |
| Fidélité               | `loyalty.points`, `pendingLoyaltyPoints`, `loyalty.amounts`               |
| Carte-cadeau           | `voucher.amount`, `voucher.currency`, `id.y2.giftCardId`                  |
| Billet d’événement     | `ticket.name`, `ticket.startDate`, `ticket.seatNumber`, `ticket.entrance` |
| Collections            | `y2.tickets`, `y2.bons.loyaltyCertificates`                               |
| Valeurs personnalisées | `additionalData.<key>`                                                    |

Les valeurs manquantes s’affichent comme une chaîne vide. Utilisez `default` lorsqu’un repli visible est nécessaire.

```liquid
{{ loyalty.points | default: 0 | floor }}
```

### Bases de la syntaxe

Utilisation `{{ ... }}` pour afficher une valeur. Utilisez `{% ... %}` pour la logique qui ne s’affiche pas d’elle-même.

```liquid
Bienvenue {{ firstName | default: "member" }} !
{% if loyalty.points and loyalty.points > 1000 %}membre VIP{% endif %}
{% assign label = ticket.priceCategory | strip %}
```

Les filtres s’exécutent de gauche à droite. La notation pointée suit la structure imbriquée de la charge utile de données.

#### Conditions et boucles

Liquid considère uniquement `nil` et `false` comme faux. Le nombre `0` et la chaîne `"false"` sont considérés comme vrais. Comparez explicitement les nombres facultatifs.

```liquid
{% if pendingLoyaltyPoints and pendingLoyaltyPoints > 0 %}
En attente : {{ pendingLoyaltyPoints }} pts
{% endif %}
```

Protégez les boucles avec une vérification de la taille de la collection. Cela évite les titres de section vides.

```liquid
{% if y2.tickets.size > 0 %}
  {% for ticket in y2.tickets %}
    - #{{ ticket.ticketNumber }} le {{ ticket.startDate | date: "D" }}
  {% endfor %}
{% endif %}
```

Dans une boucle, `forloop.index`, `forloop.first`, `forloop.last`, et `forloop.length` sont disponibles.

#### Affectations, branches et espaces

Utilisation `assign` pour réutiliser les valeurs calculées. Utilisez `case` pour les correspondances code-libellé.

```liquid
{% assign category = ticket.priceCategory | strip %}
{% case category %}
  {% when "F" %}Plein tarif
  {% when "R" %}Réduit
  {% else %}{{ category }}
{% endcase %}
```

Utilisation `{%-` et `-%}` pour supprimer les espaces autour. Cela permet de garder des gabarits multilignes compacts dans des champs Wallet étroits.

```liquid
{%- assign alley = ticket.alley | strip -%}
{%- if alley -%}Allée {{ alley }}{%- endif -%}
```

#### Valeurs YAML

Mettez entre guillemets les valeurs Liquid contenant des caractères spéciaux YAML. Utilisez `|-` pour les valeurs multilignes.

```yaml
alternateText: 'À présenter à la caisse : {{ id.y2.customerId }}'
value: |-
  {% assign name = firstName | append: " " | append: lastName %}
  {{ name }}
```

### Filtres personnalisés

#### Filtres de date

Tous les filtres de date analysent l’entrée comme une valeur de date ou d’heure, appliquent l’opération et renvoient un `DateTimeOffset`. Enchaînez-les avec `| date: "format"` lorsqu’une sortie sous forme de chaîne est nécessaire.

**`add_minutes`**

Ajoute le nombre de minutes spécifié.

```liquid
{{ someDate | add_minutes: 60 }}
{{ someDate | add_minutes: 60 | date: "yyyy-MM-dd HH:mm:ss" }}
```

**`add_hours`**

Ajoute le nombre d’heures spécifié.

```liquid
{{ someDate | add_hours: 24 }}
{{ someDate | add_hours: 24 | date: "yyyy-MM-dd HH:mm:ss" }}
```

**`add_seconds`**

Ajoute le nombre de secondes spécifié.

```liquid
{{ someDate | add_seconds: 3600 }}
{{ someDate | add_seconds: 3600 | date: "yyyy-MM-dd HH:mm:ss" }}
```

**`add_days`**

Ajoute le nombre de jours spécifié.

```liquid
{{ someDate | add_days: 7 }}
{{ someDate | add_days: 7 | date: "yyyy-MM-dd" }}
```

**`add_timespan`**

Ajoute une durée au format `hh:mm:ss` .

```liquid
{{ someDate | add_timespan: "02:30:00" }}
{{ someDate | add_timespan: "02:30:00" | date: "yyyy-MM-dd HH:mm:ss" }}
```

Tous les filtres de date utilisent la culture invariante pour l’analyse et le formatage.

#### Filtre de format

**`format`**

Applique une chaîne de formatage à toute valeur `IFormattable` de type IFormattable, comme les nombres, les dates et les énumérations.

```liquid
{{ loyaltyPoints | format: "N0" }}
```

Cela affiche un entier groupé tel que `1,234` dans la culture invariante.

```liquid
{{ balance | format: "C2" }}
```

Cela affiche une valeur au format monétaire avec deux décimales.

### Balise personnalisée

#### `minify`

Génère une URL de redirection courte à partir d’un lien de Carte rendu.

```liquid
{% minify https://yoursite.com/account/{{ customer.id }} %}
```

La balise affiche d’abord l’expression imbriquée, puis crée une URL courte via le service de redirection The Wallet Crew, et enfin renvoie la chaîne d’URL raccourcie.

### Valider et dépanner les gabarits

#### Une variable s’affiche vide

Un chemin manquant ne fait pas échouer le rendu. Il se résout en chaîne vide. Inspectez **Voir les données** sur une vraie Carte, puis utilisez `default` là où c’est nécessaire.

```liquid
{{ loyalty.points | default: 0 }}
```

{% hint style="warning" %}
Une variable manquante produit généralement un champ vide. Validez les chemins de champ par rapport à un contexte de vraie Carte avant de publier une modification de gabarit.
{% endhint %}

#### Une date est décalée ou formatée de manière inattendue

Les dates contiennent des informations de fuseau horaire. Formatez explicitement la sortie souhaitée. Utilisez `add_hours` uniquement lorsqu’un décalage connu est requis.

```liquid
{{ ticket.startDate | date: "yyyy-MM-dd" }}
{{ ticket.startDate | add_hours: 2 | date: "HH:mm" }}
```

#### `format` ignore la locale de la Carte

C’est attendu. `format` utilise la culture invariante. Utilisez `date` pour les dates tenant compte de la locale. Assemblez le texte numérique ou monétaire spécifique à la locale dans chaque fichier de locale lorsque c’est nécessaire.

#### Un fichier YAML ne s’analyse pas

Mettez entre guillemets les valeurs Liquid contenant `:`, `{`, `#`, ou `&`. Utilisez `|-` pour les valeurs multilignes.

#### Une condition se comporte de manière inattendue

Le nombre `0` et la chaîne `"false"` sont considérés comme vrais. Comparez explicitement les valeurs numériques facultatives.

```liquid
{% if loyalty.points and loyalty.points > 0 %}…{% endif %}
```

#### La sortie comporte des lignes vides

Utilisez des tirets de contrôle des espaces autour des balises.

```liquid
{%- if ticket.alley -%}
  Allée {{ ticket.alley }}
{%- endif -%}
```

#### La syntaxe Liquid littérale est requise

Utilisation `raw` et `endraw`.

```liquid
{% raw %}{{ this is literal }}{% endraw %}
```

#### Le gabarit contient une erreur de syntaxe

Un Liquid invalide peut afficher un message d’erreur au lieu de la valeur souhaitée. Considérez les erreurs d’analyse comme des défauts de gabarit et corrigez-les avant la publication.

{% hint style="info" %}
Utilisez l’aperçu de la Carte dans le back-office pour tester les expressions Liquid sur de vraies données de Carte avant de déployer une modification de gabarit en production.
{% endhint %}

Pour le timing du rendu et la gestion des échecs en dehors de Liquid lui-même, voir [Comment une Carte est rendue](/developers-guides/fr/pass-architecture/how-a-pass-is-rendered.md).

### Filtres standard

Les filtres DotLiquid standard transforment les chaînes, les nombres, les dates et les collections.

#### Chaînes

| Filtre                               | Exemple                                          |
| ------------------------------------ | ------------------------------------------------ |
| `default`                            | `{{ loyalty.points \| default: 0 }}`             |
| `upcase`, `downcase`, `capitalize`   | `{{ firstName \| capitalize }}`                  |
| `strip`, `lstrip`, `rstrip`          | `{{ ticket.name \| strip }}`                     |
| `append`, `prepend`                  | `{{ publicUrl \| append: tenantId }}`            |
| `replace`, `remove`                  | `{{ ticket.name \| replace: "VIP", "Premium" }}` |
| `truncate`, `truncatewords`, `slice` | `{{ id.y2.customerId \| slice: 0, 4 }}`          |
| `split`                              | `{{ "a,b,c" \| split: "," }}`                    |

Utilisez un suffixe de troncation vide pour créer une initiale :

```liquid
{{ firstName | truncate: 1, "" | upcase | append: ". " }}{{ lastName | upcase }}
```

#### Nombres et collections

| Filtre                                           | Exemple                                                 |
| ------------------------------------------------ | ------------------------------------------------------- |
| `floor`, `ceil`, `round`                         | `{{ loyalty.points \| default: 0 \| floor }}`           |
| `plus`, `minus`, `times`, `divided_by`, `modulo` | `{{ loyalty.points \| divided_by: 100 \| floor }}`      |
| `abs`, `at_least`, `at_most`                     | `{{ balance \| at_least: 0 }}`                          |
| `size`, `first`, `last`, `join`                  | `{{ tags \| join: ", " }}`                              |
| `sort`, `reverse`, `uniq`, `compact`             | `{{ items \| sort \| reverse }}`                        |
| `map`, `where`                                   | `{{ y2.tickets \| map: "ticketNumber" \| join: ", " }}` |

#### Dates, URL et HTML

Le `date` filtre formate les valeurs de date pour la locale de la Carte.

| Expression                                           | Sortie typique      |
| ---------------------------------------------------- | ------------------- |
| `{{ ticket.startDate \| date: "D" }}`                | `Lundi 27 mai 2026` |
| `{{ ticket.startDate \| date: "d" }}`                | `27/05/2026`        |
| `{{ ticket.startDate \| date: "M" }}`                | `27 mai`            |
| `{{ ticket.startDate \| date: "t" }}`                | `20:00`             |
| `{{ ticket.startDate \| date: "yyyy-MM-dd HH:mm" }}` | `2026-05-27 20:00`  |

Utilisation `url_encode` et `url_decode` pour les valeurs d’URL. Utilisez `escape`, `escape_once`, ou `strip_html` pour les valeurs d’e-mail HTML.

Pour la liste complète des filtres, voir la [référence DotLiquid](https://github.com/dotliquid/dotliquid/wiki/DotLiquid-for-Designers).

### Recettes

Les modèles suivants répondent aux besoins courants des cartes de fidélité, cartes-cadeaux et billets d’événement. Confirmez tous les chemins de données avant utilisation.

#### Cartes de fidélité

**Afficher les points en toute sécurité**

`default` évite un solde vide. `floor` évite les décimales indésirables.

```liquid
{{ loyalty.points | default: 0 | floor }}
```

**Afficher séparément les points en attente**

N’affichez la ligne en attente que lorsque des points attendent validation.

```liquid
Available: {{ loyalty.points | default: 0 | floor }} pts
{% if pendingLoyaltyPoints and pendingLoyaltyPoints > 0 %}
En attente : {{ pendingLoyaltyPoints }} pts
{% endif %}
```

**Créer un compteur de tampons répétitif**

`modulo` réinitialise le compteur visible après chaque récompense.

```liquid
{{ additionalData.stampCount | default: 0 | modulo: 10 }} / 10
```

Le même modèle peut sélectionner une image correspondante :

```liquid
stamp_{{ additionalData.stampCount | default: 0 | modulo: 10 }}.png
```

**Afficher la progression vers la prochaine récompense**

Calculez les points restants à partir d’un seuil modifiable.

```liquid
{% assign threshold = additionalData.next_tier_threshold | default: 100 %}
{% assign missing = threshold | minus: loyalty.points %}
{{ missing | at_least: 0 }} pts jusqu’à {{ additionalData.next_tier_name | default: "votre prochaine récompense" }}
```

**Déduire un nom de niveau**

Ce modèle fonctionne lorsque la source fournit uniquement un solde de points.

```liquid
{% assign points = loyalty.points | default: 0 %}
{% if points >= 5000 %}Membre Or
{% elsif points >= 1000 %}Membre Argent
{% else %}Membre de bienvenue
{% endif %}
```

**Lister les bons disponibles**

Affichez les bons au dos de la carte. Un `sinon` branche rend l’état vide explicite.

```liquid
{% if y2.bons.loyaltyCertificates.size > 0 %}
  Vos bons :
  {% for voucher in y2.bons.loyaltyCertificates %}
    - Bon de {{ voucher.amount }} € (expire le {{ voucher.validity.endDate | date: "D" }})
  {% endfor %}
{% else %}
  Aucun bon disponible pour l’instant.
{% endif %}
```

#### Cartes-cadeaux

**Réutiliser un identifiant**

Utilisez la même valeur pour les champs du code-barres et de saisie manuelle.

```yaml
barCodeValue: '{{ id.y2.giftCardId }}'
barCodeAlternateText: '{{ id.y2.giftCardId }}'
cardNumber: '{{ id.y2.giftCardId }}'
```

**Afficher un montant variable**

Cela utilise un montant cadeau facultatif et un repli sûr.

```yaml
value: '{{ additionalData.giftAmount | default: 50 }}'
```

**Conservez le montant et la devise séparés**

Des champs dédiés permettent aux plateformes Wallet d'appliquer un formatage local de la devise.

```yaml
value: '{{ voucher.amount }}'
currencyCode: '{{ voucher.currency }}'
```

**Définissez la fenêtre de validité**

Utilisez les dates sources pour l'expiration et la pertinence.

```yaml
relevantDate: '{{ startDate }}'
expirationDate: '{{ expirationDate }}'
start: '{{ startDate }}'
end: '{{ expirationDate }}'
```

#### Billets d'événement

**Expire après l'événement**

Une expiration le jour suivant évite les problèmes de fuseau horaire et d'arrivée tardive.

```yaml
expirationDate: '{{ ticket.startDate | add_days: 1 | date: "d" }}'
```

**Définissez une fenêtre de pertinence**

Cela aide les plateformes Wallet à afficher le billet au bon moment.

```yaml
start: '{{ ticket.startDate | add_days: 0 | date: "d" }}'
end: '{{ ticket.startDate | add_days: 1 | date: "d" }}'
```

**Affichez la date et l'heure de l'événement**

Des champs séparés permettent à la mise en page Wallet de prioriser la date ou l'heure.

```yaml
l$label-date-apple: '{{ ticket.startDate | date: "M" }}'
l$value-date-apple: '{{ ticket.startDate | date: "t" }}'
```

**Associez les codes de catégorie**

`case` convertit les codes sources en libellés lisibles et spécifiques à la locale.

```liquid
{% assign category = ticket.priceCategory | strip %}
{% case category %}
  {% when "F" %}Plein tarif
  {% when "R" %}Réduit
  {% when "S" %}Étudiant
  {% when "C" %}Enfant
  {% else %}{{ category }}
{% endcase %}
```

**Construisez les indications pour le lieu**

Nettoyez les champs facultatifs avant de les concaténer. Le contrôle des espaces blancs maintient une sortie compacte.

```liquid
{%- assign zone3 = ticket.zone3 | strip -%}
{%- assign zone4 = ticket.zone4 | strip -%}
{%- assign alley = ticket.alley | strip -%}
{%- assign entrance = ticket.entrance | strip -%}
{%- assign location = zone3 | append: " " | append: zone4 -%}
{%- if alley -%}
  {%- assign location = location | append: " - Allée " | append: alley -%}
{%- endif -%}
{{ location }}
{% case entrance -%}
  {%- when "1", "2", "3", "4", "5", "6" -%}Porte 1 · Ascenseur 2
  {%- when "7", "8" -%}Côté de la porte 1 · Ascenseur 1
  {%- when "9", "10", "11", "12" -%}Porte 2 · Ascenseur 4
  {%- when "13", "14", "15", "16" -%}Porte 3 · Ascenseur 6
{%- endcase -%}
```

**Répertoriez les billets sur une Carte multi-billets**

Ceci est utile pour les achats groupés et les Cartes multi-événements.

```liquid
{% if y2.tickets.size > 0 %}
  Vos billets :
  {% for ticket in y2.tickets %}
    - #{{ ticket.ticketNumber }} pour {{ ticket.amount }} € le {{ ticket.creationDate | date: "D" }}
  {% endfor %}
{% endif %}
```

**Créez un lien profond authentifié**

N'utilisez ce modèle que lorsque la destination prend en charge le flux d'authentification de Carte.

```liquid
Mettez à jour votre profil <a href="{{ publicUrl }}{{ tenantId }}/mobile?neo.authToken={{ authenticationToken }}">ici</a>.
```

### FAQ

<details>

<summary><strong>Shopify Liquid est-il entièrement pris en charge ?</strong></summary>

Non. Wallet Crew utilise DotLiquid ainsi que les extensions personnalisées documentées sur cette page. Il ne faut pas supposer que les extensions spécifiques à Shopify fonctionnent, sauf si elles sont documentées ici.

</details>

<details>

<summary><strong>Comment trouver le bon chemin de variable ?</strong></summary>

Utilisez une vraie Carte, inspectez **Voir les données**, puis validez l'expression dans l'aperçu. Cela évite de deviner les noms de champs de mémoire.

</details>

<details>

<summary><strong>Pourquoi un champ s'affiche-t-il vide au lieu d'échouer ?</strong></summary>

Les variables manquantes se résolvent généralement en une chaîne vide. Les erreurs de syntaxe Liquid se comportent différemment et doivent être traitées comme des défauts de modèle.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.thewalletcrew.io/developers-guides/fr/integration-guides/wallet/templating-engine.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
