37

In messages.en.yml, I have

confirmed: Congrats %username%, your account is now activated.

But I want to 'bold' username to example ... how can I made this ?

confirmed: Congrats <span class='bold'>%username%</span>, your account is now activated.   

Of course I could use two sentence in this example like

first: Congrats
second: , your account ... 

and inside twig use the html tag but this seems very dirty.

Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
Lukas Lukac
  • 7,766
  • 10
  • 65
  • 75

10 Answers10

28

Update 2

In such cases, I started to use like this:

confirmed: Congrats %start_link%%username%%end_link%, your account is now activated

Since separation of concerns is maintained, this way is strongly recommended.


Update

In YAML, I have used translations like this without any problem:

trans.key: click <a href="%url%">here</a> to continue

Although translations and design should be kept separated there are always some situations that you must use html tags inside translation files as it is also seen in huge projects like Facebook and Twitter.

In such situations, you can use XLIFF format which is being recommended by Symfony. Inside translation file:

<trans-unit id="1">
   <source>confirmed</source>
   <target>Congrats <![CDATA[<span class='bold'>%username%</span>]]> , your account is now activated.</target>
</trans-unit>
Darryl Hein
  • 142,451
  • 95
  • 218
  • 261
seferov
  • 4,111
  • 3
  • 37
  • 75
  • Hm... i like the yml heh so for this time i will separete them into two sentences but THX for this info! To future it will come handly probably :) This is the answer i was looking for. – Lukas Lukac Feb 15 '13 at 10:13
  • 12
    You can use the raw filter to show the htmlspecialchars correctly `{{ 'key'|trans|raw }}` – Rvanlaak Sep 10 '13 at 09:51
12

Twig's Raw Filter

I don't know if this was an option back in 2013 but when using translation, you can apply the raw twig filter having this translation string:

confirmed: Congrats <span class='bold'>%username%</span>, 
           your account is now activated.

And use it in twig like this:

 {{ 'confirmed'|trans|raw }}

This will not escape the html inside the string and will display the username as bold.

Update: I haven't seen the comment the first time, but Rvanlaak had proposed the raw filter solution in the first place.

Security issues

Note that the content of those translation strings must not be user provided, because it could open up your application to XSS attacks. Using the raw filter allows JavaScript to be executed if a malicious user is able to input custom data into the translation strings (Community based translations for example)

Separation of concerns

Using the raw filter does not comply with separation of concerns as the content and styling are bound together. As Ferhad mentioned, using his method, separation of concern will be maintained. But in my case, I preferred using a simple raw filter. I felt that for my case, Ferhad's method was a bit overkill for me, though it would be more recommended his way

Lunfel
  • 2,499
  • 21
  • 29
6

My approach is although still ugly, but at least respects the separation of concerns. Escape filter is used to escape a variable, making the final result is pretty safe from XSS, because all other sources considered to be hard-coded.

  • translations.yml

    points: You have %num% points left.
    
  • template.html.twig

    {% set pointsFormatted = '<span class="points">' ~ num | escape ~ '</span>' %}
    {{ 'pages.score.points' | trans({'%num%' : pointsFormatted}) | raw }}
    
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
4

I've just found something out, you can use this in your YAML file:

    mind: >
        <i>Mind is a nice thing to have</i>

So this ">" sign in the first row achieves it. I think this would be the preferred way, better than handling the escapes etc in TWIG.

I've looked it up now and it is actually a YAML feature. Check here :)

Also, there's an earlier question with similar subject: How can I get YAML to ignore raw HTML in same file.

Community
  • 1
  • 1
userfuser
  • 1,350
  • 1
  • 18
  • 32
  • It does not work (tested in Symfony 5.0) and I think it's a good thing as it probably shouldn't. **Twig** is responsible for the XSS protection, not the **YAML**, that's why many solutions use the `raw` filter. Maybe it worked in earlier versions but not anymore. – AymDev Sep 16 '20 at 16:22
1

some yml:

dashboard:
    hello: Hello <b>%username%</b>

+

{{ 'dashboard.hello'|trans({'%username%': app.user.username}, 'General') | raw }}

this | raw part worked for me

maciejolsz
  • 46
  • 5
1

In my opinion, this is the best solution today:

'key'|trans({'%username%': '<strong>' ~ suspiciousVar|escape ~ '</strong>'})|raw

The only risk here is stored XSS in your translation files.

ibram
  • 140
  • 1
  • 11
0

Holding HTML stuff in translations is wrong, because translators usually break it. But if you really need it:

Twig:

{% trans %}confirmed{% endtrans %}

Yaml translation file:

confirmed: 'Congrats <span class="bold">%username%</span>, your account is now activated.'

Discussion about this: https://github.com/symfony/symfony/issues/2713

Artem L
  • 10,123
  • 1
  • 20
  • 15
0

We could use separate twig snippets for different languages if situation requires heavy formatting differences. I wrote a little blog on this.

{# templates/translations/user_message.pl.html.twig #}
{{ 'msg.my_favourite_language_is' }}<b>{{ 'langnames.elfic_language' | trans | lower }}</b>!

{# templates/translations/user_message.en.html.twig #}
{{ 'msg.my_favourite_language_is' }}<i>{{ 'langnames.elfic_language' | trans | ucfirst }}</i>!

{# templates/pages/index.html.twig #}
{% set locale=app.request.locale[:2] %}
{% include 'translations/calculator_message.' ~ locale ~ '.html.twig' %}
kshishkin
  • 525
  • 5
  • 7
  • Tjhe structure of a sentence can change with the locale. What if in arab (in example) the structure is 'Elfic is my favourite language.' – goto Oct 15 '19 at 08:21
0

If you face same problem but in form help section. Help texts are automatically translates but also escapes htmls. To disable it

$form->add('phone', null, [
     'help_html' => true,
     'help' => 'some_content_includes_html',
])

Yml:

some_content_includes_html: yes i have <br><h1>inside</h1>

To see more: https://symfony.com/doc/current/reference/forms/types/form.html#help-html

Mehmet Gökalp
  • 314
  • 3
  • 6
-1

Translation files are for translations, design and layout is part of the view layer (namely: template engine (twig)). You can split it into two pieces: congrats and account.activated.

KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • 10
    In practice this solution is insufficient because for some text in some languages the the translation might not be literal or the pieces might be in a different order. – redbirdo Jun 18 '15 at 18:40