diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php
index fa4fb1c..9fa73b4 100644
--- a/core/lib/Drupal/Core/Utility/Token.php
+++ b/core/lib/Drupal/Core/Utility/Token.php
@@ -260,25 +260,10 @@ public function findWithPrefix(array $tokens, $prefix, $delimiter = ':') {
    * as an optional pointer indicating that the token chains to another set of
    * tokens.
    *
-   * For example:
-   * @code
-   *   $data['types']['node'] = array(
-   *     'name' => t('Nodes'),
-   *     'description' => t('Tokens related to node objects.'),
-   *   );
-   *   $data['tokens']['node']['title'] = array(
-   *     'name' => t('Title'),
-   *     'description' => t('The title of the current node.'),
-   *   );
-   *   $data['tokens']['node']['author'] = array(
-   *     'name' => t('Author'),
-   *     'description' => t('The author of the current node.'),
-   *     'type' => 'user',
-   *   );
-   * @endcode
-   *
    * @return array
-   *   An associative array of token information, grouped by token type.
+   *   The array has the same format as the return value of hook_token_info().
+   *
+   * @see hook_token_info()
    */
   public function info() {
     $data = &drupal_static('token_info');
diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc
index 947c2a5..58fa1a0 100644
--- a/core/modules/comment/comment.tokens.inc
+++ b/core/modules/comment/comment.tokens.inc
@@ -9,94 +9,87 @@
  * Implements hook_token_info().
  */
 function comment_token_info() {
-  $type = array(
+  $tokens['comment'] = array(
     'name' => t('Comments'),
     'description' => t('Tokens for comments posted on the site.'),
     'needs-data' => 'comment',
   );
-
-  // Comment-related tokens for nodes
-  $node['comment-count'] = array(
-    'name' => t("Comment count"),
-    'description' => t("The number of comments posted on a node."),
-  );
-  $node['comment-count-new'] = array(
-    'name' => t("New comment count"),
-    'description' => t("The number of comments posted on a node since the reader last viewed it."),
-  );
-
-  // Core comment tokens
-  $comment['cid'] = array(
+  // Core comment tokens.
+  $tokens['comment']['tokens']['cid'] = array(
     'name' => t("Comment ID"),
     'description' => t("The unique ID of the comment."),
   );
-  $comment['hostname'] = array(
+  $tokens['comment']['tokens']['hostname'] = array(
     'name' => t("IP Address"),
     'description' => t("The IP address of the computer the comment was posted from."),
   );
-  $comment['name'] = array(
+  $tokens['comment']['tokens']['name'] = array(
     'name' => t("Name"),
     'description' => t("The name left by the comment author."),
   );
-  $comment['mail'] = array(
+  $tokens['comment']['tokens']['mail'] = array(
     'name' => t("Email address"),
     'description' => t("The email address left by the comment author."),
   );
-  $comment['homepage'] = array(
+  $tokens['comment']['tokens']['homepage'] = array(
     'name' => t("Home page"),
     'description' => t("The home page URL left by the comment author."),
   );
-  $comment['title'] = array(
+  $tokens['comment']['tokens']['title'] = array(
     'name' => t("Title"),
     'description' => t("The title of the comment."),
   );
-  $comment['body'] = array(
+  $tokens['comment']['tokens']['body'] = array(
     'name' => t("Content"),
     'description' => t("The formatted content of the comment itself."),
   );
-  $comment['url'] = array(
+  $tokens['comment']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The URL of the comment."),
   );
-  $comment['edit-url'] = array(
+  $tokens['comment']['tokens']['edit-url'] = array(
     'name' => t("Edit URL"),
     'description' => t("The URL of the comment's edit page."),
   );
 
-  // Chained tokens for comments
-  $comment['created'] = array(
+  // Chained tokens for comments.
+  $tokens['comment']['tokens']['created'] = array(
     'name' => t("Date created"),
     'description' => t("The date the comment was posted."),
     'type' => 'date',
   );
-  $comment['changed'] = array(
+  $tokens['comment']['tokens']['changed'] = array(
     'name' => t("Date changed"),
     'description' => t("The date the comment was most recently updated."),
     'type' => 'date',
   );
-  $comment['parent'] = array(
+  $tokens['comment']['tokens']['parent'] = array(
     'name' => t("Parent"),
     'description' => t("The comment's parent, if comment threading is active."),
     'type' => 'comment',
   );
-  $comment['node'] = array(
+  $tokens['comment']['tokens']['node'] = array(
     'name' => t("Node"),
     'description' => t("The node the comment was posted to."),
     'type' => 'node',
   );
-  $comment['author'] = array(
+  $tokens['comment']['tokens']['author'] = array(
     'name' => t("Author"),
     'description' => t("The author of the comment, if they were logged in."),
     'type' => 'user',
   );
 
-  return array(
-    'types' => array('comment' => $type),
-    'tokens' => array(
-      'node' => $node,
-      'comment' => $comment,
-    ),
+  // Comment-related tokens for nodes.
+  $tokens['node']['tokens']['comment-count'] = array(
+    'name' => t("Comment count"),
+    'description' => t("The number of comments posted on a node."),
   );
+  $tokens['node']['tokens']['comment-count-new'] = array(
+    'name' => t("New comment count"),
+    'description' => t("The number of comments posted on a node since the reader last viewed it."),
+  );
+
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 63b51e1..cf18e1c 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -11,79 +11,74 @@
  * Implements hook_token_info().
  */
 function node_token_info() {
-  $type = array(
+  $tokens['node'] = array(
     'name' => t('Nodes'),
     'description' => t('Tokens related to individual content items, or "nodes".'),
     'needs-data' => 'node',
   );
-
   // Core tokens for nodes.
-  $node['nid'] = array(
+  $tokens['node']['tokens']['nid'] = array(
     'name' => t("Content ID"),
     'description' => t('The unique ID of the content item, or "node".'),
   );
-  $node['vid'] = array(
+  $tokens['node']['tokens']['vid'] = array(
     'name' => t("Revision ID"),
     'description' => t("The unique ID of the node's latest revision."),
   );
-  $node['tnid'] = array(
+  $tokens['node']['tokens']['tnid'] = array(
     'name' => t("Translation set ID"),
     'description' => t("The unique ID of the original-language version of this node, if one exists."),
   );
-  $node['type'] = array(
+  $tokens['node']['tokens']['type'] = array(
     'name' => t("Content type"),
     'description' => t("The type of the node."),
   );
-  $node['type-name'] = array(
+  $tokens['node']['tokens']['type-name'] = array(
     'name' => t("Content type name"),
     'description' => t("The human-readable name of the node type."),
   );
-  $node['title'] = array(
+  $tokens['node']['tokens']['title'] = array(
     'name' => t("Title"),
     'description' => t("The title of the node."),
   );
-  $node['body'] = array(
+  $tokens['node']['tokens']['body'] = array(
     'name' => t("Body"),
     'description' => t("The main body text of the node."),
   );
-  $node['summary'] = array(
+  $tokens['node']['tokens']['summary'] = array(
     'name' => t("Summary"),
     'description' => t("The summary of the node's main body text."),
   );
-  $node['langcode'] = array(
+  $tokens['node']['tokens']['langcode'] = array(
     'name' => t('Language code'),
     'description' => t('The language code of the language the node is written in.'),
   );
-  $node['url'] = array(
+  $tokens['node']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The URL of the node."),
   );
-  $node['edit-url'] = array(
+  $tokens['node']['tokens']['edit-url'] = array(
     'name' => t("Edit URL"),
     'description' => t("The URL of the node's edit page."),
   );
-
   // Chained tokens for nodes.
-  $node['created'] = array(
+  $tokens['node']['tokens']['created'] = array(
     'name' => t("Date created"),
     'description' => t("The date the node was posted."),
     'type' => 'date',
   );
-  $node['changed'] = array(
+  $tokens['node']['tokens']['changed'] = array(
     'name' => t("Date changed"),
     'description' => t("The date the node was most recently updated."),
     'type' => 'date',
   );
-  $node['author'] = array(
+  $tokens['node']['tokens']['author'] = array(
     'name' => t("Author"),
     'description' => t("The author of the node."),
     'type' => 'user',
   );
 
-  return array(
-    'types' => array('node' => $type),
-    'tokens' => array('node' => $node),
-  );
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/statistics/statistics.tokens.inc b/core/modules/statistics/statistics.tokens.inc
index 5320e4f..1fcf370 100644
--- a/core/modules/statistics/statistics.tokens.inc
+++ b/core/modules/statistics/statistics.tokens.inc
@@ -9,23 +9,21 @@
  * Implements hook_token_info().
  */
 function statistics_token_info() {
-  $node['total-count'] = array(
+  $tokens['node']['tokens']['total-count'] = array(
     'name' => t("Number of views"),
     'description' => t("The number of visitors who have read the node."),
   );
-  $node['day-count'] = array(
+  $tokens['node']['tokens']['day-count'] = array(
     'name' => t("Views today"),
     'description' => t("The number of visitors who have read the node today."),
   );
-  $node['last-view'] = array(
+  $tokens['node']['tokens']['last-view'] = array(
     'name' => t("Last view"),
     'description' => t("The date on which a visitor last read the node."),
     'type' => 'date',
   );
 
-  return array(
-    'tokens' => array('node' => $node),
-  );
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index bea1fab..9ff541d 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -3303,83 +3303,97 @@ function hook_tokens_alter(array &$replacements, array $context) {
  * Tokens are placeholders that can be put into text by using the syntax
  * [type:token], where type is the machine-readable name of a token type, and
  * token is the machine-readable name of a token within this group. This hook
- * provides a list of types and tokens to be displayed on text editing screens,
- * so that people editing text can see what their token options are.
+ * provides a list of data types and their tokens to be displayed on text
+ * editing screens, so that people can see what their token options are.
  *
  * The actual token replacement is done by
  * \Drupal\Core\Utility\Token::replace(), which invokes hook_tokens(). Your
  * module will need to implement that hook in order to generate token
  * replacements from the tokens defined here.
  *
- * @return
- *   An associative array of available tokens and token types. The outer array
- *   has two components:
- *   - types: An associative array of token types (groups). Each token type is
- *     an associative array with the following components:
- *     - name: The translated human-readable short name of the token type.
- *     - description: A translated longer description of the token type.
- *     - needs-data: The type of data that must be provided to
- *       \Drupal\Core\Utility\Token::replace() in the $data argument (i.e., the
- *       key name in $data) in order for tokens of this type to be used in the
- *       $text being processed. For instance, if the token needs a node object,
- *       'needs-data' should be 'node', and to use this token in
- *       \Drupal\Core\Utility\Token::replace(), the caller needs to supply a
- *       node object as $data['node']. Some token data can also be supplied
- *       indirectly; for instance, a node object in $data supplies a user object
- *       (the author of the node), allowing user tokens to be used when only
- *       a node data object is supplied.
- *   - tokens: An associative array of tokens. The outer array is keyed by the
- *     group name (the same key as in the types array). Within each group of
- *     tokens, each token item is keyed by the machine name of the token, and
- *     each token item has the following components:
+ * @return array
+ *   Keys are data type machine names that represent the type of data that
+ *   must be provided to token_replace() in the $data argument (i.e., the key
+ *   name in $data) in order for tokens of this type to be used in the $text
+ *   being processed. For instance, to use "node" tokens, the caller needs to
+ *   supply token_replace() witth a node object as $data['node']. Some token
+ *   data can also be supplied indirectly; for instance, a node object in $data
+ *   supplies a user object (the author of the node), allowing user tokens to
+ *   be used when only a node data object is supplied. Values are arrays with
+ *   the following keys:
+ *   - name: The translated human-readable short name of the data type.
+ *   - description: A translated longer description of the data type.
+ *   - needs-data: The type of data that must be provided to token_replace()
+ *     in the $data argument (i.e., the key name in $data) in order for tokens
+ *     of this type to be used in the $text being processed. For instance, if
+ *     the token needs a node object, 'needs-data' should be 'node', and to
+ *     use this token in token_replace(), the caller needs to supply a node
+ *     object as $data['node']. Some token data can also be supplied
+ *     indirectly; for instance, a node object in $data supplies a user object
+ *     (the author of the node), allowing user tokens to be used when only
+ *     a node data object is supplied.
+ *   - tokens: An array with tokens of which keys are the tokens' machine
+ *     names. Values are arrays with the following keys:
  *     - name: The translated human-readable short name of the token.
  *     - description: A translated longer description of the token.
- *     - type (optional): A 'needs-data' data type supplied by this token, which
- *       should match a 'needs-data' value from another token type. For example,
- *       the node author token provides a user object, which can then be used
- *       for token replacement data in \Drupal\Core\Utility\Token::replace()
- *       without having to supply a separate user object.
+ *     - type (optional): Another data type that this type extends.
+ *   - type (optional): Another data type that this type extends.
+ * For example:
+ * @code
+ *   $tokens['node'] = array(
+ *     'needs-data' => 'node,
+ *     'name' => t('Nodes'),
+ *     'tokens' => array(
+ *       'title' => array(
+ *         'label' => t('Title'),
+ *       ),
+ *       'author' => array(
+ *         'name' => t('Author'),
+ *         'description' => t('The author of the current node.'),
+ *         'type' => 'user',
+ *       ),
+ *     ),
+ *   );
+ * @endcode
  *
+ * @see token_info()
  * @see hook_token_info_alter()
  * @see hook_tokens()
  */
 function hook_token_info() {
-  $type = array(
+  $tokens['node'] = array(
     'name' => t('Nodes'),
     'description' => t('Tokens related to individual nodes.'),
     'needs-data' => 'node',
   );
 
   // Core tokens for nodes.
-  $node['nid'] = array(
+  $tokens['node']['tokens']['nid'] = array(
     'name' => t("Node ID"),
     'description' => t("The unique ID of the node."),
   );
-  $node['title'] = array(
+  $tokens['node']['tokens']['title'] = array(
     'name' => t("Title"),
     'description' => t("The title of the node."),
   );
-  $node['edit-url'] = array(
+  $tokens['node']['tokens']['edit-url'] = array(
     'name' => t("Edit URL"),
     'description' => t("The URL of the node's edit page."),
   );
 
   // Chained tokens for nodes.
-  $node['created'] = array(
+  $tokens['node']['tokens']['created'] = array(
     'name' => t("Date created"),
     'description' => t("The date the node was posted."),
     'type' => 'date',
   );
-  $node['author'] = array(
+  $tokens['node']['tokens']['author'] = array(
     'name' => t("Author"),
     'description' => t("The author of the node."),
     'type' => 'user',
   );
 
-  return array(
-    'types' => array('node' => $type),
-    'tokens' => array('node' => $node),
-  );
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/system/system.tokens.inc b/core/modules/system/system.tokens.inc
index 78056c5..3964f36 100644
--- a/core/modules/system/system.tokens.inc
+++ b/core/modules/system/system.tokens.inc
@@ -12,117 +12,108 @@
  * Implements hook_token_info().
  */
 function system_token_info() {
-  $types['site'] = array(
+  // Site-wide global tokens.
+  $tokens['site'] = array(
     'name' => t("Site information"),
     'description' => t("Tokens for site-wide settings and other global information."),
   );
-  $types['date'] = array(
-    'name' => t("Dates"),
-    'description' => t("Tokens related to times and dates."),
-  );
-  $types['file'] = array(
-    'name' => t("Files"),
-    'description' => t("Tokens related to uploaded files."),
-    'needs-data' => 'file',
-  );
-
-  // Site-wide global tokens.
-  $site['name'] = array(
+  $tokens['site']['tokens']['name'] = array(
     'name' => t("Name"),
     'description' => t("The name of the site."),
   );
-  $site['slogan'] = array(
+  $tokens['site']['tokens']['slogan'] = array(
     'name' => t("Slogan"),
     'description' => t("The slogan of the site."),
   );
-  $site['mail'] = array(
+  $tokens['site']['tokens']['mail'] = array(
     'name' => t("Email"),
     'description' => t("The administrative email address for the site."),
   );
-  $site['url'] = array(
+  $tokens['site']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The URL of the site's front page."),
   );
-  $site['url-brief'] = array(
+  $tokens['site']['tokens']['url-brief'] = array(
     'name' => t("URL (brief)"),
     'description' => t("The URL of the site's front page without the protocol."),
   );
-  $site['login-url'] = array(
+  $tokens['site']['tokens']['login-url'] = array(
     'name' => t("Login page"),
     'description' => t("The URL of the site's login page."),
   );
 
   // Date related tokens.
-  $date['short'] = array(
+  $tokens['date'] = array(
+    'name' => t("Dates"),
+    'description' => t("Tokens related to times and dates."),
+  );
+  $tokens['date']['tokens']['short'] = array(
     'name' => t("Short format"),
     'description' => t("A date in 'short' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'short'))),
   );
-  $date['medium'] = array(
+  $tokens['date']['tokens']['medium'] = array(
     'name' => t("Medium format"),
     'description' => t("A date in 'medium' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'medium'))),
   );
-  $date['long'] = array(
+  $tokens['date']['tokens']['long'] = array(
     'name' => t("Long format"),
     'description' => t("A date in 'long' format. (%date)", array('%date' => format_date(REQUEST_TIME, 'long'))),
   );
-  $date['custom'] = array(
+  $tokens['date']['tokens']['custom'] = array(
     'name' => t("Custom format"),
     'description' => t("A date in a custom format. See !php-date for details.", array('!php-date' => l(t('the PHP documentation'), 'http://php.net/manual/function.date.php'))),
   );
-  $date['since'] = array(
+  $tokens['date']['tokens']['since'] = array(
     'name' => t("Time-since"),
     'description' => t("A date in 'time-since' format. (%date)", array('%date' => format_interval(REQUEST_TIME - 360, 2))),
   );
-  $date['raw'] = array(
+  $tokens['date']['tokens']['raw'] = array(
     'name' => t("Raw timestamp"),
     'description' => t("A date in UNIX timestamp format (%date)", array('%date' => REQUEST_TIME)),
   );
 
-
   // File related tokens.
-  $file['fid'] = array(
+  $tokens['file'] = array(
+    'name' => t("Files"),
+    'description' => t("Tokens related to uploaded files."),
+    'needs-data' => 'file',
+  );
+  $tokens['file']['tokens']['fid'] = array(
     'name' => t("File ID"),
     'description' => t("The unique ID of the uploaded file."),
   );
-  $file['name'] = array(
+  $tokens['file']['tokens']['name'] = array(
     'name' => t("File name"),
     'description' => t("The name of the file on disk."),
   );
-  $file['path'] = array(
+  $tokens['file']['tokens']['path'] = array(
     'name' => t("Path"),
     'description' => t("The location of the file relative to Drupal root."),
   );
-  $file['mime'] = array(
+  $tokens['file']['tokens']['mime'] = array(
     'name' => t("MIME type"),
     'description' => t("The MIME type of the file."),
   );
-  $file['size'] = array(
+  $tokens['file']['tokens']['size'] = array(
     'name' => t("File size"),
     'description' => t("The size of the file."),
   );
-  $file['url'] = array(
+  $tokens['file']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The web-accessible URL for the file."),
   );
-  $file['timestamp'] = array(
+  $tokens['file']['tokens']['timestamp'] = array(
     'name' => t("Timestamp"),
     'description' => t("The date the file was most recently changed."),
     'type' => 'date',
   );
-  $file['owner'] = array(
+  $tokens['file']['tokens']['owner'] = array(
     'name' => t("Owner"),
     'description' => t("The user who originally uploaded the file."),
     'type' => 'user',
   );
 
-  return array(
-    'types' => $types,
-    'tokens' => array(
-      'site' => $site,
-      'date' => $date,
-      'file' => $file,
-    ),
-  );
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/taxonomy/taxonomy.tokens.inc b/core/modules/taxonomy/taxonomy.tokens.inc
index 82d3a52..cb00207 100644
--- a/core/modules/taxonomy/taxonomy.tokens.inc
+++ b/core/modules/taxonomy/taxonomy.tokens.inc
@@ -9,80 +9,71 @@
  * Implements hook_token_info().
  */
 function taxonomy_token_info() {
-  $types['term'] = array(
+  // Taxonomy term related variables.
+  $tokens['term'] = array(
     'name' => t("Taxonomy terms"),
     'description' => t("Tokens related to taxonomy terms."),
     'needs-data' => 'term',
   );
-  $types['vocabulary'] = array(
-    'name' => t("Vocabularies"),
-    'description' => t("Tokens related to taxonomy vocabularies."),
-    'needs-data' => 'vocabulary',
-  );
-
-  // Taxonomy term related variables.
-  $term['tid'] = array(
+  $tokens['term']['tokens']['tid'] = array(
     'name' => t("Term ID"),
     'description' => t("The unique ID of the taxonomy term."),
   );
-  $term['name'] = array(
+  $tokens['term']['tokens']['name'] = array(
     'name' => t("Name"),
     'description' => t("The name of the taxonomy term."),
   );
-  $term['description'] = array(
+  $tokens['term']['tokens']['description'] = array(
     'name' => t("Description"),
     'description' => t("The optional description of the taxonomy term."),
   );
-  $term['node-count'] = array(
+  $tokens['term']['tokens']['node-count'] = array(
     'name' => t("Node count"),
     'description' => t("The number of nodes tagged with the taxonomy term."),
   );
-  $term['url'] = array(
+  $tokens['term']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The URL of the taxonomy term."),
   );
+  $tokens['term']['tokens']['vocabulary'] = array(
+    'name' => t("Vocabulary"),
+    'description' => t("The vocabulary the taxonomy term belongs to."),
+    'type' => 'vocabulary',
+  );
+  $tokens['term']['tokens']['parent'] = array(
+    'name' => t("Parent term"),
+    'description' => t("The parent term of the taxonomy term, if one exists."),
+    'type' => 'term',
+  );
 
   // Taxonomy vocabulary related variables.
-  $vocabulary['vid'] = array(
+  $tokens['vocabulary'] = array(
+    'name' => t("Vocabularies"),
+    'description' => t("Tokens related to taxonomy vocabularies."),
+    'needs-data' => 'vocabulary',
+  );
+  $tokens['vocabulary']['tokens']['vid'] = array(
     'name' => t("Vocabulary ID"),
     'description' => t("The unique ID of the taxonomy vocabulary."),
   );
-  $vocabulary['name'] = array(
+  $tokens['vocabulary']['tokens']['name'] = array(
     'name' => t("Name"),
     'description' => t("The name of the taxonomy vocabulary."),
   );
-  $vocabulary['description'] = array(
+  $tokens['vocabulary']['tokens']['description'] = array(
     'name' => t("Description"),
     'description' => t("The optional description of the taxonomy vocabulary."),
   );
-  $vocabulary['node-count'] = array(
+  $tokens['vocabulary']['tokens']['node-count'] = array(
     'name' => t("Node count"),
     'description' => t("The number of nodes tagged with terms belonging to the taxonomy vocabulary."),
   );
-  $vocabulary['term-count'] = array(
+  $tokens['vocabulary']['tokens']['term-count'] = array(
     'name' => t("Term count"),
     'description' => t("The number of terms belonging to the taxonomy vocabulary."),
   );
 
-  // Chained tokens for taxonomies
-  $term['vocabulary'] = array(
-    'name' => t("Vocabulary"),
-    'description' => t("The vocabulary the taxonomy term belongs to."),
-    'type' => 'vocabulary',
-  );
-  $term['parent'] = array(
-    'name' => t("Parent term"),
-    'description' => t("The parent term of the taxonomy term, if one exists."),
-    'type' => 'term',
-  );
-
-  return array(
-    'types' => $types,
-    'tokens' => array(
-      'term' => $term,
-      'vocabulary' => $vocabulary,
-    ),
-  );
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/user/user.tokens.inc b/core/modules/user/user.tokens.inc
index 1c7f16f..a16defc 100644
--- a/core/modules/user/user.tokens.inc
+++ b/core/modules/user/user.tokens.inc
@@ -9,53 +9,52 @@
  * Implements hook_token_info().
  */
 function user_token_info() {
-  $types['user'] = array(
+  // Tokens for any user.
+  $tokens['user'] = array(
     'name' => t('Users'),
     'description' => t('Tokens related to individual user accounts.'),
     'needs-data' => 'user',
   );
-  $types['current-user'] = array(
-    'name' => t('Current user'),
-    'description' => t('Tokens related to the currently logged in user.'),
-    'type' => 'user',
-  );
-
-  $user['uid'] = array(
+  $tokens['user']['tokens']['uid'] = array(
     'name' => t('User ID'),
     'description' => t("The unique ID of the user account."),
   );
-  $user['name'] = array(
+  $tokens['user']['tokens']['name'] = array(
     'name' => t("Name"),
     'description' => t("The login name of the user account."),
   );
-  $user['mail'] = array(
+  $tokens['user']['tokens']['mail'] = array(
     'name' => t("Email"),
     'description' => t("The email address of the user account."),
   );
-  $user['url'] = array(
+  $tokens['user']['tokens']['url'] = array(
     'name' => t("URL"),
     'description' => t("The URL of the account profile page."),
   );
-  $user['edit-url'] = array(
+  $tokens['user']['tokens']['edit-url'] = array(
     'name' => t("Edit URL"),
     'description' => t("The URL of the account edit page."),
   );
 
-  $user['last-login'] = array(
+  $tokens['user']['tokens']['last-login'] = array(
     'name' => t("Last login"),
     'description' => t("The date the user last logged in to the site."),
     'type' => 'date',
   );
-  $user['created'] = array(
+  $tokens['user']['tokens']['created'] = array(
     'name' => t("Created"),
     'description' => t("The date the user account was created."),
     'type' => 'date',
   );
 
-  return array(
-    'types' => $types,
-    'tokens' => array('user' => $user),
+  // The currently logged in user.
+  $tokens['current-user'] = array(
+    'name' => t('Current user'),
+    'description' => t('Tokens related to the currently logged in user.'),
+    'type' => 'user',
   );
+
+  return $tokens;
 }
 
 /**
diff --git a/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php b/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php
index 1139f3d..1ef9b1a 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/views/PluginBase.php
@@ -277,13 +277,13 @@ public function getAvailableGlobalTokens($prepared = FALSE, array $types = array
     $info = \Drupal::token()->info();
     // Site and view tokens should always be available.
     $types += array('site', 'view');
-    $available = array_intersect_key($info['tokens'], array_flip($types));
+    $available = array_intersect_key($info, array_flip($types));
 
     // Construct the token string for each token.
     if ($prepared) {
       $prepared = array();
-      foreach ($available as $type => $tokens) {
-        foreach (array_keys($tokens) as $token) {
+      foreach ($available as $type => $type_info) {
+        foreach (array_keys($type_info['tokens']) as $token) {
           $prepared[$type][] = "[$type:$token]";
         }
       }
@@ -305,12 +305,12 @@ public function getAvailableGlobalTokens($prepared = FALSE, array $types = array
   public function globalTokenForm(&$form, &$form_state) {
     $token_items = array();
 
-    foreach ($this->getAvailableGlobalTokens() as $type => $tokens) {
+    foreach ($this->getAvailableGlobalTokens() as $type => $type_info) {
       $item = array(
         '#markup' => $type,
         'children' => array(),
       );
-      foreach ($tokens as $name => $info) {
+      foreach ($type_info['tokens'] as $name => $info) {
         $item['children'][$name] = "[$type:$name]" . ' - ' . $info['name'] . ': ' . $info['description'];
       }
 
diff --git a/core/modules/views/lib/Drupal/views/Tests/Handler/AreaTest.php b/core/modules/views/lib/Drupal/views/Tests/Handler/AreaTest.php
index b8e5f6f..6a216d1 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Handler/AreaTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Handler/AreaTest.php
@@ -140,7 +140,7 @@ public function testRenderAreaToken() {
     foreach (array('site', 'view') as $type) {
       $this->assertTrue(!empty($available[$type]) && is_array($available[$type]));
       // Test that each item exists in the list.
-      foreach ($available[$type] as $token => $info) {
+      foreach ($available[$type]['tokens'] as $token => $info) {
         $this->assertText("[$type:$token]");
       }
     }
diff --git a/core/modules/views/views.tokens.inc b/core/modules/views/views.tokens.inc
index 70c354a..87f5e2c 100644
--- a/core/modules/views/views.tokens.inc
+++ b/core/modules/views/views.tokens.inc
@@ -9,58 +9,58 @@
  * Implements hook_token_info().
  */
 function views_token_info() {
-  $info['types']['view'] = array(
+  $tokens['view'] = array(
     'name' => t('View'),
     'description' => t('Tokens related to views.'),
     'needs-data' => 'view',
   );
-  $info['tokens']['view']['label'] = array(
+  $tokens['view']['tokens']['label'] = array(
     'name' => t('Label'),
     'description' => t('The label of the view.'),
   );
-  $info['tokens']['view']['description'] = array(
+  $tokens['view']['tokens']['description'] = array(
     'name' => t('Description'),
     'description' => t('The description of the view.'),
   );
-  $info['tokens']['view']['id'] = array(
+  $tokens['view']['tokens']['id'] = array(
     'name' => t('ID'),
     'description' => t('The machine-readable ID of the view.'),
   );
-  $info['tokens']['view']['title'] = array(
+  $tokens['view']['tokens']['title'] = array(
     'name' => t('Title'),
     'description' => t('The title of current display of the view.'),
   );
-  $info['tokens']['view']['url'] = array(
+  $tokens['view']['tokens']['url'] = array(
     'name' => t('URL'),
     'description' => t('The URL of the view.'),
     'type' => 'url',
   );
-  $info['tokens']['view']['base-table'] = array(
+  $tokens['view']['tokens']['base-table'] = array(
     'name' => t('Base table'),
     'description' => t('The base table used for this view.'),
   );
-  $info['tokens']['view']['base-field'] = array(
+  $tokens['view']['tokens']['base-field'] = array(
     'name' => t('Base field'),
     'description' => t('The base field used for this view.'),
   );
-  $info['tokens']['view']['total-rows'] = array(
+  $tokens['view']['tokens']['total-rows'] = array(
     'name' => t('Total rows'),
     'description' => t('The total amount of results returned from the view. The current display will be used.'),
   );
-  $info['tokens']['view']['items-per-page'] = array(
+  $tokens['view']['tokens']['items-per-page'] = array(
     'name' => t('Items per page'),
     'description' => t('The number of items per page.'),
   );
-  $info['tokens']['view']['current-page'] = array(
+  $tokens['view']['tokens']['current-page'] = array(
     'name' => t('Current page'),
     'description' => t('The current page of results the view is on.'),
   );
-  $info['tokens']['view']['page-count'] = array(
+  $tokens['view']['tokens']['page-count'] = array(
     'name' => t('Page count'),
     'description' => t('The total page count.'),
   );
 
-  return $info;
+  return $tokens;
 }
 
 /**
