diff --git a/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorLanguageTest.php b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorLanguageTest.php
new file mode 100644
index 0000000..56c1d0d
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Plugin/CacheDecoratorLanguageTest.php
@@ -0,0 +1,121 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\system\Tests\Plugin\CacheDecoratorLanguageTest.
+ */
+
+namespace Drupal\system\Tests\Plugin;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\Core\Language\Language;
+
+/**
+ * Tests that the AlterDecorator fires and respects the alter hook.
+ */
+class CacheDecoratorLanguageTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('plugin_test', 'locale', 'language');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'CacheDecoratorLanguage',
+      'description' => 'Tests that the CacheDecorator stores definitions by language appropriately.',
+      'group' => 'Plugin API',
+    );
+  }
+
+  public function setUp() {
+    parent::setUp();
+
+    // Populate sample definitions.
+    $this->mockBlockExpectedDefinitions = array(
+      'user_login' => array(
+        'label' => 'User login',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserLoginBlock',
+      ),
+      'menu:main_menu' => array(
+        'label' => 'Main menu',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockMenuBlock',
+      ),
+      'menu:navigation' => array(
+        'label' => 'Navigation',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockMenuBlock',
+      ),
+      'layout' => array(
+        'label' => 'Layout',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
+      ),
+      'layout:foo' => array(
+        'label' => 'Layout Foo',
+        'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
+      ),
+    );
+
+    // Create two languages: Spanish and German.
+    $this->languages = array('de', 'es');
+    foreach ($this->languages as $langcode) {
+      $language = new Language(array('langcode' => $langcode));
+      $languages[$langcode] = language_save($language);
+      // Set up translations for each mock block label.
+      $custom_strings = array();
+      foreach ($this->mockBlockExpectedDefinitions as $plugin_id => $definition) {
+        $custom_strings[$definition['label']] = $langcode . ' ' . $definition['label'];
+      }
+      variable_set('locale_custom_strings_' . $langcode, array('' => $custom_strings));
+    }
+  }
+
+  /**
+   * Check the translations of the cached plugin definitions.
+   */
+  public function testCacheDecoratorLanguage() {
+    $languages = $this->languages;
+    $this->drupalGet('plugin_definition_test');
+    foreach ($this->mockBlockExpectedDefinitions as $plugin_id => $definition) {
+      // Find our source text.
+      $this->assertText($definition['label']);
+    }
+    foreach ($languages as $langcode) {
+      $url = $langcode . '/plugin_definition_test';
+      // For each language visit the language specific version of the page again.
+      $this->drupalGet($url);
+      foreach ($this->mockBlockExpectedDefinitions as $plugin_id => $definition) {
+        // Find our provided translations.
+        $label = $langcode . ' ' . $definition['label'];
+        $this->assertText($label);
+      }
+    }
+    // Manually check that the expected cache keys are present.
+    $languages[] = 'en';
+    foreach ($languages as $langcode) {
+      $cache = cache()->get('mock_block:' . $langcode);
+      $this->assertEqual($cache->cid, 'mock_block:' . $langcode, format_string('The !cache cache exists.', array('!cache' => 'mock_block:' . $langcode)));
+      $this->assertEqual($cache->expire, 1542646800, format_string('The cache expiration was properly set.'));
+    }
+    // Delete cached items tagged with "plugin_test".
+    cache()->deleteTags(array('plugin_test'));
+    foreach ($languages as $langcode) {
+      $cache = cache()->get('mock_block:' . $langcode);
+      $this->assertFalse($cache, format_string('The !cache cache was properly cleared through the cache::deleteTags() method.', array('!cache' => 'mock_block:' . $langcode)));
+    }
+    // Change the translations for the german language and recheck strings.
+    $custom_strings = array();
+    foreach ($this->mockBlockExpectedDefinitions as $plugin_id => $definition) {
+      $custom_strings[$definition['label']] = $definition['label'] . ' de';
+    }
+    variable_set('locale_custom_strings_de', array('' => $custom_strings));
+    $this->drupalGet('de/plugin_definition_test');
+    foreach ($this->mockBlockExpectedDefinitions as $plugin_id => $definition) {
+      // Find our provided translations.
+      $label = $definition['label'] . ' de';
+      $this->assertText($label);
+    }
+  }
+
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/CachedMockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/CachedMockBlockManager.php
new file mode 100644
index 0000000..07ba59e
--- /dev/null
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/CachedMockBlockManager.php
@@ -0,0 +1,29 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\plugin_test\Plugin\CachedMockBlockManager.
+ */
+
+namespace Drupal\plugin_test\Plugin;
+
+use Drupal\Core\Plugin\Discovery\CacheDecorator;
+
+/**
+ * Defines a plugin manager used by Plugin API cache decorator web tests.
+ */
+class CachedMockBlockManager extends MockBlockManager {
+
+  /**
+   * Adds a cache decorator to the MockBlockManager's discovery.
+   *
+   * @see Drupal\plugin_test\Plugin\MockBlockManager::__construct().
+   */
+  public function __construct() {
+    parent::__construct();
+    // The CacheDecorator allows us to cache these plugin definitions for
+    // quicker retrieval. In this case we are generating a cache key by
+    // language.
+    $this->discovery = new CacheDecorator($this->discovery, 'mock_block:' . language(LANGUAGE_TYPE_INTERFACE)->langcode, 'cache',  1542646800, array('plugin_test'));
+  }
+}
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
index 14484f5..fcf1824 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/MockBlockManager.php
@@ -39,7 +39,7 @@ public function __construct() {
 
     // A simple plugin: the user login block.
     $this->discovery->setDefinition('user_login', array(
-      'label' => 'User login',
+      'label' => t('User login'),
       'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockUserLoginBlock',
     ));
 
@@ -61,7 +61,7 @@ public function __construct() {
     // MockLayoutBlockDeriver class ensures that both the base plugin and the
     // derivatives are available to the system.
     $this->discovery->setDefinition('layout', array(
-      'label' => 'Layout',
+      'label' => t('Layout'),
       'class' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlock',
       'derivative' => 'Drupal\plugin_test\Plugin\plugin_test\mock_block\MockLayoutBlockDeriver',
     ));
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockLayoutBlockDeriver.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockLayoutBlockDeriver.php
index c654bd0..1bfe806 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockLayoutBlockDeriver.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockLayoutBlockDeriver.php
@@ -46,7 +46,7 @@ public function getDerivativeDefinitions(array $base_plugin_definition) {
       // customized one, but in a real implementation, this would be fetched
       // from some config() object.
       'foo' => array(
-        'label' => 'Layout Foo',
+        'label' => t('Layout Foo'),
       ) + $base_plugin_definition,
     );
 
diff --git a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockMenuBlockDeriver.php b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockMenuBlockDeriver.php
index aa84202..6b33d13 100644
--- a/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockMenuBlockDeriver.php
+++ b/core/modules/system/tests/modules/plugin_test/lib/Drupal/plugin_test/Plugin/plugin_test/mock_block/MockMenuBlockDeriver.php
@@ -41,10 +41,10 @@ public function getDerivativeDefinitions(array $base_plugin_definition) {
     // Drupal's configuration to find out which menus actually exist.
     $derivatives = array(
       'main_menu' => array(
-        'label' => 'Main menu',
+        'label' => t('Main menu'),
       ) + $base_plugin_definition,
       'navigation' => array(
-        'label' => 'Navigation',
+        'label' => t('Navigation'),
       ) + $base_plugin_definition,
     );
 
diff --git a/core/modules/system/tests/modules/plugin_test/plugin_test.module b/core/modules/system/tests/modules/plugin_test/plugin_test.module
index 147e052..45f89cf 100644
--- a/core/modules/system/tests/modules/plugin_test/plugin_test.module
+++ b/core/modules/system/tests/modules/plugin_test/plugin_test.module
@@ -1,5 +1,7 @@
 <?php
 
+use Drupal\plugin_test\Plugin\CachedMockBlockManager;
+
 /**
  * @file
  * Helper module for the plugin tests.
@@ -14,3 +16,33 @@ function plugin_test_plugin_test_alter(&$definitions) {
   }
   $definitions['user_login']['altered_single'] = TRUE;
 }
+
+/**
+ * Implements hook_menu().
+ */
+function plugin_test_menu() {
+  $items = array();
+  $items['plugin_definition_test'] = array(
+    'access callback' => TRUE,
+    'page callback' => 'plugin_test_definitions',
+  );
+  return $items;
+}
+
+/**
+ * A simple page callback that prints plugin labels for testing.
+ *
+ * @return array
+ *   A simple renderable array of plugin labels.
+ */
+function plugin_test_definitions() {
+  $manager = new CachedMockBlockManager();
+  $output = array();
+  foreach($manager->getDefinitions() as $plugin_id => $definition) {
+    $output[$plugin_id] = array(
+      '#type' => 'markup',
+      '#markup' => $definition['label'],
+    );
+  }
+  return $output;
+}
