Pass variables to Twig Translator - symfony

In messages.en.yml:
variable_name: Welcome to %site_name% - %other_info%
In Twig
{{ 'variable_name'|trans( -here- ) }}
It's the -here- part I'm struggling to know how to pass data in. I must do it this way (above is just an example).

Maybe I'm misunderstanding the question but if I understand correctly, you only need to give an array as the first parameter of the trans filter.
{{ 'variable_name'|trans({'%site_name%': 'My Website'}) }}
And of course, values can be variables if you don't put them between quotes :
{{ 'variable_name'|trans({'%site_name%': 'My Website', '%other_info%': page_name}) }}

Related

call twig function from custom twig function

I created a custom twig function in AppExtension Class. I need to call form_label() from this new function. ¿Is it posible? I tried but does not work:
from template I call:
{{ myFunc(form.someField) }}
public function myFunc( $field )
{
$html = form_label($field);
}
The idea is to render each form field in a different order/way than the form_widget(form) twig function. The "form_label()" function it's not reconized.
Thx for any suggestion.
I feel like this is the wrong approach to handle this. Extensions are for transforming data not really to manipulate the form definition itself.
First of all the order is defined as in the form type, so you can swap those around. To render the fields differently you can use form themes, or even rendering a custom form type.
Alternatively if its a one time thing (you could also create a macro for this) you can also instead of form_widget(form) order them in the way you like.
{{ form_start(form) }}
{{ form_row(form.field3) }}
{{ form_row(form.field1, { attr: { class: 'im-different' } }) }}
{{ form_row(form.field2) }}
{{ form_end(form) }}
Or even go deeper.
{{ form_start(form) }}
{{ form_row(form.field3) }}
<div>
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
{{ form_errors(form.field1) }}
</div>
{{ form_row(form.field2) }}
{{ form_end(form) }}
To see these functions and how they all rendered by default you can look at form_div_layout.html.twig.
I agree with Jenne van der Meer and Nico Haase that your approach isn't particularly optimal. If I had the choice, I would go a different route: Instead of rendering in your function, render in twig, then pass the result to the function (like {{ myFunc(form_label(form), form) }}). Since you omit what your function actually needs and/or does, it's hard to provide further advice. However, I'm absolutely sure, that rendering can be done in twig before or after entering your function, via a macro/block, maybe even a form theme).
However, if you really really require your function to render the form field ... the following will possibly help you. I strongly advise against doing this, there's probably a better suited solution.
The form_label function is slightly more complex than a simple function. Instead, it uses twig's compile mechanisms to generate specific php code. It will eventually call:
FormRenderer::searchAndRenderBlock(FormView $view, string $blockNameSuffix, array $variables = [])
Diving deep into the compiler, the template call form_label(form, options) would be turned into:
$this->env->getRuntime('Symfony\Component\Form\FormRenderer')->searchAndRenderBlock(
$form, 'label', $options
);
where the $this->env seems to be the twig environment. That means, to call this in your twig extension you need to have access to the proper Twig environment, and then it should already work with the recipe I just provided. Especially if you can omit the options argument, I didn't take a deeper look into how that one's assembled (but it's probably just straight forward).
So your twig function must be defined via:
public function getFunctions(): array
{
return [
new TwigFunction('myFunc', [&$this, 'myFunc'], [
'needs_environment' => true, // <--- this!
'is_safe' => ['html'],
]),
];
}
public function myFunc(\Twig\Environment $env, $field) {
// other stuff
$html = $env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(
$field, 'label', $options
);
return $html;
}

Translate the value of twig variable

Is it possible to translate the value of twig variables in a template with the 'trans' tag?
Say for instance I am passing a product to my template. This product has a definition with a trans tag e.g {{ product.definition|trans }}. This definition could either be in EN or DE or some other language. How could I translate the definition.
What are you trying to do is not a good way, It would look like this:
messages.en.yml
product:
definition:
some_value1: Some value 1
some_value2: Some value 2
and in template, you would do something like this:
{% set definition_value = product.definition %}
{% set trans_definition = 'product.definition.' ~ definition_value %}
{{ trans_definition|trans }}
it'll work, if it finds the key. What if it cant find it?
That's why you should use DoctrineBehaviors from KnpLabs, which handles all the dynamic translations for you..
If {{ product.definition }} equals 'cellphone' the following should work.
message.language.yml:
'cellphone': This will work!
However if you want to map it with the 'product' key in your message file like this:
product:
'cellphone': This also works
add the key to the twig template like so:
{{('product.'~product.definition)|trans }}

How to apply Twig filters to form_label(form.name), e.g. 'capitalize'?

My problem concerns just applying Twig filter inside a form without getting a 500 server error. Here is the code, which is in the view 'Room/new.html.twig':
{{ form_label(form.name) }}
or
{{ form_label(form.name, 'room.name') }}
Both will output: 'nom de salle' ('room name' in French). That is because, in my translation file 'messages.fr.yml', I have:
room.name: "nom de salle"
Also, I activated the translation in my form type 'RoomType.php' with this code:
->add('name', 'text', array(
'label' => 'room.name'
))
I tried every possible combination I thought of with |capitalize and got either a 500 server error or no change at all. Some examples:
{{ form_label(form.name)|capitalize }}
{{ form_label(form.name, 'room.name'|capitalize) }}
and so many more...
Does anyone know how to do it, it doesn't seem to be in the Symfony doc. Of course, I thought about duplicating the translation to have one in lower case and one starting with a capital letter but that would defeat the object. Plus there are other Twig filters I would like to use with this form_label() function.
Help greatly appreciated, thank you.
I just found the solution. It's so easy that it is embarrassing. I thought I didn't need the |trans as it was already translated but without it, 'room.name' = 'nom de salle' would transform to 'Room.name' instead of 'Nom de salle'. So the correct code is just:
{{ form_label(form.name, 'room.name'|trans|capitalize) }}

Passing all parameters as array and changing one of them

I am passing an array of get arguments from controller to twig template, and then create a link:
{{ url('route_name', array_of_get_parameters) }}
It works, but what if I want to pass all BUT ONE of those parameters unchanged? Something like:
{{ url('route_name', array_of_get_parameters, {'param1': 'value'}) }}
The example above doesn't work of course...is there a way to do this?
Use twig merge filter like this:
{{ url('route_name', array_of_get_parameters|merge({'param1': 'value'})) }}
You cannot do this.
Instead override the value in the controller (<- better) or in the twig template, before the url generation.

Keep leading 0 in Twig

In my database, I have a field containing the following data : 000010 (the type is integer)
In my twig tpl, I want to display it, then I do : {{ spending.documentName }}
But the browser displays "10". As if Twig was automaticcaly performing a trim on my data.
I tried {{ spending.documentName|raw }} but it doesn't work. I dont find anything on Google about how to keep leading 0 with Twig.
Does anyone know how to proceed ?
I think you must force the format (as your type is integer).
You can use the format filter :
{{ "%06d"|format(spending.documentName) }}
Or better create a twig extension (http://symfony.com/doc/current/cookbook/templating/twig_extension.html):
public function strpad($number, $pad_length, $pad_string) {
return str_pad($number, $pad_length, $pad_string, STR_PAD_LEFT);
}
It's clearer in your template :
{{ spending.documentName | strpad(6,'0') }}
You need to use the format filter.
Since placeholders follows the sprintf() notation, you should be able to convert sprintf('%06d', $integer); in PHP to {{ '%06d'|format($integer) }} in Twig.
Kinda late here, but ran into the same.
With twig 3.x you can use:
{{your.number | format_number({min_integer_digit:'2'})}}

Resources