diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php
index 53432e8..922c126 100644
--- a/core/lib/Drupal/Core/Utility/Token.php
+++ b/core/lib/Drupal/Core/Utility/Token.php
@@ -184,7 +184,9 @@ public function __construct(ModuleHandlerInterface $module_handler, CacheBackend
    */
   public function replace($text, array $data = array(), array $options = array(), BubbleableMetadata $bubbleable_metadata = NULL) {
     $text_tokens = $this->scan($text);
-    if (empty($text_tokens)) {
+    $text_token_aliases = $this->alias_scan($text);
+
+    if (empty($text_tokens) && empty($text_token_aliases)) {
       return $text;
     }
 
@@ -192,6 +194,8 @@ public function replace($text, array $data = array(), array $options = array(),
     $bubbleable_metadata = $bubbleable_metadata ?: new BubbleableMetadata();
 
     $replacements = array();
+
+    // Standard token replacements.
     foreach ($text_tokens as $type => $tokens) {
       $replacements += $this->generate($type, $tokens, $data, $options, $bubbleable_metadata);
       if (!empty($options['clear'])) {
@@ -199,6 +203,46 @@ public function replace($text, array $data = array(), array $options = array(),
       }
     }
 
+    // Token aliases replacements.
+    foreach ($text_token_aliases as $type => $text_token_alias) {
+      foreach ($text_token_alias as $alias => $tokens) {
+
+        // Aliased token are treated as normal tokens. We simply strip the
+        // alias chunk and call generate. We need a mapping between the aliased
+        // tokens and stripped tokens to add the aliased token value to the
+        // replacement array.
+        $replacements_unaliased = array();
+        $alias_chunk = '{' . $alias . '}';
+
+        // Strip alias from token and map the aliased token with the unaliased
+        // token.
+        $token_alias_map = array();
+        foreach ($tokens as &$token) {
+          $token_name_proccessed = str_replace($alias_chunk, '', $token);
+          $token_alias_map[$token_name_proccessed] = $token;
+          $token = $token_name_proccessed;
+        }
+
+        // Token::generate should only receive data related to the current
+        // token.
+        if (isset($data[$type . $alias_chunk])) {
+          $data_filtered = array($type => $data[$type . $alias_chunk]);
+          $replacements_unaliased  += $this->generate($type, $tokens, $data_filtered, $options, $bubbleable_metadata);
+          if (!empty($options['clear'])) {
+            $replacements_unaliased  += array_fill_keys($tokens, '');
+          }
+
+          // Map the token alias to the calculated token value.
+          $replacements_alias = array();
+          foreach ($replacements_unaliased  as $token => $value) {
+            $replacements_alias[$token_alias_map[$token]] = $value;
+          }
+          // Merge token alias from current type to the replacements array.
+          $replacements += $replacements_alias;
+        }
+      }
+    }
+
     // Escape the tokens, unless they are explicitly markup.
     foreach ($replacements as $token => $value) {
       $replacements[$token] = $value instanceof MarkupInterface ? $value : new HtmlEscapedText($value);
@@ -239,7 +283,7 @@ public function scan($text) {
     // $type may not contain : or whitespace characters, but $name may.
     preg_match_all('/
       \[             # [ - pattern start
-      ([^\s\[\]:]+)  # match $type not containing whitespace : [ or ]
+      ([^\s\[\]:{}]+)  # match $type not containing whitespace : [ or ]
       :              # : - separator
       ([^\[\]]+)     # match $name not containing [ or ]
       \]             # ] - pattern end
@@ -260,6 +304,45 @@ public function scan($text) {
   }
 
   /**
+   * Builds a list of all token-alias-like patterns that appear in the text.
+   *
+   * @param $text
+   *   The text to be scanned for possible token alias.
+   *
+   * @return array
+   *   An associative array of discovered tokens alias, grouped by type.
+   */
+  public function alias_scan($text) {
+    // Matches token alias with the following pattern: [$type{$alias}:$name]
+    // $type and $name may not contain  [ ] characters.
+    // $type may not contain : or whitespace characters, but $name and $alias may.
+    preg_match_all('/
+      \[             # [ - pattern start
+      ([^\s\[\]:]*)  # match $type not containing whitespace : [ or ]
+      {([^\[\]]*)}   # match $alias name
+      :              # : - separator
+      ([^\[\]]+)     # match $name not containing [ or ]
+      \]             # ] - pattern end
+      /x', $text, $matches);
+
+    $types = $matches[1];
+    $alias = $matches[2];
+    $tokens = $matches[3];
+
+
+    // Iterate through the matches, building an associative array containing
+    // $alias grouped by $types, and those $alias contains pairs of $tokens keys
+    // and the complete token found in the source text. For example,
+    // $results['node'['alias1']['title'] = '[node{alias1}:title]';
+    $results = array();
+    for ($i = 0; $i < count($tokens); $i++) {
+      $results[$types[$i]][$alias[$i]][$tokens[$i]] = $matches[0][$i];
+    }
+
+    return $results;
+  }
+
+  /**
    * Generates replacement values for a list of tokens.
    *
    * @param string $type
