Symfony ICU translation trailing newline after the translated message - symfony

I followed the official Symfony documentation on how to translate messages using the new ICU message format.
Inside the messages+intl-icu.pl.yaml file I have the following entry:
pages:
show:
ratings_title: Opinie
ratings_count: >
{count, plural,
=0 {brak opinii}
one {jedna opinia}
few {# opinie}
other {# opinii}
}
Which is consumed as follows:
<div>
<h1>{{ 'pages.show.ratings_title'|trans }}</h1>
<sub>({{ 'pages.show.ratings_count|trans({'count': count}) }})</sub>
</div>
Which results in:
<div>
<h1>Opinie</h1>
<sub>(brak opinii
)</sub>
</div>
While the expected output should be:
<div>
<h1>Opinie</h1>
<sub>(brak opinii)</sub>
</div>
So my question is: how to remove that trailing newline character after the translated message?

Ok this was simply due to misconfigured YAML file. In order to strip YAML's trailing newline inside a multi-line string I should have written the translation entry as follows:
pages:
show:
ratings_title: Opinie
ratings_count: >-
{count, plural,
=0 {brak opinii}
one {jedna opinia}
few {# opinie}
other {# opinii}
}
Notice the use of >- instead of >

Related

Dynamically generate / omit HTML attribute in Twig

I want to generate a div with a specific HTML attribute present or absent in it, in function of if a variable my_var has been defined or not. If it has been defined, its value should be used as the according attribute.
my_var is either not defined or equal to a value consisting of several words separated by a space (software needs these, I know it's not usual...).
I've tried the following:
<div class="container" {{ my_var ? "data-my-var='" ~ {{ my_var }} ~ "'" : ""}}>
</div>
But this escapes the quotes I use and yields sth like this in my output, with my_var = hello there how are you:
<div class="container" data-my-var="hello there how are you">
</div>
This does not change when I escape the quotes using
"data-my-var=\"" ~ {{ my_var }} ~ "\""
instead of what's written above.
I've also tried to simply omit the quotes, so do sth like:
"data-my-var=" ~ {{ my_var }}
which resulted in the attribute data-my-var being output with no quotes whatsoever; hence only recognizing the first word of the value of my_var.
So how can I reach what I want?
Variables and concatenations with variables are not marked as safe by default. You will need to apply the filter raw to mark the output as safe. Also you can omit the second part if you just return an empty string
<div class="container"{{ my_var ? (' data-my-var="' ~my_var ~ '"')|raw }}>
</div>
demo
Another method, as commented by #Bossman is to use an {% if ... %}{% endif %}

for in twig templates of drupal is behaving strangely

I am trying to show only upcoming events from a list of events. Below is how I have tried to display.
<div class="row">
{% for item in items %}
{% if item.content['#node'].field_event_type.getValue()|first.value == 'upcoming' %}
<div class="col">{{item.content}}</div>
{% endif %}
{% endfor %}
</div>
But the output rendering is, the second event is displaying after the row div like below. I don't understand how this is happening as the for loop is inside the row div
<div class="row">
<div class="col"> content </div>
</div><div class="col"> content </div>
Expected output
<div class="row">
<div class="col"> content </div>
<div class="col"> content </div>
</div>
Twig does lots of things:
loading (open your Twig content)
parsing (create a parse tree from your Twig content)
compiling (browse that tree to create a php file)
caching (store the php file somewhere to avoid recompile it next time)
executing (execute the generated php file)
When a {% for %} is detected during parsing, Twig calls the token parser recursively until it finds {% endfor %} and builds a token tree. In your case, it would look like:
root
|
--- string
|
--- for
| |
| --- if
| |
| --- string
|
--- string
Then, Twig compiler crosses over that tree recursively and generates the corresponding php code. In that way, the following Twig loop:
{% for i in 1..5 %}
Value = {{ i }}
{% endfor %}
Compiles to this in PHP:
// line 1
$context['_parent'] = $context;
$context['_seq'] = twig_ensure_traversable(range(1, 5));
foreach ($context['_seq'] as $context["_key"] => $context["i"]) {
// line 2
echo "Value = ";
echo twig_escape_filter($this->env, $context["i"], "html", null, true);
}
$_parent = $context['_parent'];
unset($context['_seq'], $context['_iterated'], $context['_key'], $context['i'], $context['_parent'], $context['loop']);
$context = array_intersect_key($context, $_parent) + $_parent;
As you can see, a {% for %} is no more than a simple foreach and as Twig tokens are stored into a tree, it is by design not possible to display contents located below a pair of open/close tags.
The only possibility I can see is that one of the tag you're using in Twig is playing with output buffering, and one of the methods you're using in your loop breaks the ob stack (like a ob_get_clean() without any ob_start() for example, that have been open previously).
My advice is to grep your twig file name into your cache directory (eg: grep -Ri 'test.twig' cache/) in order to see that file compiled to PHP, to understand exactly what it does, and debug it.
Instead of filtering your content in twig, filter the results in your Drupal view.
In the "filter criteria" on your view, select the field_event_type field and set it "is equal to" and select/add 'upcoming' as the option.
If you filter in the view, you don't have to mess with the twig template.

Symfony2 twig translate string containing colon

How can I translate string containing colon in symfony2 using twig? Here's what I have:
Inside twig template:
{% trans with {'%order_no%': order_no} %}Loading offer: %order_no%...{% endtrans %}
Inside translation file:
Loading offer: %order_no%...: Įkeliamas užsakymas %order_no%...
As expected this doesn't work. How can I make it work?
You need to use quotes around the text as such:
'Loading offer: %order_no%...': Įkeliamas užsakymas %order_no%...
edited to show the correct example.

In TWIG, is possible to get absolute url of a link with twig variables in it?

I have several URLs that look as follows:
{{domainID}}/action/{{userId}}/anotherAction
And the latter URL points to:
http://localhost/viewA/{{domainID}}/action/{{userId}}/anotherAction
However, If I try to load viewA from viewB through an iframe, the link inside viewA instead of pointing to:
http://localhost/viewA/{{domainID}}/action/{{userId}}/anotherAction
it will point to:
http://localhost/viewB/{{domainID}}/action/{{userId}}/anotherAction
and the user will end up in a 404 page if it follows the latter.
My question is:
Is there anyway to get the absolute path of a url built that way in twig?
EDIT
The route definition is:
#Route("/domain/details/{domainId}", name="domain_detailed_view")
I tried to get the absolute path this way:
{{ url({{domainID}}/action/{{userId}}/anotherAction) }}
but I get this error:
A hash key must be a quoted string, a number, a name, or an expression
enclosed in parentheses
The url or path functions take the route name, not the path. You can give it an associative array as an optional second argument if the route requires parameters.
For example:
{{ url('domain_detailed_view', { 'domainId': domainId, 'userId': userId }) }}
http://symfony.com/doc/master/reference/twig_reference.html
I know it's old and answered, but with symfony 3 & twig you can do:
{{ app.request.getSchemeAndHttpHost() }}
/* will match even port :) i.e.
* http://localhost:8000
* http://localhost
* http://example.com
*/
which is extremely helpful :D
You have two ways to do the same thing.
Generally you could use url() or path inside absolute_url function like so absoulute_url(path(...)). Consider the following:
// example 1:
{{ url('domain_detailed_view', { 'domainId': domainId, 'userId': userId }) }}
// example 2:
{{ absolute_url(path('domain_detailed_view', { 'domainId': domainId, 'userId': userId })) }}">
// note - those two do the same thing
Generally since Symfony 2.7 you could use absolute_url() with asserts and relative path also (relative to web/root folder). This is how you could use them to set absolute path to image in bundle and in main web folder:
[app/src/UserBundle/Resources/public/img/image.jpg]
<img src="{{ absolute_url(asset('bundle/user/img/image.jpg')) }}" /> // new way since 2.7 up
<img src="{{ asset('bundle/user/img/image.jpg', absolute: true ) }}" /> // old way below 2.7 removed in symfony 3.0
[web/css/img/some.jpg]
<img src="{{ absolute_url('css/img/some.jpg') }}" />
This is what symfony recommends to use while rendering email view.
http://symfony.com/doc/current/email.html

Symfony2 : Auto htmlentities using Twig

I'm displaying some variable retrieved in my database using Twig :
<p>{{ my_variable }}</p>
The thing is this variable may contain html tags, such as "<br />".
Twig seems to automatically call some htmlentities-like function when displaying variables.
Is there any way to disable it so that when I display a variable containing "Hello<br />world !" I get :
Hello
world !
rather than :
Hello<br />world !
Thanks
Use {{ my_variable|raw }} to prevent my_variable from being automatically escaped.
See Twig documentation: http://twig.sensiolabs.org/doc/filters/raw.html
Try using this
{% autoescape false %}{{ my_variable}}{% endautoescape %}
even better: {{ '<br />|raw('html') }} to avoid unescaping other sensible stuff.
If you just want to use linebreaks in the text stored in your database but don't care to use html , you can also use the nl2br filter as in {{ var|nl2br }}. Allows you to use string linebreak character \n in your text. Filter converts it to <br/>

Resources