I've implemented the Jmsi18nRountingBundle in my symfony2 application : symfony2: how to parameter localization so we can have 2 languages?
I thought it was it but now that I have started making some translations, I realize that the locale used to translate the text surrounded by the trans tag in twig varies in a single template.
See the ouput of the profiler :
Any idea of what might be causing this ?
In my template, I have the following code:
{# src/FoodMeUp/CoreBundle/Resources/views/Default/header.html.twig #}
{% trans_default_domain 'header' %}
<header>
<section id="toprow" class="greybg">
<ul class="wrapperext">
<li id="startup_button">
{% trans %}howto{% endtrans %} <span>{% trans %}start{% endtrans %} </span><i class="fa fa-question-circle"></i>
</li>
<li id="top_row_message" class="padding-h">{{ socialButtons({url: 'home', padding: false , facebookLike : { layout : 'button_count'}, facebookShare : { layout : 'button_count'}, twitter : { count : 'horizontal'} , googleplus : { annotation: 'bubble'} }) }}</li>
</ul>
</section>
<section id="header_content" class="padding-v whitebg clearfix">
<div id="pres" class="wrapper fmu_flex space-between center">
<h2 class="align_left">{% trans %}description.left.normal{% endtrans %} <strong>{% trans %}description.left.strong{% endtrans %}</strong>...</h2>
<a id="logo" href="{{ path('home') }}"><img src="{{ asset('images/foodmeup_horizontal_w280.png') }}" alt="logo Foodmeup" class="margin-auto block"></a>
<h2 class="align_right">...{% trans %}description.right.normal{% endtrans %} <strong>{% trans %}description.right.strong{% endtrans %}</strong> {% trans %}description.right.normal2{% endtrans %}</h2>
</div>
{% if isAuthenticated() == false %}
<div id="create_account_button" class="wrapper align_center">{% trans %}create.account{% endtrans %}</div>
{% endif %}
</section>
</header>
and I have two files for my translations, header.fr.xlf and header.en.xlf :
en :
howto: 'How to'
start: 'start'
connect: 'Connect'
description.left.normal: 'FoodMeUp is a platform of'
description.left.strong: 'services'
description.right.normal: 'dedicated to'
description.right.strong: 'professionals'
description.right.normal2: 'of the food industry'
create.account: 'Create your account in one minute'
fr:
start: 'démarrer'
howto: 'Comment'
connect: 'Connexion'
description.left.normal: 'FoodMeUp est une plateforme de'
description.left.strong: 'services'
description.right.normal: 'dédiée aux'
description.right.strong: 'professionnels'
description.right.normal2: 'des métiers de bouche'
create.account: 'Créez votre compte en 1 minute'
EDIT 1:
I have figured out this might be a priority issue of my locale listener.
If I set the priority to 17, then the locale stays the same for the template. This is because there is a translation listener of priority 10 which changes the locale with the request default value for the locale, which is actually set by the locale listener by reading the session value.
I still have different locales for a given template and the one generated with render(controller())... investigating this.
Found the solution, ouf, this is what follows my edit.
In addition to adding a priority of 17 to my locale listener,I neeeded to make sure it also handled subrequests.
See the corrected code here : symfony2: how to parameter localization so we can have 2 languages?
Related
I'm trying to check through Twig if there is a request in order to show the results of my searchBar, in Twig, ONLY if there is a request.
I found old symfony docs on app.request, but it doesn't seem to work for my 5.2 Symfony Project (here is my twig template) :
{% if app.request %}
<h3 class="main-header_h3">Résultats de la recherche</h3>
<hr>
<div class="grid">
{% for product in products %}
{% include 'product/_card.html.twig' with {product: product} only %}
{% endfor %}
</div>
<hr>
{%endif %}
Problem here is that my {% if app.request %} isn't being interpreted, so I get my whole product database coming on my view.
If you need any more code, let me know (Controller/Repository...) but the request definitely works, it's just my rendering in Twig that gives me trouble using that if.
Thanks to #bechir, the solution to checking if my URL has a 'search' parameter in it using TWIG is :
{% if app.request.query.get('search', null) %} where search is the
url parameter. (from : bechir)
So this is what it now looks like, and I do have my partial product/_card.html.twig loaded only when there's a URL parameter search:
{% if app.request.query.get('search', null) %}
<h3 class="main-header_h3">Résultats de la recherche :</h3>
<hr>
<div class="grid">
{% for product in products %}
{% include 'product/_card.html.twig' with {product: product} only %}
{% endfor %}
</div>
<hr>
{% endif %}
I'm building an e-commerce site based on WooCommerce and use Timber (Twig) for templating. I'm now trying to build a page (e.g. domain.com/sale) which lists all my Products, that are on sale. Since I totally customized the entire WooCommerce template structure (because I'm templating in Twig), shortcodes are not an option.
My Problem:
I managed to build a custom query showing my products on sale, but it seems I'm missing something, since no pagination is shown in the bottom, neither my AJAX Filters are working.. and so on.. Probably because I'm not calling the default query? Even if I go the non-AJAX-way: domain.com/sale/page/2 it will return me the same results I already get on the first page. literally not changing anything...
What I did:
I created a page in my Wordpress named "Sale". Went to my index.php and added the following code:
<!-- index.php -->
$products = Timber::get_posts(
array(
'post_type' => 'product',
'nopaging' => false,
'posts_per_archive_page' => '24',
'meta_query' => array(
'relation' => 'OR',
array( // Simple products type
'key' => '_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
),
array( // Variable products type
'key' => '_min_variation_sale_price',
'value' => 0,
'compare' => '>',
'type' => 'numeric'
)
)
)
);
$context['products'] = $products;
Timber::render( '/pages/landingpages/sale.twig', $context );
In my option this totally works fine. And of corse this is surrounded with correct if clauses to call when domain.com/sale is requested. I now went to my sale.twig file and added following code:
sale.twig
$context = Timber::get_context();
{% block content %}
<div id="product_list" class="product_listing grid">
{{ fn('woocommerce_breadcrumb', breadcrumb_settings) }}
<h1>Sale</h1>
<div id="product_list" class="product_listing grid">
{# Filters #}
<div class="product_filter">
{{ fn('do_shortcode', '[br_filters_group group_id=7861]') }}
</div>
{# Order by #}
<div class="product_sorting">
<label for="orderby">Order by:</label>
{{ fn('woocommerce_catalog_ordering') }}
</div>
{# Products #}
<div class="product_listing-content">
<ul class="product_results products">
{% for product in products %}
{% include ('partials/loop-product.twig') %}
{% endfor %}
</ul>
<div class="products-footer">
{% include 'partials/pagination.twig' %}
</div>
</div>
</div>
</div>
{% endblock content %}
At this point I must say that I'm using BeRocket AJAX Filters for my Filters. The included files loop-product.twig and pagination.twig look like this:
loop-product.twig // deleted some lines for simplicity
<li id="{{ 'product-' ~ product._sku }}" class="product-item {{ product._stock_status }}">
{{ product.name }}
</li>
pagination.twig
<ul class="pagination clearfix">
{% if posts.pagination.prev %}
<li class="prev-item">
<a href="{{posts.pagination.prev.link}}" class="prev {{posts.pagination.prev.link|length ? '' : 'invisible'}}">
<span class="sr-only">Prev</span>
</a>
</li>
{% endif %}
{% for page in posts.pagination.pages %}
<li class="page">
{% if page.link %}
{{page.title}}
{% else %}
<span class="{{page.class}}">{{page.title}}</span>
{% endif %}
</li>
{% endfor %}
{% if posts.pagination.next %}
<li class="next-item">
<a href="{{posts.pagination.next.link}}" class="next {{posts.pagination.next.link|length ? '' : 'invisible'}}">
<span class="sr-only">Next</span>
</a>
</li>
{% endif %}
</ul>
Again to not get me wrong: I'm receiving all my products in a correct way. My problem is that it is not behaving like an archive page. Pagination, Filters etc.
Maybe there is total different approach to this topic, but it seems it is the only one. I found tuns of code snippets online with similar problems, but non of them suited for me...
Any help appreciated!
Edit:
For testing only I tried to add the common WooCommerce shortcode [sale_products] and at-least my filters work again. My Pagination still does not appear...
I am going to take a stab at helping. Please forgive me if I am off base. The gutenburg blocks is still very hard for me to grasp.
Your sale.twig is dynamically pulling data and using JS to fill content via a php include but it never actually writes the content via the WP hooks to the database that the /sale page or post is pulling the data from. Is that intentional?
Also note the twig js that is supposed to provide you the pagenation from the dom does not match the dom created via link_template.php
have a look
I kind of think you will have to call this
<?php previous_post_link( '<strong>%link</strong>' ); ?>
link_template
I am currently working on a small personal project to learn how to manipulate Symfony and Sonata, and I find myself confronted with a small problem. I have constrained one of my variables to a "template" in "configureListFields" but I can not submit it to "editable". I can do the one without the other but not both at the same time if not the "editable" bug as I show you a bit further down.
List :
$listMapper->add('status', 'string', array(
'template' => 'WebBundle:Default:list_client.html.twig',
'label'=> 'Status'))
Form :
$formMapper->add('Status', 'choice', array(
'choices' => array(
'Client' => 'Client',
'Ex-Client' => 'Ex-Client',
'Prospect' => 'Prospect')))
Template :
{% extends 'SonataAdminBundle:CRUD:base_list_field.html.twig' %}
{% block field %}
<div>
<p class="ClientStatus {% if object.Status == 'Ex-Client' %}
label label-danger
{% elseif object.Status == 'Client' %}
label label-success
{% else %}
label label-info
{% endif %}" >
{{ object.Status }}
</p>
</div>
{% endblock %}
View with that config :
Second config :
$listMapper->add('status', 'choice', array(
'choices'=>array(
"Client"=>"Client",
"New Client"=>"New Client",
"Ex-Client"=>"Ex Client"
),
'label'=> 'Status',
'editable'=>true))
View :
Third Config :
->add('status', 'choice', array(
'choices'=>array(
"Client"=>"Client",
"New Client"=>"New Client",
"Ex-Client"=>"Ex Client"
),
'template' => 'WebBundle:Default:list_client.html.twig',
'label'=> 'Status',
'editable'=>true))
view :
So there seems to be a conflict between "template" and "editable" opinions on how to handle this problem ?
Thanks a lot.
check out the list_choice template that is provided with the Sonata sources.
# SonataAdminBundle/Resources/views/CRUD/list_choice.html.twig
{% set is_editable =
field_description.options.editable is defined and
field_description.options.editable and
admin.hasAccess('edit', object)
%}
{% set x_editable_type = field_description.type|sonata_xeditable_type %}
{% if is_editable and x_editable_type %}
{% block field_span_attributes %}
{% spaceless %}
{{ parent() }}
data-source="{{ field_description|sonata_xeditable_choices|json_encode }}"
{% endspaceless %}
{% endblock %}
{% endif %}
They check if the field is editable and add data-source attribute to the field_span_attributes block of the parent base_list_field template part:
<span {% block field_span_attributes %}class="x-editable"
data-type="{{ xEditableType }}"
data-value="{{ data_value }}"
data-title="{{ field_description.label|trans({}, field_description.translationDomain) }}"
data-pk="{{ admin.id(object) }}"
data-url="{{ url }}" {% endblock %}>
{{ block('field') }}
</span>
So try adding the data-source in your custom template as well.
This answer worked for me:
If you check the HTML code, on your element choice, of your site you can detect if any tag is missing, for example the code below is the code that generate the page without the 'template' option configured:
<span class="x-editable label-info editable editable-click editable-open" data-type="select"
data-value="Rechazado"
data-title="Estado"
data-pk="4"
data-url="/eventos/web/app_dev.php/admin/core/set-object-field-value?context=list&field=estado&objectId=4&code=admin.evento"
data-source="[{"value":"Aprobado","text":"1"},{"value":"Pendiente","text":"Pendiente"},{"value":"Rechazado","text":"Rechazado"}]" data-original-title="" title="" aria-describedby="popover786605">
</span>
And now check the code generated when the 'template' option is on set
<span class="x-editable label label-danger editable editable-click"
data-type="select"
data-value="Rechazado"
data-title="Estado"
data-pk="4"
data-url="/eventos/web/app_dev.php/admin/core/set-object-field-value?context=list&field=estado&objectId=4&code=admin.evento">
</span>
The data-source field is missing and that is the reason why its crash.
The solution is simple (isn't the best but it is something) on your template add the data-source with the data of your choice.
I'm improving my web application by adding more languages. I've done it following this tutorial: https://coderwall.com/p/eiqd_g
Everything seemed to work fine, but now I've figured out that when trying to create a new post on the forum (HerzultForumBundle), I get the above exception.
I can see in the debugger:
in kernel.root_dir/cache/dev/classes.php at line 8422
function twig_array_merge($arr1, $arr2)
{
if (!is_array($arr1) || !is_array($arr2)) {
throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
}
return array_merge($arr1, $arr2);
}
at twig_array_merge (null, array('_locale' => 'en'))
in kernel.root_dir/cache/dev/twig/c7/1/9188032d83474dae4ab5fad0cdaf278f4614c031cf7a5531428c5812bd57.php at line 200
echo ">
\t <a href=\"";
// line 81
echo twig_escape_filter($this->env, $this->env->getExtension('routing')->getPath($this->getAttribute($this->getAttribute((isset($context["app"]) ? $context["app"] : $this->getContext($context, "app")), "request"), "get", array(0 => "_route"), "method"), twig_array_merge($this->getAttribute($this->getAttribute((isset($context["app"]) ? $context["app"] : $this->getContext($context, "app")), "request"), "get", array(0 => "_route_params"), "method"), array("_locale" => (isset($context["locale"]) ? $context["locale"] : $this->getContext($context, "locale"))))), "html", null, true);
echo "\">";
echo twig_escape_filter($this->env, (isset($context["locale"]) ? $context["locale"] : $this->getContext($context, "locale")), "html", null, true);
echo "</a>
So it seems like the twig_array_merge() function is getting a null value as first parameter. And the HerzultForumBundle:Topic:new.html.twig template seems to be the cause.
The HerzultForumBundle:Topic:new.html.twig template holds the below code:
{% extends 'HerzultForumBundle::layout.html.twig' %}
{% block title %}New Reply{% endblock %}
{% block content %}
<div class="forum post_new">
<ul class="crumbs">
<li>Forum</li>
<li>{{ topic.category.name }}</li>
<li>{{ topic.subject }}</li>
<li>New Reply</li>
</ul>
<div class="main">
<h2>New Reply</h2>
<form action="{{ url('herzult_forum_topic_post_create', { 'slug': topic.slug, 'categorySlug' : topic.category.slug }) }}" method="post">
{{ form_widget(form) }}
<div>
<button type="submit" name="reply">Add post</button>
</div>
</form>
</div>
<div class="side">
<p>Back to the topic</p>
</div>
</div>
{% endblock %}
My guess is that the exception comes from this line:
<form action="{{ url('herzult_forum_topic_post_create', { 'slug': topic.slug, 'categorySlug' : topic.category.slug }) }}" method="post">
But don't know how to solve it. Any idea? The forum was working perfectly before.
Well, here was my problem, in the base template:
<ul id="languages">{% for locale in ['en', 'fr', 'es', 'de'] %}
<li {% if locale == app.request.locale %}class="active"{% endif %}>
{{ locale }}
</li>
{% endfor %}
</ul>
So figured that app.request.get('_route_params') was null. I tried:
<ul id="languages">{% for locale in ['en', 'fr', 'es', 'de'] %}
<li {% if locale == app.request.locale %}class="active"{% endif %}>
{% if app.request.get('_route_params') %} {{ locale }}{% endif %}
</li>
{% endfor %}
</ul>
And yes! It works. I won't have translations on the forum but never mind, I think it's pretty understandable in english.
I had a similar bug "The merge filter only works with arrays or hashes in ..." in the template. whatever line it was, whatever change i did the line of the error moved but the message remained the same..
It appeared after I added i18n compatibility to my site only on the page where there was a form.
the reason was me using a ->forward() to another template depending on the presence of error or not.
So this error is indeed linked to routing problem.
I ended up rendering the template instead of forwarding to another page.
I am working on a PHP project using Symfony2 with Twig templating, and I can't find a solution for this problem.
I have an admin bundle and all the templates extend from admin base which has a master template with a menu.
I need to set the current tab of the menu in the base template of the page to selected when the user is on that page.
Is there any way to pass parameter to the base template through extends?
Here is a simple example:
base.html.twig:
{# base.html.twig #}
...
<ul>
<li{% if menu_selected|default('one') == 'one' %} class="selected"{% endif %}>One</li>
<li{% if menu_selected == 'two' %} class="selected"{% endif %}>Two</li>
<li{% if menu_selected == 'three' %} class="selected"{% endif %}>Three</li>
</ul>
...
page2.html.twig:
{# page2.html.twig #}
{% extends 'YourBundle::base.html.twig' %}
{% set menu_selected = 'two' %}
Output from rendering page2.html.twig:
<ul>
<li>One</li>
<li class="selected">Two</li>
<li>Three</li>
</ul>
A better way that I just discovered is the basic approach by checking the route for the shortcut route name:
<li class="{% if app.request.attributes.get('_route') == 'homepage' %}active{% endif %}">Home</li>
Or another way is to name all your route shortcut names according to the group it belongs to. For example all the routes from your products controller start with "product_...." and then in the template you can do this:
<li class="{% if app.request.attributes.get('_route') starts with 'product' %}active{% endif %}">