0

I'm using the https://api.drupal.org/InlineTemplate to render a string with a variable, and that variable is itself another theme function.

My reading of the documentation is that this is supported; based on the fact that the #context variable can be a string or render array.

#context: (array) The variables to substitute into the Twig template. Each variable may be a string or a render array.

However, my implementation is not working:

    $my_subtemplate = [
      '#type' => 'inline_template',
      '#template' => '{% trans %}my {{ foo }} here{% endtrans %}',
      '#context' => ['foo' => 'bar'],
    ];

    $my_string_with_embedded_themable = [
      '#type' => 'inline_template',
      '#template' => '{% trans %}Print this string and this subtemplate: {{ my_subtemplate }}.{% endtrans %}',
      '#context' => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];

The generated output is:

Print this string and this subtemplate: .

I've confirmed that my_subtemplate generates the correct output on its own:

my bar here

But when its placed into a variable of another inline template, it does not render.

  • 1
    Even if this worked it would not be a valid use case for interface translation, which is supposed to be used for string constants and not for strings after variable placeholders got replaced. And in inline templates defined in PHP you don't need Twig methods to translate because you can use t(). – 4k4 Dec 29 '19 at 18:56
  • I get your point that you could use t(), but otherwise, this comment ^ doesn't make sense. The example in the core documentation linked above uses the trans Twig function, and the trans Twig functions itself supports variables as placeholders, for position purposes. IMHO the bug here is that the trans Twig function doesn't support render array variable expansion, while other Twig functions do, eg spaceless. – JamesWilson Dec 29 '19 at 19:32
  • Regarding position purposes, I mean 'Hello {{name}}' might be translated in another language by putting the name first, so the translation in some other language would be '{{name}} ASDF' (where ASDF is the translation of Hello). – JamesWilson Dec 29 '19 at 19:37
  • To make it work I would use t() instead of renderRoot. Depending on where you place this code it is bad for caching and attachments or can cause a nested renderRoot error. – 4k4 Dec 29 '19 at 20:23
1

The issue not in the inline_template but the issue comes from {% trans %} if you place a render array variable into {% trans %}{% endtrans %} you will get the following error and it will not rendered:

Warning: htmlspecialchars() expects parameter 1 to be string, array given in Drupal\Component\Utility\Html::escape()

So you have two options:

1) get the variable out of {% trans %}{% endtrans %} like the following:

    $my_subtemplate = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} my {{ foo }} here {% endtrans %}',
      '#context'  => [
        'foo' => 'bar'
      ],
    ];
    $my_string_with_embedded_themable = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} Print this string and this subtemplate: {% endtrans %} {{ my_subtemplate }} .',
      '#context'  => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];

2) Pre-render the renderable array variable to a string first.

    $my_subtemplate = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} my {{ foo }} here {% endtrans %}',
      '#context'  => [
        'foo' => 'bar'
      ],
    ];

    $renderer = \Drupal::service('renderer'); 
    $my_subtemplate = $renderer->renderRoot($my_subtemplate); // this fixes it

    $my_string_with_embedded_themable = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} Print this string and this subtemplate: {{ my_subtemplate }}.{% endtrans %}',
      '#context'  => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];
|improve this answer|||||
  • 1
    wow, that is very interesting. Thanks for the quick response. I've added a comment to the documentation (link in OP) and expanded your answer to provide the other alternative -- to render the renderable to string first. – JamesWilson Dec 29 '19 at 18:22
  • 1
    You are welcome, i'm glad that helped, great i read your comment in documentation, good job! – berramou Dec 29 '19 at 18:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.