Problem/Motivation
Drupal caches blocks explicitly by language. BlockViewBuilder has these default cache keys:
$default_cache_keys = array(
'entity_view',
'block',
$entity->id(),
$this->languageManager->getCurrentLanguage()->getId(),
// Blocks are always rendered in a "per theme" cache context.
'cache_context.theme',
);
However it is still possible to configure the blocks to NOT vary per the language cache context, which is not actually adhered to (because its hardwired above).
Proposed resolution
Make the UI honest about the use of language in cache being always on for blocks. Fix the code to refer to the cache context instead of a specific language code.
Remaining tasks
Commit.
User interface changes
None.
API changes
None.
Comment | File | Size | Author |
---|---|---|---|
#37 | block_content_vary_by_language-2318437-37.patch | 5.89 KB | geertvd |
#37 | interdiff.txt | 1.11 KB | geertvd |
#20 | block_content_vary_by_language-2318437-20.patch | 5.26 KB | Wim Leers |
Comments
Comment #1
Wim LeersNo test coverage yet, but this should fix the problem: we make sure that this block is always cached per language.
Comment #2
Gábor HojtsyThats not the right approach, the content block is already render-cached per language, we need the main block to be tagged for its language, and then we need to clear caches with that tag. This patch will clear the cache for tags for that language when submitting config translation.
Comment #3
Wim LeersTurns out that using the language entity is not an option, because it's only available when the language module is enabled. Which would mean we can only add cache tags when the language module is enabled, which is less than great.
So I added a
getCacheTag()
method toLanguageInterface
.Perhaps this issue should be broadened in scope; it could become the "cache tags for languages" issue.
Comment #5
Gábor HojtsyNow that cache tag needs to be expected at several tests. These were in the fails.
Comment #6
Gábor HojtsyBTW I think it would be good to start to practically introduce language cache tags here, and then spread them instead of starting even one more level up...
Comment #8
Gábor HojtsyFix one missing cache tag and one misplaced. This will now pass I think. Still needs its own test for translating the block itself.
Comment #9
dawehnerI wonder whether we could just add language somehow
You could argue that we could put this even higher in the chain. Could the
cache.render
cache service always include it?Comment #10
Gábor HojtsyReuploading patch because it was not sent for testing. It was removed as part of @dawehner's comment for some odd reason.
Comment #11
Wim Leers#9: I've thought about putting it higher in the chain too. It couldn't live in the
cache.render
cache back-end though, but it could live incache_render_cache_set()
.But that would make it almost impossible to choose not to render cache per-language. It's really the responsibility of each renderable thing to declare by what it needs to be invalidated, by setting the proper cache tags.
Agreed, so I'm starting to do that now.
I updated the patch to vary each block per language (using the "language" cache context), because if we're going to tag every block with the current language's cache tag, we should also vary each block per language. This was already done "kind of": each block got the
LanguageManager->getCurrentLanguage()->getId()
key, but we might just as well use the cache context, because otherwise we already cache blocks per UI language, but still allow users to configure blocks to be cached per language. That's rather confusing.This caused one subtle change: blocks no longer get the
en
part of their cache ID while there is only a single language on the website, they'll get the empty string instead. I think it's clearer for everybody if we always include the language explicitly, so I'm updatingLanguageCacheContext
slightly.We'll also want to bring the language cache tag to entities (nodes etc.), because they may be showing field labels. And by default there's the
text, which also depends on the UI language. We may also want to introducecache_context.language
there, butEntityViewBuilder::getBuildDefaults()
currently hasSo I'd love input from e.g. Gábor on how to correctly handle all that.
We generally should be careful about UI language, content language, and available translations of entities when doing adding cache tags and varying by language.
Comment #12
Gábor HojtsyOnce again the smaller scope we can start with the better chance this has to get in without lingering for months on and on. As for content cache tags, the content language used for rendering the content may be whatever (eg. in views, you may filter to German all the time even for English UI pages). I'm not sure we are doing a fabulous job yet to somehow coordinate the field labels for content with the content language, but we should. So if you display a German entity on an English UI page, the field labels *may* show in English (did not test but I assume so :/). Yet one more reason we don't want to delve too deep into this at first.
Comment #14
Gábor HojtsyI think the current title Introduce language cache tag and use it where necessary may be valid for a META issue but not for an issue where you actually want to get something done. Where language is used and which languages exactly is probably an epic question. I'd rather see we start introducing language cache tags on blocks and then going forward on other elements and/or refine our understanding of what a block's language is.
Comment #15
Gábor HojtsyRetitling for a scope that would not be a meta :) Agreed?
Comment #16
Gábor HojtsyClearly not being worked on :/
Comment #17
Gábor HojtsyDuh.
Comment #18
jhedstromComment #19
Wim LeersThe STR in the IS are fixed with this patch. Still needed: a test that follows the STR.
(Patch now simplified because of #12/#14. No interdiff because the patch is now tiny, thanks to its focus. A new issue should be filed to deal with the cache tags aspect that was handled in #11.)
Comment #20
Wim LeersForgot to include one hunk in #19.
Comment #23
Gábor HojtsyFix looks good. Not sure how to best test this, but a test for the STR may be good.
Comment #24
Gábor HojtsyComment #25
Wim LeersLet's see if somebody wants to write this test :)
Comment #26
geertvd CreditAttribution: geertvd commentedI'll write a test for this.
Comment #27
Wim LeersWonderful, thank you!
Comment #28
geertvd CreditAttribution: geertvd commentedI'm actually not able to reproduce this following the STR in the IS.
Not sure if I'm overlooking something, can someone confirm that the STR in the IS are still relevant?
Comment #29
rodrigoaguileraWhat is STR and IS?
Comment #30
geertvd CreditAttribution: geertvd commented@rodrigoaguilera
STR: Steps to reproduce
IS: Issue summary
Comment #31
Wim LeersConfirmed, I also can't reproduce this anymore.
It feels like something is missing from the STR. Hopefully Gábor can enlighten us :)
Comment #32
Gábor HojtsyOk I cannot reproduce this anymore either. Neither by visiting the page first. I wonder why is this fixed now? I mean the language context is *clearly* not selected on the block for caching.
Comment #33
Wim LeersBut blocks have always been cached by language already, just in a hardcoded, less-than-great way:
I think this is what happened originally:
What has changed since the above, is simple: config cache tags. We now consistently invalidate cache tags for config: #2040135: Caches dependent on simple config are only invalidated on form submissions — even when not using the config entity, but config itself directly. AFAICT,
config_translation
uses config "directly" (not config entities). So those CRUD operations now trigger the cache tag invalidations for the placed block config entity, whose cache tags live on the page, and voila: it all works!If Gábor can confirm the above explanation, I think we should repurpose this issue to not be a bugfix, but a task, to still do what #20 does, because it's still a valid cleanup.
Comment #34
geertvd CreditAttribution: geertvd commentedI also think #20 is still a valid change, I can still write a test to confirm that the cache tag is actually invalidated on form submission what will still happen when I apply this issue if I'm not wrong.
Comment #35
Wim LeersI don't think a test is necessary. This is now basically a code clean-up. Retitled.
Comment #36
Gábor HojtsyI agree, this looks like a cleanup and also makes our UI more honest about its caching per language. Still needs the existing test fails resolved though :/ Only the expected form elements were present. in the BlockInterfaceTest.
Comment #37
geertvd CreditAttribution: geertvd commentedThis fixes that.
Comment #40
Gábor HojtsyLooks good, thanks! :) Great cleanup. Let's not call it a novice though.
Comment #41
Gábor HojtsyUpdated issue summary.
Comment #42
alexpottThis issue addresses a major bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 0d869b1 and pushed to 8.0.x. Thanks!
Comment #44
Gábor HojtsyYay, thanks all!
Comment #45
Wim Leers