KNP Menu Bundle Translation Domain - symfony

I'm using Symfony 2.3 and the KnpMenuBundle.
Is it possible to use a translation domain for menu items?
Like this:
$menu['management']->addChild(
'msg.user.list',
array(
'route' => 'user_list',
'translation_domain' => 'navigation'
)
);

According to the Symfony documentation and KnpMenuBundle documentation,you may set the translation domain (menu in my snippets), while adding menu items in your MenuBuilder class:
$menu->addChild('Home', array('route' => 'homepage'))
->setExtra('translation_domain', 'menu');
You may better want to add the translation domain into the whole menu instead:
$menu = $this->factory->createItem('root')
->setExtra('translation_domain', 'menu');
Then create a file named knp_menu.html.twig in:
app/Resources/views/menu/
and put this in it:
{% extends 'knp_menu.html.twig' %}
{% block label %}
{% if options.allow_safe_labels and item.getExtra('safe_label', false) %}
{{ item.label | raw | trans(item.getExtra('translation_params', {}), item.getExtra('translation_domain', 'menu'))}}
{% else %}
{{ item.label | trans(item.getExtra('translation_params', {}), item.getExtra('translation_domain', 'menu')) }}
{% endif %}
{% endblock %}
(If the file already exists, just replace the {% block label %}{% endblock %} part)
Be carefull to have translation files (.xliff or whatever) naming strategy like:
{translation_domain}.{locale}.{extenstion}
for example:
menu.fa.xliff
In this path:
app/Resources/translations/
The last part is:
# app/config/config.yml
knp_menu:
twig:
template: knp_menu.html.twig
Up-Vote this nice tutorial.
Have fun!

Related

Symfony ChoiceType deep label customization

