Problem/Motivation
In #2114069: Routing / tabs / actions lack way to attach context to UI strings we are adding context to UI strings to handle the case of ambiguous items like "Extend" and "Views". However tabs / routes / actions may also equally need title replacement values. The menu system supported these so this is a regression that we only allow static strings. This results in problems that derivative tab titles, eg. 'Translate @type' don't work, where we'd derive @type from elsewhere. See #2119497-9: Default local tasks are not to be assumed $route_name . '_tab' point 1.
Proposed resolution
Add support for replacement arguments that routes/tabs/actions would be able to provide. This will round out the arguments of t() to be supported.
Remaining tasks
- Commit.
User interface changes
None.
API changes
- Local tasks / local actions / contextual links get a new title_arguments key that is an optional array of key-value pairs
- Routes get a new _title_arguments key (in defaults) that is an optional array of key-value pairs
These can be used to provide static title arguments for replacement after translation (as in Drupal 7 - resolves the Drupal 7 regression). Additional title arguments are added from the request raw variables as well.
Related Issues
#2114069: Routing / tabs / actions lack way to attach context to UI strings
Comment | File | Size | Author |
---|---|---|---|
#40 | interdiff.txt | 6.51 KB | dawehner |
#40 | title-2120235-40.patch | 15.33 KB | dawehner |
#37 | title-2120235-37.patch | 18.28 KB | dawehner |
#33 | title-2120235-33.patch | 18.17 KB | dawehner |
#33 | interdiff.txt | 5.89 KB | dawehner |
Comments
Comment #1
Gábor HojtsyRegression should be a bug.
Comment #2
Gábor HojtsyPostponed on #2114069: Routing / tabs / actions lack way to attach context to UI strings.
Comment #3
Gábor Hojtsy#2114069: Routing / tabs / actions lack way to attach context to UI strings landed.
Comment #4
Gábor HojtsyTagging for sprint.
Comment #5
dawehnerTechnically we can already do that if you override the class need for contextual links but yeah I agree that this should be part of the actual system, if D6/D7 supported it as well.
Comment #6
Gábor HojtsyThanks a lot! I *thought* that allowing for @ placeholders only may be an issue, especially given D7 did not have any limitation like that:
But then again, this was for many things not "just" tabs/routes/etc. I did not find any processing of title arguments from the data returned in the hook to serializing it in the db in _menu_router_save(). So in D7 you could use @, ! or % equally. I think % would look pretty out of place in a contextual link or tab, but ! *may* be needed if you are working with already processed data. Allowing the full placeholder name would also have a transparent API without magic.
Is the concern that this will be harder to encode in YAML? Quotes needed around the keys due to the special chars? I think the use case of title placeholders in static YAML's is *minimal* if not nonexistent, since if you have a static tab/route, etc. you can just include the text in the title, right? :) Any other concerns with using the full placeholder name?
Comment #7
Gábor HojtsyNow #2084463: Convert contextual links to a plugin system similar to local tasks/actions landed, that needs coverage as well :)
Comment #8
Gábor Hojtsy#2130075: Config translation should work with new contextual links API demonstrates how we lost this functionality on contextual links (that was used by config_translation :).
Comment #9
dawehnerWell yeah we could scan the title for used "tokens" and than replace the values with the available request attributes.
Comment #10
Gábor Hojtsy5: title_parameters-2120235.patch queued for re-testing.
Comment #13
dawehnerIt seems to be that something like this could already work.
Comment #14
dawehner13: title-2120235-13.patch queued for re-testing.
Comment #15
Gábor HojtsyThe changes look good, thanks for working on this @dawehner. The only thing to note with the patch seems to be missing coverage for contextual links at this point. :) Looks RTBC except that :)
Comment #16
dawehnerOh right, good point.
There we go.
Comment #18
dawehner16: title-2120235-16.patch queued for re-testing.
Comment #20
dawehnerups.
Comment #21
tstoecklerCould you explain how one would go about using this?
Using the example of 'Translate @type' from the issue summary it is not immediately clear to me how I would make the 'type' that I want end up in the request variables.
Also it is not super problematic but a bit unfortunate that this approach seemingly does not support translating 'This is escaped: @title, this is not escaped !title' (i.e. multiple placeholders of different type with the same name). I don't know any use-case for that I just think it's unfortunate that t() actually supports that but this does not. Perhaps that should be documented somewhere?
Comment #22
Gábor Hojtsy@tstoeckler:
1. I think you can add arbitrary (static) request variables in the routing.yml file's defaults section. That is not a very creative use case, because then you can just as well include that in the title itself (since it would be static). However, for dynamically defined routes, you can add the placeholder values which are replaced later on in title translation. That means #2134077: Subclass contextual links and local tasks to have dynamic title can mostly be rolled back and we should be able to rely on this. I did not explicitly check the defaults values all end up in _raw_variables. I could not verify that with a quick search. Maybe would be best to convert that back here to serve as additional proof.
2. As for supporting !value and %value, that is already supported, all keys are added with all placeholder types to the replacement array.
Comment #23
tstoecklerRe 1: So you mean on /node/123 because the route has a route parameter, I can do 'Node id: !node' as title?! I don't quite get what
means in practice.
Re 2: I meant the use-case of:
where the different placeholder types correspond do different variables. Again, I realize this is very far fetched, but it's inconsistent with the general usage of t().
Comment #24
Gábor HojtsyYou can add them as different names easily.
Comment #25
dawehnerMaybe we should indeed also support direct placeholders like in D6/D7 where you could specify 'title arguments' in your hook_menu entry.
Comment #26
YesCT CreditAttribution: YesCT commentedneeds reroll due to #2053153: Allow contrib modules to provide plugins on behalf of optional modules
doing that now. patch soon.
Comment #27
YesCT CreditAttribution: YesCT commentedpretty easy one. dont need to read these notes (unless it fails, or you are just curious)
conflict:
ContextualLinkManager.php
#2053153: Allow contrib modules to provide plugins on behalf of optional modules added the moduleHandler, so keeping that. it did
also, so keeping that change.
And the patch here just was adding
+ $this->requestStack = $request_stack;
So that means I resolved the conflict like:
pretty straightforward.
ContextualLinkManagerTest conflict was:
I dont see any context lines changes... and the patch is just inserting lines. so I kept those inserted lines from the patch.
Comment #29
YesCT CreditAttribution: YesCT commentedThe testbot errors looked like they might be a common error that some people had seen,
in irc
@larowlan helped me sort through this phpunit error.
tldr;
$this->moduleHandler =
doesn't need to be added here, as it is already set earlier.
=======
with the patch applied, http://privatepaste.com/7a44e42688#
looking for expects dealing with alter, found two moduleHandler expects:
$this->moduleHandler->expects($this->at(1)) ->method('alter') ->with($this->equalTo('contextual_links'), new \PHPUnit_Framework_Constraint_Count(2), $this->equalTo('group1'), $this->equalTo(array('key' => 'value')));
$this->moduleHandler->expects($this->once()) ->method('alter') ->with('contextual_links_plugins', $definitions);
so, were they trying to give the expected value (or something) for the first $this->moduleHandler =
and then the at(1) was what was expected for the second call?
or was it a mistake to do $this->moduleHandler = ... twice?
taking out the $this->moduleHandler =
that this patch added gave:
OK (19 tests, 79 assertions)
better.
patch attached.
Comment #30
Gábor Hojtsy@dawehner: re#26 it is not entirely clear to me what is included with raw variables. Is it possible to inject anything in there with the routing structure or would we need specific support for that? Again, this issue is to avoid custom subclassing of subtabs and contextual links and have translation support built-in for placeholders to get back what we had in D7 without each module needing to subclass it for their own. So would this in itself be able to get rid of the subclassing in config translation?
Comment #31
dawehnerSo we talk about the following piece of code:
So we could have something like the following in the yml files / the derivative definition:
Comment #32
Gábor HojtsyYes, yes and yes :) The use cases are at least in the config translation module.
Comment #33
dawehnerTryed(trait) to move the common code into a trait but it somehow did not worked. If someone wants to try it, feel free to do it!
Comment #34
Gábor HojtsyYay, that looks great to me. Thanks so much for resolving this!
Also updated issue summary, explained the API changes proposed.
Comment #35
Gábor Hojtsy33: title-2120235-33.patch queued for re-testing.
Comment #36
catchIf it's not straighforward to add a trait, is there somewhere we can put a static method with a @todo for the trait?
Comment #37
dawehnerSure.
Comment #38
Gábor HojtsyYay, thanks!
Comment #39
catchThat adds a @todo to one case of the code, but I was asking about a static method somewhere with a @todo - to avoid the copy/paste.
Comment #40
dawehnerRealized that we don't need dynamic parameters as this is already covered by using a custom getTitle method on your plugin.
Let's just support static title arguments, like we did in D7. This at least solves the regression and covers most of the usecases.
Comment #41
Gábor HojtsySo now the previously duplicate logic is only in the route titleresolver, and I wrote a change notice draft at [#2226891]. This should be all ready now.
Comment #42
catchCommitted/pushed to 8.x, thanks!
Comment #44
Gábor HojtsyWoot, thanks @dawehner for your persistence.
Comment #46
pwolanin CreditAttribution: pwolanin commentedI missed this when it went in, but the idea of putting static arguments in the YAML perplexes me. I don't understand the actual use case.
Comment #47
Gábor HojtsyThe use case was/is to be able to drop the custom implementations is ConfigTranslationContextualLink and ConfigTranslationLocalTask, because the only reason those exist is due to the replacement strings (D7 title arguments equivalents) not present in Drupal 8. We did not do the conversion here, so maybe less evident.
Comment #48
pwolanin CreditAttribution: pwolanin commented@Gabor: So both of those are using title_context, which seems more reasonable since that would be a static string. I'm much less sure it makes sense to ever define title arguments in the plugin definition.
Comment #49
Gábor HojtsyBoth of them also use a title argument that is derived from the plugin definition (so I think can just as well be stored in the plugin definition):
Title context and title arguments were both added so to not need to override plugins for this case to avoid lots of contrib copy-paste implementations.
Comment #50
pwolanin CreditAttribution: pwolanin commentedOk, I see: thee use case for this is really when creating derivatives, where each derivative would have a different static title argument.
I don't love it as a solution, but at least I see the use case now.
Comment #51
Gábor Hojtsy#2252735: Convert contextual links title arguments to native title arguments shows the benefit with a diffstat of 4 files changed, 2 insertions(+), 110 deletions(-) :) Please review.
Comment #52
YesCT CreditAttribution: YesCT commentedWhy was this changed?
#2783375: ContextualLinkManager calls getTitle() on ContextualLinkInterface plugins without using the controller resolver is related