8
votes

In Symfony / Twig, I could use tags by using percentages in my translated block. For example:

Hello {{nickname}}

would become

{% trans %}Hello %nickname%{% endtrans %}

This works as expected. The array with placeholders that I pass to Twig, are automatically mapped to %placeHolder%. No extra work involved. So this works with my PHP array from the controller being:

Array('nickname' => 'rolandow')

When I want to use the nickname inside the translation block, all I have to do is surround it with percentages %. Unfortunately, this doesn't seem to work when I pass it to trans.

Now I would like to translate a whole block of text, using tags. I can't figure out how I can use the tags in my translation. So, my twig would look something like this:

{{ say.hello|trans }}

And my translation snippet

<trans-unit id="1">
  <source>say.hello</source>
  <target>Hello %nickName%, how are you doing today? lots-of-text-here</target>
</trans-unit>

I got it working by using this in my template, but it feels like doing things twice. I now need to put the array of placeholder into the trans function again. For example:

{{ say.hello|trans('%nickName%' : nickName) }}

If I want to use other tags that are given to twig in my controller, I need to pass them to the translator as well. Can't I just pass the complete array somehow?

2
Are you actually building an array like $tags = array('%nickname%'=>'luke') in your controller? If so you can just do {{ say.hello|trans(tags) }}Luke
Or declare the tags variable using the Twig set keyword.eagleoneraptor
@Luke, no the array is like array('nickname' => 'luke'). That's actually my point, it feels like redundant coding to run through the array and add the percentages. I was hoping there was a better way to do this. I do realise now that doing this in the controller is a much better place than in the template though.rolandow

2 Answers

2
votes

{{ say.hello|trans('%nickname%': 'rolandow') }}

1
votes

There are several questions here so let's cover them.

1) Twig's behaviour is not like a Doctrine query, where each parameter must be bounded. You can pass an array that contains unused parameters to trans, so if you don't want to specify {'key': 'value', 'key2': 'value2'...} to the filter, just pass the entire array (example: | trans(array)). That's @Luke point.

2) You can translate block of texts using several ways, the most simple is {% set %}. The {% set %} tag can be used two ways :

  • {% set var = expression %} or {% set var1, var2 = expression1, expression2 %} is the most known and used way: you just put some value inside one or several variables.

  • {% set var %} block of text {% endset %} allow you to set an entire block of text inside that variable. This is useful if you want to put that block into a filter (such as, escape, or in your case, trans).

So to translate a block of text, you'll do something like:

{% set variable %}
block to translate %placeholder%
{% endset %}
{{ variable | trans(array) }}

Anyway, I don't see any interest of translating a whole block in one time : we use | trans generally after a property (such as say.hello), and I can't imagine your xlf/yml translation file with such a design. If you want to use the translator just to fulfill placeholders, just use Twig as it is written for that job :-)

3) About replacing placeholder by %placeholder% in your parameters array's keys : the point of Twig is: put what you want as placeholder. In such a way, if your translated sentence contains several %, you can use $something$, #something# or even something as placeholder.

If your array keys does not contain those %, you need to add them, you don't have any choice. If you really want to do it on a Twig file, you can create a macro that will do the job for you, and put it in a file you import in your base layout.

Something like :

{% macro trans_pct(property, params) %}
  {% set newParams = [] }
  {% if params %}
    {% for key, value in params %}
      {% set newParams['%' ~ key ~ '%'] = value %}
    {% endfor %}
  {% endif %}
  {{ property | trans(newParams) }}
{% endmacro %}

And then use it with {{ _self.trans_pct('hello.say', array) | trim }}.

Notes :

  • _self is the template where is stored the macro (see the documentation for more details).

  • trim is used because I wrote the macro with indentation and line breaks (that's cleaner to read). Those spaces are, by default, printed.