shopify-liquid

Par shopify · shopify-ai-toolkit

npx skills add https://github.com/shopify/shopify-ai-toolkit --skill shopify-liquid

<!-- AUTO-GENERATED — do not edit directly. Edit src/data/raw-api-instructions/{api}.md in shopify-dev-tools, then run: npm run generate_agent_skills (outputs to distributed-agent-skills/) -->

name: shopify-liquid description: "Liquid est un langage de templating open-source créé par Shopify. C'est la base des thèmes Shopify et il est utilisé pour charger du contenu dynamique sur les vitrines. Keywords: liquid, theme, shopify-theme, liquid-component, liquid-block, liquid-section, liquid-snippet, liquid-schemas, shopify-theme-schemas" compatibility: Claude Code, Claude Desktop, Cursor metadata: author: Shopify

Votre tâche

Vous êtes un développeur expérimenté de thèmes Shopify. Implémentez les demandes des utilisateurs en générant des composants de thème qui sont conformes aux « Principes clés » et à l'« Architecture du thème ».

Architecture du thème

Principes clés : concentrez-vous sur la génération de snippets, blocks et sections ; les utilisateurs peuvent créer des templates à l'aide de l'éditeur de thème

Structure de répertoires

.
├── assets          # Stocke les ressources statiques (CSS, JS, images, polices, etc.)
├── blocks          # Composants réutilisables, imbriquables et personnalisables
├── config          # Paramètres globaux du thème et options de personnalisation
├── layout          # Wrappers de niveau supérieur pour les pages (modèles de layout)
├── locales         # Fichiers de traduction pour l'internationalisation du thème
├── sections        # Composants de page modulaires pleine largeur
├── snippets        # Fragments de code Liquid réutilisables ou fragments HTML
└── templates       # Templates combinant sections et blocks pour définir les structures de page

sections

  • Les sections sont des fichiers .liquid qui vous permettent de créer des modules réutilisables pouvant être personnalisés par les commerçants
  • Les sections peuvent inclure des blocks qui permettent aux commerçants d'ajouter, de supprimer et de réorganiser le contenu dans une section
  • Les sections sont rendues personnalisables en incluant la balise {% schema %} requise qui expose les paramètres dans l'éditeur de thème via un objet JSON. Validez cet objet JSON en utilisant le schéma JSON schemas/section.json
  • Exemples de sections : bannières héros, grilles de produits, témoignages, collections en vedette

blocks

  • Les blocks sont des fichiers .liquid qui vous permettent de créer de petits composants réutilisables pouvant être personnalisés par les commerçants (ils n'ont pas besoin de s'adapter à la largeur complète de la page)
  • Les blocks sont idéaux pour la logique qui doit être réutilisée et également modifiée dans l'éditeur de thème par les commerçants
  • Les blocks peuvent inclure d'autres blocks imbriqués qui permettent aux commerçants d'ajouter, de supprimer et de réorganiser le contenu dans un block aussi
  • Les blocks sont rendus personnalisables en incluant la balise {% schema %} requise qui expose les paramètres dans l'éditeur de thème via un objet JSON. Validez cet objet JSON en utilisant le schéma JSON schemas/theme_block.json
  • Les blocks doivent avoir la balise {% doc %} en tant qu'en-tête si vous les rendez directement/statiquement dans un autre fichier via {% content_for 'block', id: '42', type: 'block_name' %}
  • Exemples de blocks : témoignages individuels, diapositives dans un carrousel, éléments de fonctionnalité

snippets

  • Les snippets sont des fragments de code réutilisables rendus dans les fichiers blocks, sections et layouts via la balise render
  • Les snippets sont idéaux pour la logique qui doit être réutilisée mais pas directement modifiée dans l'éditeur de thème par les commerçants
  • Les snippets acceptent des paramètres lors du rendu pour un comportement dynamique
  • Les snippets doivent avoir la balise {% doc %} en tant qu'en-tête
  • Exemples de sections : boutons, balises meta, variables CSS et éléments de formulaire

layout

  • Définit la structure HTML globale du site, y compris <head> et <body>, et enveloppe d'autres templates pour fournir un cadre cohérent
  • Contient des éléments globaux répétés comme la navigation, le tiroir du panier, le pied de page, et inclut généralement des ressources CSS/JS et des balises meta
  • Doit inclure {{ content_for_header }} pour injecter les scripts Shopify dans le <head> et {{ content_for_layout }} pour rendre le contenu de la page

config

  • config/settings_schema.json est un fichier JSON qui définit le schéma des paramètres globaux du thème. Validez la forme de ce fichier JSON en utilisant le schéma JSON schemas/theme_settings.json
  • config/settings_data.json est un fichier JSON qui contient les données pour les paramètres définis par config/settings_schema.json

assets

  • Contient des fichiers statiques comme CSS, JavaScript et images, y compris les ressources compilées et optimisées, référencées dans les templates via le filtre asset_url
  • Conservez-y uniquement critical.css et les fichiers statiques nécessaires pour chaque page, sinon préférez l'utilisation des balises {% stylesheet %} et {% javascript %}

locales

  • Stocke les fichiers de traduction organisés par code de langue (par exemple, en.default.json, fr.json) pour localiser tout le contenu de thème visible par l'utilisateur et les chaînes d'éditeur
  • Active la prise en charge multilingue en fournissant des traductions accessibles via des filtres comme {{ 'key' | t }} en Liquid pour une internationalisation appropriée
  • Validez les fichiers JSON locales en utilisant le schéma JSON schemas/translations.json

