Symfony 4 : localized twig date forms - twig

I was used to redefine the date_widget in a form/fields.html.twig file in Symfony 2 and 3 to force twig generated date choices to french order : day month year with this code :
{%- block date_widget -%}
{%- if widget == 'single_text' -%}
{{ block('form_widget_simple') }}
{%- else -%}
<div {{ block('widget_container_attributes') }}>
{{- date_pattern|replace({
'{{ year }}': form_widget(form.year),
'{{ month }}': form_widget(form.day),
'{{ day }}': form_widget(form.month),
})|raw -}}
</div>
{%- endif -%}
{%- endblock date_widget -%}
Now with Symfony 4.4, I get automagicaly this french order in my Linux station. But in the production server, the order is again US standard : month day year. If I redefine this order with the code sample above, I get french order in production server, but US order in my station.
Both systems have the php.ini defining date.timezone = 'Europe/Paris'
Also, the months names are in french and in english according to the month position. So where does TWIG search the locale to define this order?
Thanks

I've found the trick : Twig uses the php-intl extension to localize. This extension was missing in my production server.

Related

Shopware6 Social Shopping: Google Shopping Feed: Varianten template <g:size>

H
I added structured data values such as:
<g:color>, <g:material>.
{% for properties in product.properties %}
{% if properties.group.name == "Kolor" %}
<g:color>{{ properties.name }}</g:color>
{% endif %}
{% endfor %}
{% for properties in product.properties %}
{% if properties.group.name == "Skład" %}
<g:material>{{ properties.name }}</g:material>
{% endif %}
{% endfor %}
, but I don't know how I can add <g:size> from product variants?
First of all you have to enable "Export variants as discrete products" in the settings of your product comparison sales channel.
There are two separate association to properties:
product.properties for general properties, not necessarily variant specific
product.options which define the combination of properties for a specific variant.
You may want to iterate product.options instead.
0
I tried this:
{%- if product.variation -%}
{%- for variation in product.variation -%}
{%- if variation.group == 'Kolor' -%}
<g:color>{{ variation.option }}</g:color>
{%- endif -%}
{%- if variation.group == 'Wymiary' -%}
<g:size>{{ variation.option }}</g:size>
{%- endif -%}
{%- endfor -%}
{%- endif -%}
But it doesn't work
First of all you have to enable "Export variants as discrete products" in the settings of your product comparison sales channel.
There are two separate association to properties:
product.properties for general properties, not necessarily variant specific
product.options which define the combination of properties for a specific variant.
You may want to iterate product.options instead.

Macro causing white space in Jinja2?

I was expecting that this macro
{% macro join_them(first) -%}
{% set data = [] %}
{% if first not in ["", None, "None"] %}
{{ data.append(first) }}
{% endif %}
{% for arg in varargs %}
{% if arg not in ["", None, "None"] %}
{{ data.append(arg) }}
{% endif %}
{% endfor %}
{{' '.join(data)}}
{%- endmacro %}
Would render this
<td> * {{ join_them(docs["Author"]["Name"].title, docs["Author"]["Name"].first, docs["Author"]["Name"].middle, docs["Author"]["Name"].last, docs["Author"]["Name"].suffix) }}</td>
As this line, without the use of the macro, does
<td> * {{ ' '.join([docs["Author"]["Name"].title, docs["Author"]["Name"].first, docs["Author"]["Name"].middle, docs["Author"]["Name"].last, docs["Author"]["Name"].suffix])}}</td>
The non macro version is working fine, and outputing the name information correctly, but the Macro version is putting out white space and some "None" strings.
e.g.
<td> *
None
None
Computer Community
*</td>
<td>Computer Community </td>
Anyone have any suggestions on what I'm missing here? Or a better way to handle this? I don't typically use macros in Jinja2, but this seemed a perfect opportunity to do so.
The macro is indeed causing those blank lines, and you had the right approach already, you need to use whitespace control to remove them. You only placed them at the beginning and the end of your macro but note that:
You can also strip whitespace in templates by hand. If you add a minus sign (-) to the start or end of a block, a comment, or a variable expression, the whitespaces before or after that block will be removed
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#whitespace-control, emphasis, mine
So, for each and every single block in your macro, you have to repeat this operation. To be extra sure, what you could do here is to frame any block in the macro with the minus sign.
Then for the None appearing, this is because you are using an expression delimiter {{ ... }} to append to your array, when you should use a statement delimiter {% ... %} and a do, as pointed in the documentation
If the expression-statement extension is loaded, a tag called do is available that works exactly like the regular variable expression ({{ ... }}); except it doesn’t print anything. This can be used to modify lists
{% do navigation.append('a string') %}
Source: https://jinja.palletsprojects.com/en/3.1.x/templates/#expression-statement
So, your macro should end up looking like:
{%- macro join_them() -%}
{%- set data = [] -%}
{%- for arg in varargs if arg not in ["", None, "None"] -%}
{%- do data.append(arg) -%}
{%- endfor -%}
{{- ' '.join(data) -}}
{%- endmacro -%}
Note that, if you don't have the expression-statement extension loaded, you could also replace the {% do ... %} blocks by this inline-if 'hack':
{{- '' if data.append(arg) -}}

Timber Twig - show elements if date/time is in the present/future