I want to customize my EntityType's choice labels highly, like creating a table with multiple attributes of my model.
So I want to access my choices class attributes. The choices are my entities of class MyClass through the EntityType. How can I do so in twig?
Currently I do it like this:
1. in my FormClass I json_encode all fields I need in my label
2. in my template I json_decode these information and display according
IN CODE:
1.
$builder
->add('field', EntityType::class, [
'class' => MyClass::class,
'multiple' => false,
'expanded' => true,
],
'choice_label' => function (MyClass $myClass) {
$data = [
'name' => $myClass->getName(),
'description' => $myClass->getDescription(),
];
return json_encode($data);
},
])
2.
{% block my_form_widget %}
...
{# form is my 'field' FormView of the EntityType #}
{% for child in form %}
{# child is a FormView, one choice of my EntityType #}
{# child.vars.data is boolean as its a checkbox #}
{% set data = child.vars.label|json_decode %}
create some complex html here, like tables
...
{% endfor %}
...
{% endblock %}
Working. But is there a better way?
Thanks,
Kim
In a Symfony form (or form field, which is just a form of its own) that is mapped to an entity, you always have access to the underlying data in form.vars.data. So in this case, form.vars.data would either be null or an instance of MyClass.
For ease of use in your template, you might do something like:
{% set my_object = form.field.vars.data %}
{% if my_object %}
{{ my_object.getName() }}
{{ my_object.getDescription() }}
{% endif %}
Thus there is no need to re-encode your entity data for the view layer, since it's always already available.
If you are working with an EntityType and want to access the properties of each choice's entity, they are available as well in the choices array:
{% for choice in form.field.vars.choices %}
{{ choice.data.getName() }}
{{ choice.data.getDescription() }}
{% endfor %}
A nice trick when you're trying to access any form data and aren't sure where to look is to temporarily add a line to your template like:
{{ dump(form.field) }}
This will allow you to look through the available data and see what all is available. Note that it requires the Twig debug extension to be enabled, and XDebug to be enabled in PHP in order to make the output look nice.
Ok I got it, here is an example of how to access the data of your EntityType's choices in twig. You can check the child.parent.vars.choices list.
{% block my_form_widget %}
...
{# form is my 'field' FormView of the EntityType #}
{% for child in form %}
{# child is a FormView, one choice of my EntityType #}
{# child.vars.data is boolean as its a checkbox #}
{% for choice in child.parent.vars.choices if choice.value == child.vars.value %}
{{ choice.data.name }} {# contains MyClass name #}
{{ choice.data.description }} {# contains MyClass description #}
{% endfor %}
...
{% endfor %}
...
{% endblock %}

Symfony - easyAdmin changing 'list.row_actions'

Currently I'm using Symfony 3 and implementing Easy Admin backend.
By default, the label available show as something like 'list.row_actions'.
I have read the documentation for Easy Admin, and manage to edit certain label such as Edit and Delete.
But come to confusion why I cannot edit the 'list.row_actions on the list table header.
The same problem I have with the Edit page, specifically the buttons:
Here is some of the configurations I add into config.yml under easy_admin tree:
config.yml
list:
actions:
- { name: 'new', label: 'New' }
- { name: 'search', label: 'Search' }
- { name: 'edit', label: 'Edit' }
- { name: 'delete', label: 'Delete' }
After several tweaking and failures, I have found a solution, it was documented but I did not expect it to be documented there nested.
Here's the github page: Advanced Design Configuration
We will overwrite the default html.twig file by overriding the {{ block }}
Create an Overwrite Folder
First, create a folder easy_admin inside Resources\views.
Suppose you want to change list.row_actions, head over to the source file from easy-admin usually inside:
vendor\javiereguiluz\easyadmin-bundle\views\includes\ In the last version
Finding the source
Find the list.html.twig file and check out its content for a brief. If you CTRL + F (Find) for list.row_actions, it will show you directly something like this. Now copy the whole block
{% block table_head %}
<tr>
{% for field, metadata in fields %}
{% set isSortingField = metadata.property == app.request.get('sortField') %}
{% set nextSortDirection = isSortingField ? (app.request.get('sortDirection') == 'DESC' ? 'ASC' : 'DESC') : 'DESC' %}
{% set _column_label = (metadata.label ?: field|humanize)|trans(_trans_parameters) %}
{% set _column_icon = isSortingField ? (nextSortDirection == 'DESC' ? 'fa-caret-up' : 'fa-caret-down') : 'fa-sort' %}
<th data-property-name="{{ metadata.property }}" class="{{ isSortingField ? 'sorted' }} {{ metadata.virtual ? 'virtual' }} {{ metadata.dataType|lower }} {{ metadata.css_class }}">
{% if metadata.sortable %}
<a href="{{ path('easyadmin', _request_parameters|merge({ sortField: metadata.property, sortDirection: nextSortDirection })) }}">
<i class="fa {{ _column_icon }}"></i>
{{ _column_label|raw }}
</a>
{% else %}
<span>{{ _column_label|raw }}</span>
{% endif %}
</th>
{% endfor %}
{% if _list_item_actions|length > 0 %}
<th>
<span>{{ 'list.row_actions'|trans(_trans_parameters, 'EasyAdminBundle') }}</span>
</th>
{% endif %}
</tr>
{% endblock table_head %}
Pasting to Overwrite File
To paste/overwrite this, you need to create a file with exact name as the filename where you copied it. In this case, list.html.twig. Then paste it inside the file
IMPORTANT : At top of the file, include this tag -
{% extends '#EasyAdmin/default/list.html.twig' %}
{% block table_head %}
<tr>
{% for field, metadata in fields %}
...code continues...
Why overwrite?
If you edit the file from the source code, you will have trouble deploying it especially if you're using git clone and then composer update.
Overwriting make sure that the code persist even when you deploy it.
I've had the same issue. As for me, I fixed it easier.
First of all try to use this
# app/config/config.yml (Symfony3)
# config/packages/framework.yaml (Symfony4)
framework:
translator: { fallbacks: "%locale%" }
But if you want to override with your translation, create this file:
# translations/EasyAdminBundle.en.yaml
list.row_actions: "My actions"

Symfony Twig exception

I am trying to use a HTML table bundle:
https://github.com/ekyna/TableBundle
Here is the calling code:
$table = $this->get('table.factory')->createBuilder(
new InventoryType(),
['name' => 'project_inventory_list']
)->getTable($request);
$content = ['content_area' => $table->createView()];
return $this->render('MyProjectBundle:Default:index.html.twig', $content);
I am getting an exception:
An exception has been thrown during the rendering of a template
("Catchable Fatal Error: Object of class
Ekyna\Component\Table\TableView could not be converted to string") in
MyProjectBundle:Default:index.html.twig at line 6.
Stepped through code not sure whats going on - hoping it's a trivial issue???
| EDIT
{% extends 'mYThemeBundle:layout:base-layout.html.twig' %}
{% block title %}HEADER{% endblock %}
{% block page_content %}
{{ content_area }}
{% endblock %}
In your TWIG template, you have to do the following:
{% extends 'mYThemeBundle:layout:base-layout.html.twig' %}
{% block title %}HEADER{% endblock %}
{% block page_content %}
{{ ekyna_table_render(content_area ) }}
{% endblock %}
You need to use the TWIG function ekyna_table_render to render the table view.
After installing EkynaBundle (documentation was not up to date) I also needed to adjust the template as demonstrated above in addition to:
Install and enable WhiteOctoberPagerfantaBundle
Install and enable BraincraftedBootstrapBundle
Install twig extensions
Install and enable LiipImagineBundle
Thanks for all the help.

Unable to override KnpMenuBundle template

With ...MyBundle\Resources\views\Menu\knp_menu.html.twig, deleting the </li> has no effect on the rendered menu. (Removing the tag is done to remove the space between inline list elements.) I have followed the advice provided in this answer, including the {% import 'knp_menu.html.twig' as knp_menu %} mentioned toward the bottom of that post. Is this because knp_menu.html.twig already extends knp_menu_base.html.twig? Or what?
layout.html.twig:
...
{{ render(controller('VolVolBundle:Default:userMenu')) }}
...
userMenuAction:
$user = $this->getUser();
$tool = $this->container->get('vol.toolbox');
$type = $tool->getUserType($user);
return $this->render(
'VolVolBundle:Default:userMenu.html.twig', array('type' => $type)
);
userMenu.html.twig
...
{% if type is not null %}
{% set menu = "VolVolBundle:Builder:"~type~"Menu" %}
{{ knp_menu_render(menu) }}
{% endif %}
The answer was found deep in here. All that's required to do a global override of the template is to modify config.yml.
config.yml:
...
knp_menu:
twig: # use "twig: false" to disable the Twig extension and the TwigRenderer
template: VolVolBundle:Menu:knp_menu.html.twig
...

Link in form label using route

In my registration form i have a checkbox "I accept the terms", and want to link the word "terms" to my terms page.
Is there a way to add a link to a form label, using a route? (preferably without injecting the container in the form)
As the solution above somehow didn't work for me I solved it using the solution suggested here: https://gist.github.com/marijn/4137467
OK, so here i how I did it:
{% set terms_link %}<a title="{% trans %}Read the General Terms and Conditions{% endtrans %}" href="{{ path('get_general_terms_and_conditions') }}">{% trans %}General Terms and Conditions{% endtrans %}</a>{% endset %}
{% set general_terms_and_conditions %}{{ 'I have read and accept the %general_terms_and_conditions%.'|trans({ '%general_terms_and_conditions%': terms_link })|raw }}{% endset %}
<div>
{{ form_errors(form.acceptGeneralTermsAndConditions) }}
{{ form_widget(form.acceptGeneralTermsAndConditions) }}
<label for="{{ form.acceptGeneralTermsAndConditions.vars.id }}">{{ general_terms_and_conditions|raw }}</label>
</div>
The best way is to overwrite the twig block used to render that specific label.
First, check the form fragment naming section of the docs. Then create a new block in your form template with the the appropriate name. Don't forget to tell twig to use it:
{% form_theme form _self %}
For the next step check the default form_label block.
You'll probably only need a portion of it, something like this (I'm leaving the default block name here):
{% block form_label %}
{% spaceless %}
<label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
{{ label|trans({}, translation_domain) }}
</label>
{% endspaceless %}
{% endblock %}
As an option, you can do so:
->add('approve', CheckboxType::class, [
'label' => 'Text part without link',
'help' => 'And download it',
'help_html' => true,
])
In Symfony 5.1 there are new form improvements.
HTML contents are allowed in form labels!
HTML contents are escaped by default in form labels for security reasons. The new label_html boolean option allows a form field to include HTML contents in their labels, which is useful to display icons inside buttons, links and some formatting in checkbox/radiobutton labels, etc.
// src/Form/Type/TaskType.php
namespace App\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
// ...
->add('save', SubmitType::class, [
'label' => ' Save',
'label_html' => true,
])
;
}
}
In your case you can set form label directly from template and pass the route there.
{{ form_widget(form.acceptTermsAndConditions, {
label: '' ~ "I accept ..."|trans ~ '',
label_html: true
})
}}
My solution was another:
form:
$builder
->add(
'agree_to_rules',
'checkbox',
[
'required' => true,
'label' => 'i_agree_to'
]
);
And html:
<span style="display:inline-block">
{{ form_widget(form.agree_to_rules) }}
</span>
<span style="display:inline-block">
rules
</span>
And looks the same :)
A very simple way to do it would be
{{ form_widget(form.terms, { 'label': 'I accept the terms and conditions' }) }}
You can also do this if you want to use translation
In your translation file for example messages.en.yml add
terms:
url: 'I accept the terms and conditions'
And in your view add
{{ form_widget(form.terms, { 'label': 'terms.url'|trans({'%url%': path('route_to_terms')}) }) }}

Resources