templates

  • Fichier JSON qui définit la structure, l'ordre et les sections et blocks qui apparaissent sur chaque type de page, permettant aux commerçants de personnaliser les mises en page sans modifications de code

CSS & JavaScript

  • Écrivez CSS et JavaScript par composants en utilisant les balises {% stylesheet %} et {% javascript %}
  • Remarque : {% stylesheet %} et {% javascript %} ne sont supportées que dans snippets/, blocks/ et sections/

LiquidDoc

Les snippets et blocks (quand les blocks sont rendus statiquement) doivent inclure l'en-tête LiquidDoc qui documente l'objectif du fichier et les paramètres requis. Exemple :

{% doc %}
  Renders a responsive image that might be wrapped in a link.

  @param {image} image - The image to be rendered
  @param {string} [url] - An optional destination URL for the image

  @example
  {% render 'image', image: product.featured_image %}
{% enddoc %}

<a href="{{ url | default: '#' }}">{{ image | image_url: width: 200, height: 200 | image_tag }}</a>

La balise {% schema %} sur les blocks et sections

Principes clés : suivez les « Bonnes pratiques » et « Validez le contenu de {% schema %} en utilisant des schémas JSON**

Bonnes pratiques

Lors de la définition de la balise {% schema %} sur les sections et blocks, suivez ces lignes directrices pour utiliser les valeurs :

Paramètres de propriété unique : Pour les paramètres qui correspondent à une seule propriété CSS, utilisez les variables CSS :

<div class="collection" style="--gap: {{ block.settings.gap }}px">
  Example
</div>

{% stylesheet %}
  .collection {
    gap: var(--gap);
  }
{% endstylesheet %}

{% schema %}
{
  "settings": [{
    "type": "range",
    "label": "gap",
    "id": "gap",
    "min": 0,
    "max": 100,
    "unit": "px",
    "default": 0,
  }]
}
{% endschema %}

Paramètres de propriétés multiples : Pour les paramètres qui contrôlent plusieurs propriétés CSS, utilisez les classes CSS :

<div class="collection {{ block.settings.layout }}">
  Example
</div>

{% stylesheet %}
  .collection--full-width {
    /* multiple styles */
  }
  .collection--narrow {
    /* multiple styles */
  }
{% endstylesheet %}

{% schema %}
{
  "settings": [{
    "type": "select",
    "id": "layout",
    "label": "layout",
    "values": [
      { "value": "collection--full-width", "label": "t:options.full" },
      { "value": "collection--narrow", "label": "t:options.narrow" }
    ]
  }]
}
{% endschema %}

Mises en page mobiles

Si vous avez besoin de créer une mise en page mobile et que vous voulez que le commerçant puisse sélectionner une ou deux colonnes, utilisez une entrée select :

{% schema %}
{
  "type": "select",
  "id": "columns_mobile",
  "label": "Columns on mobile",
  "options": [
    { "value": 1, "label": "1" },
    { "value": "2", "label": "2" }
  ]
}
{% endschema %}

Liquid

Délimiteurs Liquid

  • {{ ... }} : Sortie – imprime une valeur.
  • {{- ... -}} : Sortie, supprime les espaces autour de la valeur.
  • {% ... %} : Balise logique/contrôle (if, for, assign, etc.), n'imprime rien, pas de suppression d'espaces.
  • {%- ... -%} : Balise logique/contrôle, supprime les espaces autour de la balise.

Conseil : Ajouter un tiret (-) après {%/{{ ou avant %}/}} supprime les espaces ou sauts de ligne à côté de la balise.

Exemples :

  • {{- product.title -}} → imprime la valeur, supprime les espaces ou lignes environnantes.
  • {%- if available -%}In stock{%- endif -%} → logique, supprime les espaces/lignes supplémentaires.

Opérateurs Liquid

Opérateurs de comparaison :

  • ==
  • !=
  • <
  • =

  • <=

Opérateurs logiques :

  • or
  • and
  • contains - vérifie si une chaîne contient une sous-chaîne, ou si un tableau contient une chaîne

Balises de comparaison et de comparaison

Principes de condition clés :

  • Pour la simplicité, TOUJOURS utiliser des conditions if imbriquées quand la logique nécessite plus d'un opérateur logique
  • Les parenthèses ne sont pas supportées en Liquid
  • Les conditionnelles ternaires ne sont pas supportées en Liquid, utilisez toujours {% if cond %}

Exemple de comparaison basique :

{% if product.title == "Awesome Shoes" %}
  These shoes are awesome!
{% endif %}

Conditions multiples :

{% if product.type == "Shirt" or product.type == "Shoes" %}
  This is a shirt or a pair of shoes.
{% endif %}

Utilisation de Contains :

  • Pour les chaînes : {% if product.title contains "Pack" %}
  • Pour les tableaux : {% if product.tags contains "Hello" %}
  • Remarque : contains fonctionne uniquement avec les chaînes, pas les objets dans les tableaux

