1. Legacy Theme Migration
  • Getting Started
    • Introduction
    • Theme Development
    • Publishing Your Theme
    • Legacy Theme Migration
      • Store Settings Mapping
      • Moving to Vitrin Using LLMs
      • Twig to Jinja
      • Breaking Changes
  • Key Concepts
    • Architecture
    • Templates
      • Overview
      • Template Library
        • home.jinja
        • 404_not_found.jinja
        • account_wishlist.jinja
        • categories.jinja
        • page.jinja
        • reviews.jinja
        • account_addresses.jinja
        • blog.jinja
        • category.jinja
        • product.jinja
        • search.jinja
        • account_orders.jinja
        • blogs.jinja
        • faqs.jinja
        • products.jinja
        • shipping_payment.jinja
        • account_profile.jinja
        • cart.jinja
        • questions.jinja
        • wishlist.jinja
    • Settings
      • Sections
      • Input Settings
      • Media Settings
      • Form Controls Settings
      • Products Settings
      • Additional Settings
      • Conditional Visibility
      • Migrating twig settings schema
    • Localization
      • localization (jinja v. twig)
  • Building with Vitrin
    • Jinja Basics
    • Vitrin's Jinja Extensions
    • Objects Reference
  • Vitrin CLI
    • Introduction
    • CLI Commands
  • Tips & Tricks
    • Performance
  • Features
    • Loyalty
    • Bundle Products
  1. Legacy Theme Migration

Twig to Jinja

Overview#

This page notes key equivalents between Twig and Jinja, highlighting important syntax differences and migration tips.

Filenames#

Rename .twig and .html to .jinja

Direct equivalents (filters)#

TwigJinja
rawsafe
json_encode()tojson
filterselect or reject
url_encodeurlencode

Tags converted to filters#

Twig (function)Jinja (filter)
asset_urlasset_url
assetUrlasset_url
strReplacereplace(search, replace)
datetimeFormat(date: string, format: string = 'Y-m-d H:i:s’, locale: string = null)def format_datetime(
datetime: _Instant = None,
format: _PredefinedTimeFormatstr = 'medium',
tzinfo: datetime.tzinfoNone = None,
locale: Localestr
) -> str:
from babel.dates
timeFormat(time: string, format: string = 'g:i a’, locale: string = null)def format_time(
time: datetime.timedatetime.datetime
format: _PredefinedTimeFormatstr = 'medium',
tzinfo: datetime.tzinfoNone = None,
locale: Localestr
) -> str:
from babel.dates
Globals
TwigJinja
requestAdd(query: dict)replace with direct session.url.include_query_params(**params)
requestGetreplace with direct session.query_params.get()
requestUrisession.url.path
requestInputssession.url.params
urlWithQueryreplace with direct session.url.include_query_params(**params)
rangeNuse python’s default range() function
rangeNWithStepuse python’s default range() function
tDate- no equivalent -
- no equivalent -def url_for(
name: str,
*,
localize: bool = True,
query_params: dict[str, str]None = None,
**path_params,
) -> str:
”””
returns a path for the requested operation name
e.g. url_for("list_products")
”””

Data#

TwigJinja
paginated response standardsresponse.data
response.total
response.current_page
…
response.last_page
response.results
response.count
response.page
response.page_size
response.pages_count

Syntax#

descriptionTwigJinjanotes
null safety??or or `default('')`
you can pass true default('', true) to force falsy values (None, '', 0, empty list, False, etc.) as “missing” and substitute with default.
nullNone
create a small, local context for an included template{% include … with {…} only %}{% with … %}
{% include … %}
{% endwith %}
translationslocals.hello_world_(”Hello world”)locals.{something} is not twig syntax but rather a mapping passed in context

Settings Schema#

Move the json contents of the tag {% schema %} to {}_schema.json file with same name. And remove them from the jinja file

Translations#

Rewrite all locals. to _('english text') based on en.json, and then create a .po file with the Arabic translations from ar.json to replace the json files. Then arguments passed to _ function should be moved to string formatting.
Template Conversion:
including or extending vitrin-managed templates need to start with vitrin:{template}
{{ template_for_product_badge }} -> {% include 'vitrin:products/badge.jinja' %}
{{ template_for_product_variants_list }} -> {% include 'vitrin:products/variants_list.jinja' %}
{{ template_for_product_variants_dropdown }} -> {% include 'vitrin:products/variants_dropdown.jinja' %}
{{ template_for_product_payments_widget }} -> {% include 'vitrin:products/payment_widgets.jinja' %}
{{ template_for_product_custom_input_fields }} -> {% include 'vitrin:products/custom_input_fields' %}
{{ account_profile_template_content|safe }} -> {% include 'vitrin:account/profile.jinja' %}
{% include 'vitrin:shared/mazeed_badge.jinja' %}
{{ template_for_cart_products_list }} -> {% include 'vitrin:cart/products_list.jinja' %}
Modified at 2025-08-18 11:55:10
Previous
Moving to Vitrin Using LLMs
Next
Breaking Changes
Built with