Two part question:
One:
I've used ACf to make some fields for linking to a Zoom meeting, including a date field and a time field, and I want a banner to only show if the date value is equal to or greater than the current date (i.e. today or future) - I've tried:
{% if post.meta('zoom_meeting_date') >= 'now'|date %}
<!-- markup here -->
{% endif %}
This is only working if the date is in the future, not if it is today.
Two: I want a 'join' button that will only show once it is within say 15mins of the start time - no idea where to start with that one!
Any help greatly appreciated!
I suggest using the same date filter without time on both sides of the comparison: |date('m/d/Y')
{% if date("2020-03-30 23:59:59.000000")|date('m/d/Y') >= 'now'|date('m/d/Y') %}
<h1>bang<h1>
{% endif %}
{% if date("2020-03-30 00:00:01.000000")|date('m/d/Y') >= 'now'|date('m/d/Y') %}
<h1>boom<h1>
{% endif %}
{{ 'now'|date }}
{{ 'now'|date('m/d/Y') }}

Twig loop.first not working

I have the following :
{% for field in fields -%}
<div class="item{% if loop.first %} active{% endif %}">
{{ field.content }}
</div>
{%- endfor %}
but it's adding the active class to every field wrapper, rather than just the first which is my intention.
Thanks Darkbee. User malfunction here. The code was in a nested template file ( Drupal ) and the loop I thought I was iterating through was actually in a higher level template file.

How can I use Jinja2 to group articles by date and paginate in Pelican?

I'm using the Pelican static site generator to create a high-volume blog. Pelican themes paginate the index page, showing a list of post titles and summaries, sorting the posts by date. Here's an example of how this is accomplished, from the bootstrap theme:
{% if articles %}
{% for article in (articles_page.object_list if articles_page else articles) %}
<div class='article'>
<h2>{{ article.title }}</h2>
<div class="well small">{% include "metadata.html" %}</div>
<div class="summary">{{ article.summary }} <a class="btn primary xsmall" href="{{ SITEURL }}/{{ article.url }}">more…</a>
</div>
</div>
{% endfor %}
{%endif%}
And here's the also-pretty-standard code for the pagination navigation:
{% if articles_page and articles_paginator.num_pages > 1 %}
<div class="pagination">
<ul>
{% if articles_page.has_previous() %}
{% set num = articles_page.previous_page_number() %}
<li class="prev">← Previous</li>
{% else %}
<li class="prev disabled">← Previous</li>
{% endif %}
{% for num in range( 1, 1 + articles_paginator.num_pages ) %}
<li class="{{ 'active' if num == articles_page.number else '' }}">{{ num }}</li>
{% endfor %}
{% if articles_page.has_next() %}
<li class="next">Next →</li>
{% else %}
<li class="next disabled">→ Next</li>
{% endif %}
Since my site has lots of information to share in a small space--sometimes 20 articles a day--I've written summaries fit in a single line. Instead of listing the date with each post, I'd like the index page to group posts by date, like this:
February 1, 2014
Post 1
Post 2
Post 3
February 2, 2014
Post 1
Post 2
Here's a way to group articles by date with Jinja2:
{% if articles %}
{% for year, year_articles in articles|groupby('date.year')|sort(reverse=True) %}
{% for month, month_articles in year_articles|groupby('date.month')|sort(reverse=True) %}
{% for day, day_articles in month_articles|groupby('date.day')|sort(reverse=True) %}
<dl>
<dt>{{ day_articles[0].date.strftime('%d %B %Y') }}</dt>
{% for article in day_articles %}
<dd>
{{ article.title }}
</dd>
{% endfor %}
</dl>
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
I want to combine these features so that the articles are grouped by date and paginated. So far my admitted-guesswork has failed. I'm using 100 articles to start with, set to show 10 articles per page; in my attempts, the index lists 10 pages of articles but it shows all of the articles on each page. I'd be happy with any working solution. Any ideas how to proceed?
Further thoughts
Maybe instead of all the grouping, a Jinja if-loop could identify the first article listed for that date and write the date, then the linked article title, etc. For all subsequent articles, it would skip printing the date and write the linked article title, etc. I'm not sure how to do that, and that if-loop would still have to avoid knocking the paginator off its game. But if it works, creating a nice-looking list is a CSS job instead of a Jinja job.
Use the dates_page variable instead of articles, see details here: http://pelican.readthedocs.org/en/latest/themes.html#index-html
dates_paginator A paginator object for the article list, ordered by date, ascending.
dates_page The current page of articles, ordered by date, ascending.
Probably far too late to be helpful, but I'm sharing because I just spent an evening fighting with this and finally got it working in Pelican 4.2. I'm not grouping by individual date, but this should still work with an extra inner loop for the day:
{% for year, year_group in dates_page.object_list|groupby('date.year')|reverse %}
{% for month, month_group in year_group|groupby('date.month')|reverse %}
<h1>{{ (month_group|first).date|strftime('%B %Y') }}</h1>
{% for article in month_group %}
... do stuff with individual article here ...
{% endfor %}
{% endfor %}
{% endfor %}
{% if dates_page.has_other_pages() %}
{% include 'pagination.html' %}
{% endif %}
The key thing is to the start outer loop with dates_page.object_list; dates_page provides the paged list of articles ordered by date, and object_list is the iterable that provides the actual list of articles used by the template. Other examples I was trying to use omitted object_list and causing various errors.
The block of code at the bottom loads the pagination template as needed.

Resources