diff --git a/core/modules/block/src/Tests/Views/DisplayBlockTest.php b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
index 7f3665a8923..56e7354791e 100644
--- a/core/modules/block/src/Tests/Views/DisplayBlockTest.php
+++ b/core/modules/block/src/Tests/Views/DisplayBlockTest.php
@@ -276,8 +276,8 @@ class DisplayBlockTest extends ViewTestBase {
$cached_block = $this->drupalPlaceBlock('views_block:test_view_block-block_1');
$this->drupalGet('test-page');
- $id = 'block:block=' . $block->id() . ':|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1';
- $cached_id = 'block:block=' . $cached_block->id() . ':|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1';
+ $id = 'block:block=' . $block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
+ $cached_id = 'block:block=' . $cached_block->id() . ':langcode=en|entity.view.edit_form:view=test_view_block:location=block&name=test_view_block&display_id=block_1&langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('
$id)) . '>
', format_string('Contextual link placeholder with id @id exists.', array('@id' => $id)));
$this->assertRaw(' $cached_id)) . '>
', format_string('Contextual link placeholder with id @id exists.', array('@id' => $cached_id)));
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index b7e8ef24ff2..a0cd5b640cd 100644
--- a/core/modules/contextual/contextual.module
+++ b/core/modules/contextual/contextual.module
@@ -7,6 +7,7 @@
use Drupal\Component\Serialization\Json;
use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Routing\RouteMatchInterface;
/**
@@ -137,9 +138,9 @@ function contextual_contextual_links_view_alter(&$element, $items) {
* Serializes #contextual_links property value array to a string.
*
* Examples:
- * - node:node=1:
- * - views_ui_edit:view=frontpage:location=page&view_name=frontpage&view_display_id=page_1
- * - menu:menu=tools:|block:block=bartik.tools:
+ * - node:node=1:langcode=en
+ * - views_ui_edit:view=frontpage:location=page&view_name=frontpage&view_display_id=page_1&langcode=en
+ * - menu:menu=tools:langcode=en|block:block=bartik.tools:langcode=en
*
* So, expressed in a pattern:
* ::
@@ -155,9 +156,15 @@ function contextual_contextual_links_view_alter(&$element, $items) {
*/
function _contextual_links_to_id($contextual_links) {
$ids = array();
+ $langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_URL)->getId();
foreach ($contextual_links as $group => $args) {
$route_parameters = UrlHelper::buildQuery($args['route_parameters']);
- $metadata = UrlHelper::buildQuery((isset($args['metadata'])) ? $args['metadata'] : array());
+ $args += ['metadata' => []];
+ // Add the current URL language to metadata so a different ID will be
+ // computed when URLs vary by language. This allows to store different
+ // language-aware contextual links on the client side.
+ $args['metadata'] += ['langcode' => $langcode];
+ $metadata = UrlHelper::buildQuery($args['metadata']);
$ids[] = "{$group}:{$route_parameters}:{$metadata}";
}
return implode('|', $ids);
diff --git a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
index 20d55cd178b..01eb4f57d0f 100644
--- a/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
+++ b/core/modules/contextual/src/Tests/ContextualDynamicContextTest.php
@@ -8,6 +8,7 @@
namespace Drupal\contextual\Tests;
use Drupal\Component\Serialization\Json;
+use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Template\Attribute;
@@ -45,7 +46,7 @@ class ContextualDynamicContextTest extends WebTestBase {
*
* @var array
*/
- public static $modules = array('contextual', 'node', 'views', 'views_ui');
+ public static $modules = array('contextual', 'node', 'views', 'views_ui', 'language');
protected function setUp() {
parent::setUp();
@@ -53,6 +54,9 @@ class ContextualDynamicContextTest extends WebTestBase {
$this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
$this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+ ConfigurableLanguage::createFromLangcode('it')->save();
+ $this->rebuildContainer();
+
$this->editorUser = $this->drupalCreateUser(array('access content', 'access contextual links', 'edit any article content'));
$this->authenticatedUser = $this->drupalCreateUser(array('access content', 'access contextual links'));
$this->anonymousUser = $this->drupalCreateUser(array('access content'));
@@ -77,12 +81,12 @@ class ContextualDynamicContextTest extends WebTestBase {
// Now, on the front page, all article nodes should have contextual links
// placeholders, as should the view that contains them.
- $ids = array(
- 'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime(),
- 'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime(),
- 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime(),
- 'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1',
- );
+ $ids = [
+ 'node:node=' . $node1->id() . ':changed=' . $node1->getChangedTime() . '&langcode=en',
+ 'node:node=' . $node2->id() . ':changed=' . $node2->getChangedTime() . '&langcode=en',
+ 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=en',
+ 'entity.view.edit_form:view=frontpage:location=page&name=frontpage&display_id=page_1&langcode=en',
+ ];
// Editor user: can access contextual links and can edit articles.
$this->drupalGet('node');
@@ -127,6 +131,12 @@ class ContextualDynamicContextTest extends WebTestBase {
$this->assertResponse(403);
$this->renderContextualLinks($ids, 'node');
$this->assertResponse(403);
+
+ // Verify that link language is properly handled.
+ $node3->addTranslation('it')->save();
+ $id = 'node:node=' . $node3->id() . ':changed=' . $node3->getChangedTime() . '&langcode=it';
+ $this->drupalGet('node', ['language' => ConfigurableLanguage::createFromLangcode('it')]);
+ $this->assertContextualLinkPlaceHolder($id);
}
/**
diff --git a/core/modules/contextual/src/Tests/ContextualUnitTest.php b/core/modules/contextual/src/Tests/ContextualUnitTest.php
index bd145f646fe..f164051d6b5 100644
--- a/core/modules/contextual/src/Tests/ContextualUnitTest.php
+++ b/core/modules/contextual/src/Tests/ContextualUnitTest.php
@@ -38,10 +38,10 @@ class ContextualUnitTest extends KernelTestBase {
'route_parameters' => array(
'node' => '14031991',
),
- 'metadata' => array()
+ 'metadata' => array('langcode' => 'en'),
),
),
- 'id' => 'node:node=14031991:',
+ 'id' => 'node:node=14031991:langcode=en',
);
// Test branch conditions:
@@ -56,10 +56,10 @@ class ContextualUnitTest extends KernelTestBase {
'key' => 'baz',
'qux',
),
- 'metadata' => array(),
+ 'metadata' => array('langcode' => 'en'),
),
),
- 'id' => 'foo:0=bar&key=baz&1=qux:',
+ 'id' => 'foo:0=bar&key=baz&1=qux:langcode=en',
);
// Test branch conditions:
@@ -75,10 +75,11 @@ class ContextualUnitTest extends KernelTestBase {
'metadata' => array(
'location' => 'page',
'display' => 'page_1',
+ 'langcode' => 'en',
),
),
),
- 'id' => 'views_ui_edit:view=frontpage:location=page&display=page_1',
+ 'id' => 'views_ui_edit:view=frontpage:location=page&display=page_1&langcode=en',
);
// Test branch conditions:
@@ -90,7 +91,7 @@ class ContextualUnitTest extends KernelTestBase {
'route_parameters' => array(
'node' => '14031991',
),
- 'metadata' => array(),
+ 'metadata' => array('langcode' => 'en'),
),
'foo' => array(
'route_parameters' => array(
@@ -98,14 +99,14 @@ class ContextualUnitTest extends KernelTestBase {
'key' => 'baz',
'qux',
),
- 'metadata' => array(),
+ 'metadata' => array('langcode' => 'en'),
),
'edge' => array(
'route_parameters' => array('20011988'),
- 'metadata' => array(),
+ 'metadata' => array('langcode' => 'en'),
),
),
- 'id' => 'node:node=14031991:|foo:0=bar&key=baz&1=qux:|edge:0=20011988:',
+ 'id' => 'node:node=14031991:langcode=en|foo:0=bar&key=baz&1=qux:langcode=en|edge:0=20011988:langcode=en',
);
return $tests;
@@ -130,4 +131,5 @@ class ContextualUnitTest extends KernelTestBase {
$this->assertIdentical(_contextual_id_to_links($test['id']), $test['links']);
}
}
+
}
diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php
index 722548f04d7..de0ec7a6d27 100644
--- a/core/modules/menu_ui/src/Tests/MenuTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuTest.php
@@ -567,7 +567,7 @@ class MenuTest extends MenuWebTestBase {
$block = $this->drupalPlaceBlock('system_menu_block:' . $custom_menu->id(), array('label' => 'Custom menu', 'provider' => 'system'));
$this->drupalGet('test-page');
- $id = 'block:block=' . $block->id() . ':|menu:menu=' . $custom_menu->id() . ':';
+ $id = 'block:block=' . $block->id() . ':langcode=en|menu:menu=' . $custom_menu->id() . ':langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw('', format_string('Contextual link placeholder with id @id exists.', array('@id' => $id)));
diff --git a/core/modules/views_ui/src/Tests/DisplayTest.php b/core/modules/views_ui/src/Tests/DisplayTest.php
index 12c06bded26..a735c219bf4 100644
--- a/core/modules/views_ui/src/Tests/DisplayTest.php
+++ b/core/modules/views_ui/src/Tests/DisplayTest.php
@@ -181,7 +181,7 @@ class DisplayTest extends UITestBase {
$this->container->get('router.builder')->rebuildIfNeeded();
$this->drupalGet('test-display');
- $id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1';
+ $id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en';
// @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder()
$this->assertRaw(' $id)) . '>
', format_string('Contextual link placeholder with id @id exists.', array('@id' => $id)));