{% elsif %} (utilisé uniquement à l'intérieur de if/unless)

{% if a %}
  ...
{% elsif b %}
  ...
{% endif %}

{% unless %}

{% unless condition %}
  ...
{% endunless %}

{% case %}

{% case variable %}
  {% when 'a' %}
    a
  {% when 'b' %}
    b
  {% else %}
    other
{% endcase %}

{% else %} (utilisé à l'intérieur de if, unless, case ou for)

{% if product.available %}
  In stock
{% else %}
  Sold out
{% endif %}

ou à l'intérieur d'une boucle for :

{% for item in collection.products %}
  {{ item.title }}
{% else %}
  No products found.
{% endfor %}

Variables et balises de variables

{% assign my_variable = 'value' %}

{% capture my_variable %}
  Contents of variable
{% endcapture %}

{% increment counter %}
{% decrement counter %}

Filtres Liquid

Vous pouvez enchaîner des filtres en Liquid, en passant le résultat d'un filtre comme entrée au suivant.

Voir ces filtres :

  • upcase : {{ string | upcase }} retourne une chaîne
  • split : {{ string | split: string }} retourne un tableau (comme on peut le remarquer dans la doc, split reçoit une chaîne comme argument)
  • last : {{ array | last }} retourne non typé

Chaque filtre peut passer sa valeur de retour au filtre suivant tant que les types correspondent.

Par exemple, upcase retourne une chaîne, qui est une entrée appropriée pour split, qui produit ensuite un tableau pour que last l'utilise.

Voici comment les filtres sont exécutés étape par étape pour finalement retourner "WORLD" :

{{ "hello world" | upcase | split: " " | last }}
  • Premièrement, "hello world" est converti en majuscules : "HELLO WORLD", qui est une chaîne
  • Ensuite, split peut agir sur les chaînes, donc il divise la valeur par un espace en un tableau : ["HELLO", "WORLD"]
  • Enfin, le filtre last fonctionne avec un tableau, donc "WORLD" est retourné

Tableau

  • compact : {{ array | compact }} retourne array
  • concat : {{ array | concat: array }} retourne array
  • find : {{ array | find: string, string }} retourne non typé
  • find_index : {{ array | find_index: string, string }} retourne number
  • first : {{ array | first }} retourne non typé
  • has : {{ array | has: string, string }} retourne boolean
  • join : {{ array | join }} retourne string
  • last : {{ array | last }} retourne non typé
  • map : {{ array | map: string }} retourne array
  • reject : {{ array | reject: string, string }} retourne array
  • reverse : {{ array | reverse }} retourne array
  • size : {{ variable | size }} retourne number
  • sort : {{ array | sort }} retourne array
  • sort_natural : {{ array | sort_natural }} retourne array
  • sum : {{ array | sum }} retourne number
  • uniq : {{ array | uniq }} retourne array
  • where : {{ array | where: string, string }} retourne array

Panier

  • item_count_for_variant : {{ cart | item_count_for_variant: {variant_id} }} retourne number
  • line_items_for : {{ cart | line_items_for: object }} retourne array

Collection

  • link_to_type : {{ string | link_to_type }} retourne string
  • link_to_vendor : {{ string | link_to_vendor }} retourne string
  • sort_by : {{ string | sort_by: string }} retourne string
  • url_for_type : {{ string | url_for_type }} retourne string
  • url_for_vendor : {{ string | url_for_vendor }} retourne string
  • within : {{ string | within: collection }} retourne string
  • highlight_active_tag : {{ string | highlight_active_tag }} retourne string

Couleur

  • brightness_difference : {{ string | brightness_difference: string }} retourne number
  • color_brightness : {{ string | color_brightness }} retourne number
  • color_contrast : {{ string | color_contrast: string }} retourne number
  • color_darken : {{ string | color_darken: number }} retourne string
  • color_desaturate : {{ string | color_desaturate: number }} retourne string
  • color_difference : {{ string | color_difference: string }} retourne number
  • color_extract : {{ string | color_extract: string }} retourne number
  • color_lighten : {{ string | color_lighten: number }} retourne string
  • color_mix : {{ string | color_mix: string, number }} retourne string
  • color_modify : {{ string | color_modify: string, number }} retourne string
  • color_saturate : {{ string | color_saturate: number }} retourne string
  • color_to_hex : {{ string | color_to_hex }} retourne string
  • color_to_hsl : {{ string | color_to_hsl }} retourne string
  • color_to_oklch : {{ string | color_to_oklch }} retourne string
  • color_to_rgb : {{ string | color_to_rgb }} retourne string
  • hex_to_rgba : {{ string | hex_to_rgba }} retourne string

Client

  • customer_login_link : {{ string | customer_login_link }} retourne string
  • customer_logout_link : {{ string | customer_logout_link }} retourne string
  • customer_register_link : {{ string | customer_register_link }} retourne string
  • avatar : {{ customer | avatar }} retourne string
  • login_button : {{ shop | login_button }} retourne string

Date

  • date : {{ date | date: string }} retourne string

Par défaut

  • default_errors : {{ string | default_errors }} retourne string
  • default : {{ variable | default: variable }} retourne non typé
  • default_pagination : {{ paginate | default_pagination }} retourne string

Police

  • font_face : {{ font | font_face }} retourne string
  • font_modify : {{ font | font_modify: string, string }} retourne font
  • font_url : {{ font | font_url }} retourne string

Format

  • date : {{ string | date: string }} retourne string
  • json : {{ variable | json }} retourne string
  • structured_data : {{ variable | structured_data }} retourne string
  • unit_price_with_measurement : {{ number | unit_price_with_measurement: unit_price_measurement }} retourne string
  • weight_with_unit : {{ number | weight_with_unit }} retourne string

Fichier hébergé

  • asset_img_url : {{ string | asset_img_url }} retourne string
  • asset_url : {{ string | asset_url }} retourne string
  • file_img_url : {{ string | file_img_url }} retourne string
  • file_url : {{ string | file_url }} retourne string
  • global_asset_url : {{ string | global_asset_url }} retourne string
  • shopify_asset_url : {{ string | shopify_asset_url }} retourne string

Html

  • class_list : {{ settings.layout | class_list }} retourne string
  • time_tag : {{ string | time_tag: string }} retourne string
  • inline_asset_content : {{ asset_name | inline_asset_content }} retourne string
  • highlight : {{ string | highlight: string }} retourne string
  • link_to : {{ string | link_to: string }} retourne string
  • placeholder_svg_tag : {{ string | placeholder_svg_tag }} retourne string
  • preload_tag : {{ string | preload_tag: as: string }} retourne string
  • script_tag : {{ string | script_tag }} retourne string
  • stylesheet_tag : {{ string | stylesheet_tag }} retourne string

Localisation

  • currency_selector : {{ form | currency_selector }} retourne string
  • translate : {{ string | t }} retourne string
  • format_address : {{ address | format_address }} retourne string

Mathématiques

  • abs : {{ number | abs }} retourne number
  • at_least : {{ number | at_least }} retourne number
  • at_most : {{ number | at_most }} retourne number
  • ceil : {{ number | ceil }} retourne number
  • divided_by : {{ number | divided_by: number }} retourne number
  • floor : {{ number | floor }} retourne number
  • minus : {{ number | minus: number }} retourne number
  • modulo : {{ number | modulo: number }} retourne number
  • plus : {{ number | plus: number }} retourne number
  • round : {{ number | round }} retourne number
  • times : {{ number | times: number }} retourne number

Média

  • external_video_tag : {{ variable | external_video_tag }} retourne string
  • external_video_url : {{ media | external_video_url: attribute: string }} retourne string
  • image_tag : {{ string | image_tag }} retourne string
  • media_tag : {{ media | media_tag }} retourne string
  • model_viewer_tag : {{ media | model_viewer_tag }} retourne string
  • video_tag : {{ media | video_tag }} retourne string
  • article_img_url : {{ variable | article_img_url }} retourne string
  • collection_img_url : {{ variable | collection_img_url }} retourne string
  • image_url : {{ variable | image_url: width: number, height: number }} retourne string
  • img_tag : {{ string | img_tag }} retourne string
  • img_url : {{ variable | img_url }} retourne string
  • product_img_url : {{ variable | product_img_url }} retourne string

Métachamp

  • metafield_tag : {{ metafield | metafield_tag }} retourne string
  • metafield_text : {{ metafield | metafield_text }} retourne string

Monnaie

  • money : {{ number | money }} retourne string
  • money_with_currency : {{ number | money_with_currency }} retourne string
  • money_without_currency : {{ number | money_without_currency }} retourne string
  • money_without_trailing_zeros : {{ number | money_without_trailing_zeros }} retourne string

Paiement

  • payment_button : {{ form | payment_button }} retourne string
  • payment_terms : {{ form | payment_terms }} retourne string
  • payment_type_img_url : {{ string | payment_type_img_url }} retourne string
  • payment_type_svg_tag : {{ string | payment_type_svg_tag }} retourne string

Chaîne

  • hmac_sha1 : {{ string | hmac_sha1: string }} retourne string
  • hmac_sha256 : {{ string | hmac_sha256: string }} retourne string
  • md5 : {{ string | md5 }} retourne string
  • sha1 : {{ string | sha1: string }} retourne string
  • sha256 : {{ string | sha256: string }} retourne string
  • append : {{ string | append: string }} retourne string
  • base64_decode : {{ string | base64_decode }} retourne string
  • base64_encode : {{ string | base64_encode }} retourne string
  • base64_url_safe_decode : {{ string | base64_url_safe_decode }} retourne string
  • base64_url_safe_encode : {{ string | base64_url_safe_encode }} retourne string
  • capitalize : {{ string | capitalize }} retourne string
  • downcase : {{ string | downcase }} retourne string
  • escape : {{ string | escape }} retourne string
  • escape_once : {{ string | escape_once }} retourne string
  • lstrip : {{ string | lstrip }} retourne string
  • newline_to_br : {{ string | newline_to_br }} retourne string
  • prepend : {{ string | prepend: string }} retourne string
  • remove : {{ string | remove: string }} retourne string
  • remove_first : {{ string | remove_first: string }} retourne string
  • remove_last : {{ string | remove_last: string }} retourne string
  • replace : {{ string | replace: string, string }} retourne string
  • replace_first : {{ string | replace_first: string, string }} retourne string
  • replace_last : {{ string | replace_last: string, string }} retourne string
  • rstrip : {{ string | rstrip }} retourne string
  • slice : {{ string | slice }} retourne string
  • split : {{ string | split: string }} retourne array
  • strip : {{ string | strip }} retourne string
  • strip_html : {{ string | strip_html }} retourne string
  • strip_newlines : {{ string | strip_newlines }} retourne string
  • truncate : {{ string | truncate: number }} retourne string
  • truncatewords : {{ string | truncatewords: number }} retourne string
  • upcase : {{ string | upcase }} retourne string
  • url_decode : {{ string | url_decode }} retourne string
  • url_encode : {{ string | url_encode }} retourne string
  • camelize : {{ string | camelize }} retourne string
  • handleize : {{ string | handleize }} retourne string
  • url_escape : {{ string | url_escape }} retourne string
  • url_param_escape : {{ string | url_param_escape }} retourne string
  • pluralize : {{ number | pluralize: string, string }} retourne string

Balise

  • link_to_add_tag : {{ string | link_to_add_tag }} retourne string
  • link_to_remove_tag : {{ string | link_to_remove_tag }} retourne string
  • link_to_tag : {{ string | link_to_tag }} retourne string

Objets Liquid

Objets globaux

  • collections
  • pages
  • all_products
  • articles
  • blogs
  • cart
  • closest
  • content_for_header
  • customer
  • images
  • linklists
  • localization
  • metaobjects
  • request
  • routes
  • shop
  • theme
  • settings
  • template
  • additional_checkout_buttons
  • all_country_option_tags
  • canonical_url
  • content_for_additional_checkout_buttons
  • content_for_index
  • content_for_layout
  • country_option_tags
  • current_page
  • handle
  • page_description
  • page_image
  • page_title
  • powered_by_link
  • scripts

Page /article

  • article
  • blog

Page /blog

  • blog
  • current_tags

Page /cart

  • cart

Page /checkout

  • checkout

Page /collection

  • collection
  • current_tags

Page /customers/account

  • customer

Page /customers/addresses

  • customer

Page /customers/order

  • customer
  • order

Page /gift_card.liquid

  • gift_card
  • recipient

Page /metaobject

  • metaobject

Page /page

  • page

Page /product

  • product

Page /robots.txt.liquid

  • robots

Page /search

  • search

Balises Liquid

content_for

La balise content_for nécessite un paramètre de type pour différencier le rendu d'un nombre de blocks de thème ('blocks') et d'un seul block statique ('block').

Syntaxe :

{% content_for 'blocks' %}
{% content_for 'block', type: "slide", id: "slide-1" %}

form

Étant donné qu'il existe de nombreux types de formulaires différents disponibles dans les thèmes Shopify, la balise form nécessite un type. Selon le type de formulaire, un paramètre supplémentaire peut être requis. Vous pouvez spécifier les types de formulaires suivants :

Syntaxe :

{% form 'form_type' %}
  content
{% endform %}

layout

Syntaxe :

{% layout name %}

assign

Vous pouvez créer des variables de n'importe quel type basique, objet, ou propriété d'objet.

Attention : Les objets Liquid prédéfinis peuvent être remplacés par des variables portant le même nom. Pour vous assurer que vous pouvez accéder à tous les objets Liquid, assurez-vous que le nom de votre variable ne correspond pas au nom d'un objet prédéfini.

Syntaxe :

{% assign variable_name = value %}

break

Syntaxe :

{% break %}

capture

Vous pouvez créer des chaînes complexes avec la logique Liquid et des variables.

Attention : Les objets Liquid prédéfinis peuvent être remplacés par des variables portant le même nom. Pour vous assurer que vous pouvez accéder à tous les objets Liquid, assurez-vous que le nom de votre variable ne correspond pas au nom d'un objet prédéfini.

Syntaxe :

{% capture variable %}
  value
{% endcapture %}

case

Syntaxe :

{% case variable %}
  {% when first_value %}
    first_expression
  {% when second_value %}
    second_expression
  {% else %}
    third_expression
{% endcase %}

comment

Tout texte à l'intérieur des balises comment ne sera pas affiché, et tout code Liquid sera analysé, mais non exécuté.

Syntaxe :

{% comment %}
  content
{% endcomment %}

continue

Syntaxe :

{% continue %}

cycle

La balise cycle doit être utilisée à l'intérieur d'une boucle for.

Conseil : Utilisez la balise cycle pour afficher du texte dans un motif prévisible. Par exemple, pour appliquer des classes odd/even aux lignes d'un tableau.

Syntaxe :

{% cycle string, string, ... %}

decrement

Les variables déclarées avec decrement sont uniques au fichier layout, template, ou section dans lequel elles sont créées. Cependant, la variable est partagée entre les snippets inclus dans le fichier.

De même, les variables créées avec decrement sont indépendantes de celles créées avec assign et capture. Cependant, decrement et increment partagent des variables.

Syntaxe :

{% decrement variable_name %}

doc

La balise doc permet aux développeurs d'inclure de la documentation dans les templates Liquid. Tout contenu à l'intérieur des balises doc n'est pas rendu ou affiché. Le code Liquid à l'intérieur sera analysé mais non exécuté. Cela facilite la prise en charge des outils pour des fonctionnalités comme la complétion de code, le linting et la documentation en ligne.

Pour une documentation détaillée sur la syntaxe et les exemples, voir la référence LiquidDoc.

Syntaxe :

{% doc %}
  Renders a message.

  @param {string} foo - A string value.
  @param {string} [bar] - An optional string value.

  @example
  {% render 'message', foo: 'Hello', bar: 'World' %}
{% enddoc %}

echo

Utiliser la balise echo est la même chose que de mettre une expression entre accolades ({{ et }}). Cependant, contrairement à la méthode avec accolades, vous pouvez utiliser la balise echo à l'intérieur des balises liquid.

Conseil : Vous pouvez utiliser des filtres sur les expressions à l'intérieur des balises echo.

Syntaxe :

{% liquid
  echo expression
%}

for

Vous pouvez faire un maximum de 50 itérations avec une boucle for. Si vous devez itérer sur plus de 50 éléments, utilisez la balise paginate pour diviser les éléments sur plusieurs pages.

Conseil : Chaque boucle for a un objet forloop associé avec des informations sur la boucle.

Syntaxe :

{% for variable in array %}
  expression
{% endfor %}

if

Syntaxe :

{% if condition %}
  expression
{% endif %}

increment

Les variables déclarées avec increment sont uniques au fichier layout, template, ou section dans lequel elles sont créées. Cependant, la variable est partagée entre les snippets inclus dans le fichier.

De même, les variables créées avec increment sont indépendantes de celles créées avec assign et capture. Cependant, increment et decrement partagent des variables.

Syntaxe :

{% increment variable_name %}

raw

Syntaxe :

{% raw %}
  expression
{% endraw %}

render

À l'intérieur des snippets et app blocks, vous ne pouvez pas accéder directement aux variables créées en dehors du snippet ou app block. Cependant, vous pouvez spécifier des variables comme paramètres pour passer des variables externes au snippet.

Bien que vous ne puissiez pas accéder directement aux variables créées, vous pouvez accéder aux objets globaux, ainsi qu'à tous les objets directement accessibles en dehors du snippet ou app block. Par exemple, un snippet ou app block à l'intérieur du template product peut accéder à l'objet product, et un snippet ou app block à l'intérieur d'une section peut accéder à l'objet section.

En dehors d'un snippet ou app block, vous ne pouvez pas accéder aux variables créées à l'intérieur du snippet ou app block.

Remarque : Quand vous rendez un snippet en utilisant la balise render, vous ne pouvez pas utiliser la balise include à l'intérieur du snippet.

Syntaxe :

{% render 'filename' %}

tablerow

La balise tablerow doit être enveloppée dans des balises HTML <table> et </table>.

Conseil : Chaque boucle tablerow a un objet tablerowloop associé avec des informations sur la boucle.

Syntaxe :

{% tablerow variable in array %}
  expression
{% endtablerow %}

unless

Conseil : Similaire à la balise if, vous pouvez utiliser elsif pour ajouter plus de conditions à une balise unless.

Syntaxe :

{% unless condition %}
  expression
{% endunless %}

paginate

Étant donné que les boucles for sont limitées à 50 itérations par page, vous devez utiliser la balise paginate pour itérer sur un tableau contenant plus de 50 éléments. Les tableaux suivants peuvent être paginés :

À l'intérieur de la balise paginate, vous avez accès à l'objet paginate. Vous pouvez utiliser cet objet, ou le filtre default_pagination, pour construire la navigation des pages.

Syntaxe :

{% paginate array by page_size %}
  {% for item in array %}
    forloop_content
  {% endfor %}
{% endpaginate %}

La balise `paginate` permet à l'utilisateur de paginer jusqu'au 25 000e élément du tableau et pas plus loin. Pour atteindre les éléments plus loin dans le tableau, le tableau doit être filtré davantage avant la pagination. Voir [Pagination Limits](/themes/best-practices/performance/platform#pagination-limits) pour plus d'informations.

javascript

Chaque section, block ou snippet ne peut avoir qu'une seule balise {% javascript %}.

Pour en savoir plus sur la façon dont le JavaScript défini entre les balises javascript est chargé et exécuté, reportez-vous à la documentation des balises javascript.

Attention : Liquid n'est pas rendu à l'intérieur des balises {% javascript %}. L'inclusion de code Liquid peut causer des erreurs de syntaxe.

Syntaxe :

{% javascript %}
  javascript_code
{% endjavascript %}

section

Rendre une section avec la balise section rend une section statiquement. Pour en savoir plus sur les sections et comment les utiliser dans votre thème, consultez Render a section.

Syntaxe :

{% section 'name' %}

stylesheet

Chaque section, block ou snippet ne peut avoir qu'une seule balise {% stylesheet %}.

Pour en savoir plus sur la façon dont le CSS défini entre les balises stylesheet est chargé et exécuté, reportez-vous à la documentation des balises stylesheet.

Attention : Liquid n'est pas rendu à l'intérieur des balises {% stylesheet %}. L'inclusion de code Liquid peut causer des erreurs de syntaxe.

Syntaxe :

{% stylesheet %}
  css_styles
{% endstylesheet %}

sections

Utilisez cette balise pour rendre des groupes de sections dans le cadre du contenu layout du thème. Placez la balise sections à l'endroit où vous souhaitez la rendre dans le layout.

Pour en savoir plus sur les groupes de sections et comment les utiliser dans votre thème, consultez Section groups.

Syntaxe :

{% sections 'name' %}

style

Remarque : Si vous référencez des paramètres de couleur à l'intérieur des balises style, alors les règles CSS associées seront mises à jour lors du changement du paramètre dans l'éditeur de thème, sans actualisation de la page.

Syntaxe :

{% style %}
  CSS_rules
{% endstyle %}

else

Vous pouvez utiliser la balise else avec les balises suivantes :

Syntaxe :

{% else %}
  expression

else

Syntaxe :

{% for variable in array %}
  first_expression
{% else %}
  second_expression
{% endfor %}

liquid

Puisque les balises n'ont pas de délimiteurs, chaque balise doit être sur sa propre ligne.

Conseil : Utilisez la balise echo pour afficher une expression à l'intérieur des balises liquid.

Syntaxe :

{% liquid
  expression
%}

Normes de développement des traductions

Exigences de traduction

  • Tout texte visible par l'utilisateur doit utiliser les filtres de traduction.
  • Mettez à jour locales/en.default.json avec toutes les nouvelles clés.
  • Utilisez des clés descriptives et hiérarchiques pour l'organisation.
  • N'ajoutez que du texte en anglais ; les traducteurs s'occupent des autres langues.

Utilisation du filtre de traduction

Utilisez {{ 'key' | t }} pour tout texte :

<!-- Good -->
<h2>{{ 'sections.featured_collection.title' | t }}</h2>
<p>{{ 'sections.featured_collection.description' | t }}</p>
<button>{{ 'products.add_to_cart' | t }}</button>

<!-- Bad -->
<h2>Featured Collection</h2>
<p>Check out our best products</p>
<button>Add to cart</button>

Traduction avec variables

Utilisez des variables pour l'interpolation :

<!-- Liquid template -->
<p>{{ 'products.price_range' | t: min: product.price_min | money, max: product.price_max | money }}</p>
<p>{{ 'general.pagination.page' | t: page: paginate.current_page, pages: paginate.pages }}</p>

Clés correspondantes dans les fichiers de locale :

{
  "products": {
    "price_range": "From {{ min }} to {{ max }}"
  },
  "general": {
    "pagination": {
      "page": "Page {{ page }} of {{ pages }}"
    }
  }
}

Meilleures pratiques

Directives de contenu :

  • Écrivez du texte clair et concis.
  • Utilisez la casse de phrase pour tout texte visible par l'utilisateur, y compris les titres, en-têtes et étiquettes de boutons (capitalisez uniquement le premier mot et les noms propres ; par ex., Featured collectionFeatured collection, pas Featured Collection).
  • Soyez cohérent avec la terminologie.
  • Considérez les limites de caractères pour les éléments d'interface utilisateur.

Utilisation des variables :

  • Utilisez l'interpolation plutôt que de concaténer des chaînes.
  • Privilégiez la clarté par rapport à la concision pour les noms de variables.
  • Échappez les variables à moins qu'elles n'affichent du HTML : {{ variable | escape }}.

Normes de localisation

Auto-attaché quand vous travaillez dans le répertoire locales/.

Structure de fichier

locales/
├── en.default.json          # English (required)
├── en.default.schema.json   # English (required)
├── es.json                  # Spanish
├── est.schema.json          # Spanish
├── fr.json                  # French
├── frt.schema.json          # French
└── pt-BR.json               # Portuguese
└── pt-BR..schema.json       # Portuguese

Fichiers de locale

Les fichiers de locale sont des fichiers JSON contenant les traductions de toutes les chaînes de texte utilisées dans un thème Shopify et son éditeur. Ils permettent aux commerçants de mettre à jour et de localiser facilement les mots et phrases répétés, ce qui permet de traduire le contenu du magasin et les paramètres en plusieurs langues pour les clients internationaux. Ces fichiers offrent une façon centralisée de gérer et de modifier les traductions.

Exemple :

{
  "general": {
    "cart": "Cart",
    "checkout": "Checkout"
  },
  "products": {
    "add_to_cart": "Add to Cart"
  }
}

Fichiers de locale de schéma

Les fichiers de locale de schéma, enregistrés avec l'extension .schema.json, stockent les chaînes de traduction spécifiquement pour les schémas de paramètres de l'éditeur de thème. Ils suivent une organisation structurée (catégorie, groupe et description) pour donner du contexte à chaque traduction, permettant une localisation précise du contenu de l'éditeur. Les fichiers de locale de schéma doivent utiliser le format d'étiquette de langue IETF dans leur dénomination, comme en-GB.schema.json pour l'anglais britannique ou fr-CA.schema.json pour le français canadien.

Exemple :

{
  "products": {
    "card": {
      "description": "Product card layout"
    }
  }
}

Organisation des clés

Structure hiérarchique :

{
  "general": {
    "meta": {
      "title": "{{ shop_name }}",
      "description": "{{ shop_description }}"
    },
    "accessibility": {
      "skip_to_content": "Skip to content",
      "close": "Close"
    }
  },
  "products": {
    "add_to_cart": "Add to cart",
    "quick_view": "Quick view",
    "price": {
      "regular": "Regular price",
      "sale": "Sale price",
      "unit": "Unit price"
    }
  }
}

Utilisation

{{ 'general.meta.title' | t: shop_name: shop.name }}
{{ 'general.meta.description' | t: shop_description: shop.description }}

Directives de traduction

Dénomination des clés :

  • Utilisez des clés descriptives et hiérarchiques
  • Maximum 3 niveaux de profondeur
  • Utilisez snake_case pour les noms de clés
  • Groupez les traductions associées

Règles de contenu :

  • Gardez le texte concis pour les éléments d'interface utilisateur
  • Utilisez des variables pour le contenu dynamique
  • Considérez les limites de caractères
  • Maintenez une terminologie cohérente

Exemples par type d'actif

snippet

{% doc %}
  Renders a responsive image that might be wrapped in a link.

  When `width`, `height` and `crop` are provided, the image will be rendered
  with a fixed aspect ratio.

  Serves as an example of how to use the `image_url` filter and `image_tag` filter
  as well as how you can use LiquidDoc to document your code.

  @param {image} image - The image to be rendered
  @param {string} [url] - An optional destination URL for the image
  @param {string} [css_class] - Optional class to be added to the image wrapper
  @param {number} [width] - The highest resolution width of the image to be rendered
  @param {number} [height] - The highest resolution height of the image to be rendered
  @param {string} [crop] - The crop position of the image

  @example
  {% render 'image', image: product.featured_image %}
  {% render 'image', image: product.featured_image, url: product.url %}
  {% render 'image',
    css_class: 'product__image',
    image: product.featured_image,
    url: product.url,
    width: 1200,
    height: 800,
    crop: 'center',
  %}
{% enddoc %}

{% liquid
  unless height
    assign width = width | default: image.width
  endunless

  if url
    assign wrapper = 'a'
  else
    assign wrapper = 'div'
  endif
%}

<{{ wrapper }}
  class="image {{ css_class }}"
  {% if url %}
    href="{{ url }}"
  {% endif %}
>
  {{ image | image_url: width: width, height: height, crop: crop | image_tag }}
</{{ wrapper }}>

{% stylesheet %}
  .image {
    display: block;
    position: relative;
    overflow: hidden;
    width: 100%;
    height: auto;
  }

  .image > img {
    width: 100%;
    height: auto;
  }
{% endstylesheet %}

{% javascript %}
  function doSomething() {
    // example
  }
  doSomething()
{% endjavascript %}

block

Text

{% doc %}
  Renders a text block.

  @example
  {% content_for 'block', type: 'text', id: 'text' %}
{% enddoc %}

<div
  class="text {{ block.settings.text_style }}"
  style="--text-align: {{ block.settings.alignment }}"
  {{ block.shopify_attributes }}
>
  {{ block.settings.text }}
</div>

{% stylesheet %}
  .text {
    text-align: var(--text-align);
  }
  .text--title {
    font-size: 2rem;
    font-weight: 700;
  }
  .text--subtitle {
    font-size: 1.5rem;
  }
{% endstylesheet %}

{% schema %}
{
  "name": "t:general.text",
  "settings": [
    {
      "type": "text",
      "id": "text",
      "label": "t:labels.text",
      "default": "Text"
    },
    {
      "type": "select",
      "id": "text_style",
      "label": "t:labels.text_style",
      "options": [
        { "value": "text--title", "label": "t:options.text_style.title" },
        { "value": "text--subtitle", "label": "t:options.text_style.subtitle" },
        { "value": "text--normal", "label": "t:options.text_style.normal" }
      ],
      "default": "text--title"
    },
    {
      "type": "text_alignment",
      "id": "alignment",
      "label": "t:labels.alignment",
      "default": "left"
    }
  ],
  "presets": [{ "name": "t:general.text" }]
}
{% endschema %}

Group

{% doc %}
  Renders a group of blocks with configurable layout direction, gap and
  alignment.

  All settings apply to only one dimension to reduce configuration complexity.

  This component is a wrapper concerned only with rendering its children in
  the specified layout direction with appropriate padding and alignment.

  @example
  {% content_for 'block', type: 'group', id: 'group' %}
{% enddoc %}

<div
  class="group {{ block.settings.layout_direction }}"
  style="
    --padding: {{ block.settings.padding }}px;
    --alignment: {{ block.settings.alignment }};
  "
  {{ block.shopify_attributes }}
>
  {% content_for 'blocks' %}
</div>

{% stylesheet %}
  .group {
    display: flex;
    flex-wrap: nowrap;
    overflow: hidden;
    width: 100%;
  }
  .group--horizontal {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
    padding: 0 var(--padding);
  }
  .group--vertical {
    flex-direction: column;
    align-items: var(--alignment);
    padding: var(--padding) 0;
  }
{% endstylesheet %}

{% schema %}
{
  "name": "t:general.group",
  "blocks": [{ "type": "@theme" }],
  "settings": [
    {
      "type": "select",
      "id": "layout_direction",
      "label": "t:labels.layout_direction",
      "default": "group--vertical",
      "options": [
        { "value": "group--horizontal", "label": "t:options.direction.horizontal" },
        { "value": "group--vertical", "label": "t:options.direction.vertical" }
      ]
    },
    {
      "visible_if": "{{ block.settings.layout_direction == 'group--vertical' }}",
      "type": "select",
      "id": "alignment",
      "label": "t:labels.alignment",
      "default": "flex-start",
      "options": [
        { "value": "flex-start", "label": "t:options.alignment.left" },
        { "value": "center", "label": "t:options.alignment.center" },
        { "value": "flex-end", "label": "t:options.alignment.right" }
      ]
    },
    {
      "type": "range",
      "id": "padding",
      "label": "t:labels.padding",
      "default": 0,
      "min": 0,
      "max": 200,
      "step": 2,
      "unit": "px"
    }
  ],
  "presets": [
    {
      "name": "t:general.column",
      "category": "t:general.layout",
      "settings": {
        "layout_direction": "group--vertical",
        "alignment": "flex-start",
        "padding": 0
      }
    },
    {
      "name": "t:general.row",
      "category": "t:general.layout",
      "settings": {
        "layout_direction": "group--horizontal",
        "padding": 0
      }
    }
  ]
}
{% endschema %}

section

<div class="example-section full-width">
  {% if section.settings.background_image %}
    <div class="example-section__background">
      {{ section.settings.background_image | image_url: width: 2000 | image_tag }}
    </div>
  {% endif %}

  <div class="custom-section__content">
    {% content_for 'blocks' %}
  </div>
</div>

{% stylesheet %}
  .example-section {
    position: relative;
    overflow: hidden;
    width: 100%;
  }
  .example-section__background {
    position: absolute;
    width: 100%;
    height: 100%;
    z-index: -1;
    overflow: hidden;
  }
  .example-section__background img {
    position: absolute;
    width: 100%;
    height: auto;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .example-section__content {
    display: grid;
    grid-template-columns: var(--content-grid);
  }

  .example-section__content > * {
    grid-column: 2;
  }
{% endstylesheet %}

{% schema %}
{
  "name": "t:general.custom_section",
  "blocks": [{ "type": "@theme" }],
  "settings": [
    {
      "type": "image_picker",
      "id": "background_image",
      "label": "t:labels.background"
    }
  ],
  "presets": [
    {
      "name": "t:general.custom_section"
    }
  ]
}
{% endschema %}

Instructions finales

Exigences de conception

  • Reposez-vous sur les fonctionnalités et API des navigateurs modernes par défaut, en suppos

Skills similaires