Problem/Motivation
Noticed in #2226493: Apply formatters and widgets to Node base fields. Right now you get warnings and errors.
Right now {% trans %} only allows strings to be passed in and using render arrays is not possible. Being able to use render arrays in node.html.twig would allow us to simplify template_preprocess_node().
Proposed resolution
Change this line:
$compiler->string($token->getAttribute('placeholder'))->raw(' => ')->subcompile($token)->raw(', ');
in TwigNodeTrans.php
API changes
Allows common values to be rendered in Trans tag.
Before
After
Comment | File | Size | Author |
---|---|---|---|
#91 | interdiff_89-91.txt | 772 bytes | ravi.shankar |
#91 | 2334319-91.patch | 5.84 KB | ravi.shankar |
#89 | 2334319-89--9.5.x.patch | 5.85 KB | DuaelFr |
Issue fork drupal-2334319
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
joelpittetTranslation is trying to avoid dealing with complex objects. There are comments to that effect. Can we render the render array before providing it the trans block's context?
It's intended to work as the t() does as much as possible and same for t() it won't render a Renderable Array. If we do need to support render arrays in trans (which I kinda hope we don't). Maybe we should do that at the t() level?
Comment #2
joelpittetIs this the error you are getting BTW?
TwigTransTokenParser:105?
Or am I wrong in that assumption?
Comment #3
BerdirNope, I got warnings from checkPlain(), so it apparently it is passing it right through.
I don't really agree with your argumentation :) t() does not and IMHO should not treat render arrays specially because nothing on the PHP side does. There you need to know if you have a render array, an object or a string. You can't do 'some string' . $render_array anywhere.
However, isn't twig supposed to hide those differences? If it would be a different syntax inside a trans element then it might make sense, but it is the same {{ something }} that handles render arrays just fine outsided. @effulgentsia also assumed that it would work, see his comments in the referenced issue.
Comment #4
joelpittetSo you do agree with my argument:) That's what I'm saying :P We shouldn't treat render arrays specially. I just mentioned that an option, though I don't agree it's the right way and would be undone when we go Renderable Objects in the future.
Twig does hide those difference by finding print statements
{{ var }}
and wrapping that fromprint $var;
toprint twig_render_var($var);
Which internally finds render arrays and calls drupal_render() on them.But inside trans block it was prevented from using complex objects and filters because it was tricky for whomever was writing it to deal with all the cases.
It is a bit confusing as those tokens look like print, so I agree it's a bit confusing. Actually a good person to get some context on this would me @Mark Carver. Let's see if he can shed some light.
Comment #5
star-szrComment #6
Fabianx CreditAttribution: Fabianx commentedAll we need to do here is replace t($x) with t(twig_render_var($x)) in the output.
I am not worried about the performance impact anymore, which would be the only reason _not_ to do this ...
This should be a simple search+replace patch and some little work on tests.
Comment #7
Wim LeersThis problem came up in #2450993-140: Rendered Cache Metadata created during the main controller request gets lost.
Comment #8
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedHere is a start.
Comment #9
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedComment #11
Wim LeersIs this still actually a problem? I'm not sure I fully understand what the issue is about.
Comment #12
star-szrYeah definitely needs an IS update. I think the issue is that if fluffy_kittens is a render array, this doesn't work:
Comment #13
Fabianx CreditAttribution: Fabianx at Tag1 Consulting commented#12 is correct.
Comment #14
calebtr CreditAttribution: calebtr commentedPer IRC chat with joelpittet, I'm changing #8 to remove the ::escapeFilter method and use ::renderVar() instead
Comment #16
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedFixed wrong argument.
Comment #18
joelpittetComment #19
xjmThanks for tagging this for rc target triage! To have committers consider it for inclusion in RC, we should add a statement to the issue summary of why we need to make this change during RC, including what happens if we do not make the change and what any disruptions from it are. We can add a section
<h3>Why this should be an RC target</h3>
to the summary.Comment #20
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedSo so far i removed some unneeded arguments that were left over from escapeFilter() and added test for render array. Looking for some feedback on improving this.
Comment #21
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedComment #23
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedLets see what this breaks.
Comment #24
slashrsm CreditAttribution: slashrsm at MD Systems GmbH commentedFew comments. 1. and 2. from my IRC discussion with @chx.
dont break the scalar optimization
can we use " instead of \' ?
Let's not introduce unrelated changes.
Comment #25
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedFixes from #24
Comment #26
dawehnerThis is super odd ... given that this invalidates a lot of documentation of the method. Now the __toString() method is no longer called
Comment #27
dawehnerAh actually the behaviour is right, that interface is already markup, so it should not be cast to a string, as this looses information.
What about doing something like escapeFilter() which is :
so also check for
\Twig_Markup
?Comment #28
slashrsm CreditAttribution: slashrsm at MD Systems GmbH commentedComment #29
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedremoved one more unrelated change and added
\Twig_Markup
Comment #30
dawehnerIMHO a dedicated test for
render($MarkupInterfaceObject),/code> would be nice
Comment #31
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedAdded test for markup.
I found later TwigExtensionTest where i could have added the check, don't have enough time now.
Comment #32
dawehnerMH, that feels wrong, I thought more about using render_var() directly?
Comment #33
thenchev CreditAttribution: thenchev at MD Systems GmbH commentedRemoved the last test for markup and added a new one that directly tests if renderVar is returning the markupinterface obj.
Comment #34
joelpittetThank you @Denchev
Has tests for renderable arrays and
FormattableMarkup
(forMarkupInterface
).I'll add a change record.
Comment #35
joelpittetHere's a CR: https://www.drupal.org/node/2615198
Comment #36
andypost@joelpittet please provide example what will work in CR because now it confusing
Comment #38
joelpittet@andypost That example worked when I tried the CR example. Which part is confusing?.
Before:
After:
I just chucked the snippets in bartik's
bartik_preprocess_node()
andnode.html.twig.
Comment #39
andypostRTBC++
@joelpittet sorry, looks I misread "s/now/not" - thanx a lot for screens, added to summary
Comment #40
alexpottGiven that #2226493: Apply formatters and widgets to Node base fields got fixed without this I'm not sure this is a bug. As far as I can see we should only put this into 8.1.x. The patch seems to be missing documentation and a change record.
Comment #41
xjmhttps://www.drupal.org/node/2615198 was just missing the reference to this issue so I added that.
Asked @alexpott what he meant about needing documentation and he clarified that there is no update to API documentation. Setting NW for that.
Comment #42
xjmI was also wondering if it makes sense for markup objects and render arrays to be lumped together in this issue? It seems like in general we have an expectation that markup objects should be usable anywhere we would use a string in rendering, but that render arrays are another whole can of worms (which is why #2505497: Support render arrays for drupal_set_message() was not accepted).
Comment #43
BerdirThis issue started as support for render arrays, it existed before we had markup objects :)
Yes, render array are a different thing on the PHP side. But that's not true for Twig templates. You can do {{ whatever }} with anything, almost anywhere. Isn't it kind of the goal that themers don't have to know about render arrays?
I'm fine with pushing this to 8.1.x. But note that #2226493: Apply formatters and widgets to Node base fields had to use drupal_render() in preprocess to avoid this. That's very hard to understand for themers and it's also inefficient, we render those things all the time, even if we don't use them in the template. That said, I guess these days you could also use whatever|render but that's not exactly straight forward either :)
Comment #44
joelpittet+1 to #43.
I'd like Twig to deal with render arrays when printing in all cases.
Comment #45
lauriii+1 for making #43 in a follow-up!
Comment #46
lauriiiWe have CR, latest patch applies still so I think this is RTBC.
Comment #47
alexpottLooking at this I still feel it is missing documentation - however looking at this the only place where
{% trans %}
is in core/lib/Drupal/Core/Language/language.api.php and I'm not sure this is appropriate for there. We're missing a place to put documentation for how Drupal integrates with Twig and our customisations - we should have a place to document things like|without
and{% trans %}
. So let's not try and add this here.I guess we should also file a followup to remove the
drupal_render()
added totemplate_preprocess_node()
in #2226493: Apply formatters and widgets to Node base fields.I've thought a lot about security implications of this patch and I don't think it changes anything even though we've changed
TwigExtension::renderVar()
. That said I think we should improve the@return
documentation ofTwigExtension::renderVar()
. Currently it is:I think it should it is either a scalar, MarkupInterface or Twig_Markup.
Comment #49
andypostComment #50
andypostStill need to address #47
Comment #51
agoradesign CreditAttribution: agoradesign commentedIf this change will be committed, is there a chance to push it to 8.1.x too? It seems, that Entity API will need this work -> https://github.com/fago/entity/pull/38. If yes, than I guess only before rc1 in 2 weeks...
I don't know, if there's a possible workaround within Entity API. I only fear the following scenario:
Commerce 2.x (that will be a very important D8 module) depends on 8.1.x as well as on Entity API 1.x. Currently, the pull request for making Entity API 1.x fit for 8.1.x, only passes tests, when the patch from this issue is applied => neverending patching and patch re-rerolling until 8.2.x is released
Comment #52
BerdirAs commented over there, the fact that the entity module relied on this is a bug, a bug that is fixed in the Pull request that you linked.
It would still be very nice to see this fixed, but this does not block entity or commerce in any way.
Comment #53
agoradesign CreditAttribution: agoradesign commentedThanks 4 clarifying. I've mixed up the two patches/issues you mentioned in the PR. @bojanz already told me in a Commerce issue thread. However, I agree that this one looks also very useful in general.
Comment #56
joelpittetHere's a review
This line shouldn't be needed at all. In the line below
if (is_object($arg)) {
condition it should be covered by the__toString()
check that is already in there which covers both the interface and theTwig_Markup
.nit: can we put
<strong>
for html5?Comment #57
joelpittetHere's the changes I mentioned in #56, had to change the test because it was expecting the object though
renderVar
will render it as the method name suggests.Tested locally and it seems to work, let the testbot double check.
Comment #60
joelpittetHmm I'll dig in deeper into the fails, it looked like that was needed, thanks for automated test coverage.
Comment #61
star-szrJust attempting a reroll of #57, no changes.
Comment #63
joelpittetSorry I fell in a rabbit hole and then saw a bunny. Thanks for picking this up @Cottser
Comment #65
paul_canning CreditAttribution: paul_canning commentedAny update on this issue?
Looks like the latest patch failed for 8.4.
Comment #67
darvanenComment removed. Sorry, wrong issue.
Comment #69
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer and at Appnovation for Pfizer, Inc. commentedRerroll of #61
Comment #71
Manuel Garcia CreditAttribution: Manuel Garcia as a volunteer and at Appnovation for Pfizer, Inc. commentedReferencing the "drupal_core" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.
Attempting to fix these errors...
Comment #76
golddragon007 CreditAttribution: golddragon007 at European Commission and European Union Institutions, Agencies and Bodies, Petend commentedIt's not possible still to use |function on a variable within trans...
Comment #80
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedRe-roll #71.
Comment #82
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #86
DuaelFrRerolled #82's patch on D9.5 and fixed tests (I hope)
(This patch applies on 9.4 too)
Comment #88
DuaelFrRerolled on 10.1.x
Comment #89
DuaelFrI should have trusted @webflo in the first place :)
Bringed back the code I removed in #86 and fixed tests accordingly.
The attached patch is for people that needs this for D9 right now.
Comment #91
ravi.shankar CreditAttribution: ravi.shankar at OpenSense Labs commentedTried to fix the failed test of patch #89.