diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
index 8eb2568..69afe91 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
@@ -35,14 +35,25 @@ class DerivativeDiscoveryDecorator implements DiscoveryInterface {
   protected $decorated;
 
   /**
+   * Serperator string.
+   *
+   * @var string
+   */
+  protected $separator;
+
+  /**
    * Creates a new instance.
    *
    * @param \Drupal\Component\Plugin\Discovery\DiscoveryInterface $decorated
    *   The parent object implementing DiscoveryInterface that is being
    *   decorated.
+   *
+   * @param string $separator
+   *   The string to use as a separator, must be machine_name safe.
    */
-  public function __construct(DiscoveryInterface $decorated) {
+  public function __construct(DiscoveryInterface $decorated, $separator = ':') {
     $this->decorated = $decorated;
+    $this->separator = $separator;
   }
 
   /**
@@ -137,8 +148,8 @@ protected function decodePluginId($plugin_id) {
     // Try and split the passed plugin definition into a plugin and a
     // derivative id. We don't need to check for !== FALSE because a leading
     // colon would break the derivative system and doesn't makes sense.
-    if (strpos($plugin_id, ':')) {
-      return explode(':', $plugin_id, 2);
+    if (strpos($plugin_id, $this->separator)) {
+      return explode($this->separator, $plugin_id, 2);
     }
 
     return array($plugin_id, NULL);
@@ -157,7 +168,7 @@ protected function decodePluginId($plugin_id) {
    */
   protected function encodePluginId($base_plugin_id, $derivative_id) {
     if ($derivative_id) {
-      return "$base_plugin_id:$derivative_id";
+      return $base_plugin_id . $this->separator . $derivative_id;
     }
 
     // By returning the unmerged plugin_id, we are able to support derivative
