Problem/Motivation
When a block is present on a page created by page manager, and this block is managed by regular Drupal block management, and it has language visibility condition, this condition does not apply correctly.
Steps to reproduce
You should have at least 2 languages on the site enabled, say, English and French. English is default.
Create a page manager page. It may be even empty. Let it have the path /test.
Put some block in some region by regular Drupal block management (admin/structure/blocks), and assign visibility condition Language -> English.
Put another block the same way at assign it visibility condition Language->French
Go to the /test page in English. You will see an English block. Switch to French. You will still see the English block.
Proposed resolution
The responsibility for this behaviour is somewhat shared between Core and Page manager.
\Drupal\language\Plugin\Condition\Language::evaluate() relies not on the language negotiator, but on the language context.
And here's the stack trace of how language context is set
Context.php:51, Drupal\Core\Plugin\Context\Context->__construct()
CurrentLanguageContext.php:55, Drupal\Core\Language\ContextProvider\CurrentLanguageContext->getRuntimeContexts()
CurrentLanguageContext.php:72, Drupal\Core\Language\ContextProvider\CurrentLanguageContext->getAvailableContexts()
LazyContextRepository.php:97, Drupal\Core\Plugin\Context\LazyContextRepository->getAvailableContexts()
EntityConverter.php:132, Drupal\Core\ParamConverter\EntityConverter->convert()
ParamConverterManager.php:100, Drupal\Core\ParamConverter\ParamConverterManager->convert()
ParamConversionEnhancer.php:45, Drupal\Core\Routing\Enhancer\ParamConversionEnhancer->enhance()
VariantRouteFilter.php:233, Drupal\page_manager\Routing\VariantRouteFilter->getRequestAttributes()
VariantRouteFilter.php:128, Drupal\page_manager\Routing\VariantRouteFilter->getVariantRouteName()
VariantRouteFilter.php:82, Drupal\page_manager\Routing\VariantRouteFilter->filter()
Router.php:280, Drupal\Core\Routing\Router->applyRouteFilters()
Router.php:126, Drupal\Core\Routing\Router->matchRequest()
AccessAwareRouter.php:93, Drupal\Core\Routing\AccessAwareRouter->matchRequest()
AccessAwareRouter.php:151, Drupal\Core\Routing\AccessAwareRouter->match()
LanguageNegotiationUserAdmin.php:138, Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin->isAdminPath()
LanguageNegotiationUserAdmin.php:104, Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin->getLangcode()
LanguageNegotiator.php:188, Drupal\language\LanguageNegotiator->negotiateLanguage()
LanguageNegotiator.php:133, Drupal\language\LanguageNegotiator->initializeType()
ConfigurableLanguageManager.php:218, Drupal\language\ConfigurableLanguageManager->getCurrentLanguage()
LanguageRequestSubscriber.php:92, Drupal\language\EventSubscriber\LanguageRequestSubscriber->setLanguageOverrides()
LanguageRequestSubscriber.php:74, Drupal\language\EventSubscriber\LanguageRequestSubscriber->onKernelRequestLanguage()
ContainerAwareEventDispatcher.php:142, call_user_func:{/var/www/html/web/core/lib/Drupal/Component/EventDispatcher/ContainerAwareEventDispatcher.php:142}()
ContainerAwareEventDispatcher.php:142, Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch()
HttpKernel.php:134, Symfony\Component\HttpKernel\HttpKernel->handleRaw()
HttpKernel.php:80, Symfony\Component\HttpKernel\HttpKernel->handle()
Session.php:58, Drupal\Core\StackMiddleware\Session->handle()
KernelPreHandle.php:48, Drupal\Core\StackMiddleware\KernelPreHandle->handle()
PageCache.php:106, Drupal\page_cache\StackMiddleware\PageCache->pass()
PageCache.php:85, Drupal\page_cache\StackMiddleware\PageCache->handle()
ReverseProxyMiddleware.php:48, Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
NegotiationMiddleware.php:51, Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
StackedHttpKernel.php:23, Stack\StackedHttpKernel->handle()
DrupalKernel.php:708, Drupal\Core\DrupalKernel->handle()
index.php:19, {main}()
So router gets called from language negotiation, and this routing sets required contexts including language when language negotiation is not done yet.
I think \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::isAdminPath() is wrong and should not build a route if there is no yet. Maybe there's also a way to approach this in Page Manager.
The solution that is quick and dirty is to use negotiated language in \Drupal\language\Plugin\Condition\Language::evaluate() , which means a core patch. I will cross-post this as a core issue and put the patch there.
Remaining tasks
Find a clean solution.
User interface changes
No.
API changes
?
Data model changes
?
Comments
Comment #2
geaseComment #3
geaseI have uploaded a provisionary patch to #3263978: \Drupal\user\Plugin\LanguageNegotiation\LanguageNegotiationUserAdmin::isAdminPath should not build router
Comment #4
geaseUpdate: what actually introduces the problem is "Account administration pages" language detection method. It should be enabled as first detection method to reproduce the problem.