diff --git a/core/includes/common.inc b/core/includes/common.inc
index 29f1ef1..59912bf 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -3,6 +3,7 @@
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Template\Attribute;
 
 /**
  * @file
@@ -2252,11 +2253,7 @@ function drupal_http_header_attributes(array $attributes = array()) {
  * @ingroup sanitization
  */
 function drupal_attributes(array $attributes = array()) {
-  foreach ($attributes as $attribute => &$data) {
-    $data = implode(' ', (array) $data);
-    $data = $attribute . '="' . check_plain($data) . '"';
-  }
-  return $attributes ? ' ' . implode(' ', $attributes) : '';
+  return new Attribute($attributes);
 }
 
 /**
@@ -5877,7 +5874,7 @@ function drupal_render(&$elements) {
   // element is rendered into the final text.
   if (isset($elements['#pre_render'])) {
     foreach ($elements['#pre_render'] as $function) {
-      $elements = $function($elements);
+      $elements = $function($function, $elements);
     }
   }
 
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 7d638f6..1f28f9a 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -2388,9 +2388,6 @@ function template_preprocess(&$variables, $hook) {
   // Tell all templates where they are located.
   $variables['directory'] = path_to_theme();
 
-  // Initialize html class attribute for the current hook.
-  $variables['classes_array'] = array(drupal_html_class($hook));
-
   // Merge in variables that don't depend on hook and don't change during a
   // single page request.
   // Use the advanced drupal_static() pattern, since this is called very often.
@@ -2405,7 +2402,14 @@ function template_preprocess(&$variables, $hook) {
   if (!isset($default_variables) || ($user !== $default_variables['user'])) {
     $default_variables = _template_preprocess_default_variables();
   }
-  $variables += $default_variables;
+  $variables += $default_variables + array(
+    'attributes' => drupal_attributes(array('class' => array())),
+    'title_attributes' => drupal_attributes(array('class' => array())),
+    'content_attributes' => drupal_attributes(array('class' => array())),
+  );
+
+  // Initialize html class attribute for the current hook.
+  $variables['attributes']['class'] = array(drupal_html_class($hook));
 }
 
 /**
@@ -2416,9 +2420,6 @@ function _template_preprocess_default_variables() {
 
   // Variables that don't depend on a database connection.
   $variables = array(
-    'attributes_array' => array(),
-    'title_attributes_array' => array(),
-    'content_attributes_array' => array(),
     'title_prefix' => array(),
     'title_suffix' => array(),
     'user' => $user,
@@ -2450,25 +2451,6 @@ function _template_preprocess_default_variables() {
 }
 
 /**
- * A default process function used to alter variables as late as possible.
- *
- * For more detailed information, see theme().
- *
- */
-function template_process(&$variables, $hook) {
-  // Flatten out classes.
-  $variables['classes'] = implode(' ', $variables['classes_array']);
-
-  // Flatten out attributes, title_attributes, and content_attributes.
-  // Because this function can be called very often, and often with empty
-  // attributes, optimize performance by only calling drupal_attributes() if
-  // necessary.
-  $variables['attributes'] = $variables['attributes_array'] ? drupal_attributes($variables['attributes_array']) : '';
-  $variables['title_attributes'] = $variables['title_attributes_array'] ? drupal_attributes($variables['title_attributes_array']) : '';
-  $variables['content_attributes'] = $variables['content_attributes_array'] ? drupal_attributes($variables['content_attributes_array']) : '';
-}
-
-/**
  * Preprocess variables for html.tpl.php
  *
  * @see system_elements()
@@ -2480,22 +2462,24 @@ function template_preprocess_html(&$variables) {
   // Compile a list of classes that are going to be applied to the body element.
   // This allows advanced theming based on context (home page, node of certain type, etc.).
   // Add a class that tells us whether we're on the front page or not.
-  $variables['classes_array'][] = $variables['is_front'] ? 'front' : 'not-front';
+  $variables['attributes']['class'][] = $variables['is_front'] ? 'front' : 'not-front';
   // Add a class that tells us whether the page is viewed by an authenticated user or not.
-  $variables['classes_array'][] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
+  $variables['attributes']['class'][] = $variables['logged_in'] ? 'logged-in' : 'not-logged-in';
 
   // Add information about the number of sidebars.
   if (!empty($variables['page']['sidebar_first']) && !empty($variables['page']['sidebar_second'])) {
-    $variables['classes_array'][] = 'two-sidebars';
+    $variables['attributes']['class'][] = 'two-sidebars';
   }
   elseif (!empty($variables['page']['sidebar_first'])) {
-    $variables['classes_array'][] = 'one-sidebar sidebar-first';
+    $variables['attributes']['class'][] = 'one-sidebar';
+    $variables['attributes']['class'][] = 'sidebar-first';
   }
   elseif (!empty($variables['page']['sidebar_second'])) {
-    $variables['classes_array'][] = 'one-sidebar sidebar-second';
+    $variables['attributes']['class'][] = 'one-sidebar';
+    $variables['attributes']['class'][] = 'sidebar-second';
   }
   else {
-    $variables['classes_array'][] = 'no-sidebars';
+    $variables['attributes']['class'][] = 'no-sidebars';
   }
 
   // Populate the body classes.
@@ -2505,23 +2489,22 @@ function template_preprocess_html(&$variables) {
         // Add current suggestion to page classes to make it possible to theme
         // the page depending on the current page type (e.g. node, admin, user,
         // etc.) as well as more specific data like node-12 or node-edit.
-        $variables['classes_array'][] = drupal_html_class($suggestion);
+        $variables['attributes']['class'][] = drupal_html_class($suggestion);
       }
     }
   }
 
   // If on an individual node page, add the node type to body classes.
   if ($node = menu_get_object()) {
-    $variables['classes_array'][] = drupal_html_class('node-type-' . $node->type);
+    $variables['attributes']['class'][] = drupal_html_class('node-type-' . $node->type);
   }
 
   // Initializes attributes which are specific to the html and body elements.
-  $variables['html_attributes_array'] = array();
-  $variables['body_attributes_array'] = array();
+  $variables['html_attributes'] = array();
 
   // HTML element attributes.
-  $variables['html_attributes_array']['lang'] = $language_interface->langcode;
-  $variables['html_attributes_array']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
+  $variables['html_attributes']['lang'] = $language_interface->langcode;
+  $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
 
   // Add favicon.
   if (theme_get_setting('toggle_favicon')) {
@@ -2655,9 +2638,8 @@ function template_process_page(&$variables) {
  * @see html.tpl.php
  */
 function template_process_html(&$variables) {
-  // Flatten out html_attributes and body_attributes.
-  $variables['html_attributes'] = drupal_attributes($variables['html_attributes_array']);
-  $variables['body_attributes'] = drupal_attributes($variables['body_attributes_array']);
+  // Flatten out html_attributes and attributes.
+  $variables['html_attributes'] = drupal_attributes($variables['html_attributes']);
 
   // Render page_top and page_bottom into top level variables.
   $variables['page_top'] = drupal_render($variables['page']['page_top']);
@@ -2676,8 +2658,8 @@ function template_process_html(&$variables) {
  * Generate an array of suggestions from path arguments.
  *
  * This is typically called for adding to the 'theme_hook_suggestions' or
- * 'classes_array' variables from within preprocess functions, when wanting to
- * base the additional suggestions on the path of the current page.
+ * 'attributes' class key variables from within preprocess functions, when
+ * wanting to base the additional suggestions on the path of the current page.
  *
  * @param $args
  *   An array of path arguments, such as from function arg().
@@ -2692,7 +2674,7 @@ function template_process_html(&$variables) {
  * @return
  *   An array of suggestions, suitable for adding to
  *   $variables['theme_hook_suggestions'] within a preprocess function or to
- *   $variables['classes_array'] if the suggestions represent extra CSS classes.
+ *   $variables['attributes']['class'] if the suggestions represent extra CSS classes.
  */
 function theme_get_suggestions($args, $base, $delimiter = '__') {
 
@@ -2819,18 +2801,19 @@ function template_preprocess_maintenance_page(&$variables) {
   $variables['title']             = drupal_get_title();
 
   // Compile a list of classes that are going to be applied to the body element.
-  $variables['classes_array'][] = 'in-maintenance';
+  $variables['attributes']['class'][] = 'in-maintenance';
   if (isset($variables['db_is_active']) && !$variables['db_is_active']) {
-    $variables['classes_array'][] = 'db-offline';
+    $variables['attributes']['class'][] = 'db-offline';
   }
   if ($variables['layout'] == 'both') {
-    $variables['classes_array'][] = 'two-sidebars';
+    $variables['attributes']['class'][] = 'two-sidebars';
   }
   elseif ($variables['layout'] == 'none') {
-    $variables['classes_array'][] = 'no-sidebars';
+    $variables['attributes']['class'][] = 'no-sidebars';
   }
   else {
-    $variables['classes_array'][] = 'one-sidebar sidebar-' . $variables['layout'];
+    $variables['attributes']['class'][] = 'one-sidebar';
+    $variables['attributes']['class'][] = 'sidebar-' . $variables['layout'];
   }
 
   // Dead databases will show error messages so supplying this template will
@@ -2868,6 +2851,6 @@ function template_preprocess_region(&$variables) {
   $variables['content'] = $variables['elements']['#children'];
   $variables['region'] = $variables['elements']['#region'];
 
-  $variables['classes_array'][] = drupal_region_class($variables['region']);
+  $variables['attributes']['class'][] = drupal_region_class($variables['region']);
   $variables['theme_hook_suggestions'][] = 'region__' . $variables['region'];
 }
diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
new file mode 100644
index 0000000..1d40932
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\Attribute.
+ */
+
+namespace Drupal\Core\Template;
+use ArrayAccess;
+use Twig_Markup;
+
+/**
+ * A class that can be used for collecting then rendering HTML attributtes.
+ *
+ * To use, one may both pass in an array of already defined attributes and
+ * add attributes to it like using array.syntax.
+ * @code
+ *  $attributes = new Attribute(array('id' => 'socks'));
+ *  $attributes['class'] = array('black-cat', 'white-cat');
+ *  $attributes['class'][] = 'black-white-cat';
+ *  echo '<cat ' . $attributes . '>';
+ *  // Produces <cat id="socks" class="black-cat white-cat black-white-cat">
+ * @endcode
+ *
+ * Indivudal parts of the attribute may be printed first.
+ * @code
+ *  $attributes = new Attribute(array('id' => 'socks'));
+ *  $attributes['class'] = array('black-cat', 'white-cat');
+ *  $attributes['class'][] = 'black-white-cat';
+ *  echo '<cat class="cat ' . $attributes['class'] . '" ' . $attributes . '>';
+ *  // Produces <cat class="cat black-cat white-cat black-white-cat" id="socks">
+ * @endcode
+ *
+ * Once it's turned into a string, it cannot be re-used.
+ *
+ * @see drupal_attributes()
+ */
+class Attribute implements ArrayAccess {
+  protected $storage = array();
+  function __construct($attributes) {
+    foreach ($attributes as $name => $value) {
+      $this->offsetSet($name, $value);
+    }
+  }
+
+  function offsetGet($name) {
+    if (isset($this->storage[$name])) {
+      return $this->storage[$name];
+    }
+  }
+
+  function offsetSet($name, $value) {
+    if (!is_object($value) || $value instanceOf Twig_Markup) {
+      if (is_array($value)) {
+        $value = new AttributeArray($name, $value);
+      }
+      elseif (is_bool($value)) {
+        $value = new AttributeBoolean($name, $value);
+      }
+      else {
+        $value = new AttributeString($name, $value);
+      }
+    }
+    // The $name could be NULL.
+    if (isset($name)) {
+      $this->storage[$name] = $value;
+    }
+    else {
+      $this->storage[] = $value;
+    }
+  }
+
+  function offsetUnset($name) {
+    unset($this->storage[$name]);
+  }
+
+  function offsetExists($name) {
+    return isset($this->storage[$name]);
+  }
+  function __toString() {
+    $return = '';
+    foreach ($this->storage as $name => $value) {
+      if (!$value->printed()) {
+        $rendered = is_object($value) ? $value->render() : (check_plain($name) . ' = "' . check_plain($value) . '"');
+        if ($rendered) {
+          $return .= " $rendered";
+        }
+      }
+    }
+    return $return;
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/AttributeArray.php b/core/lib/Drupal/Core/Template/AttributeArray.php
new file mode 100644
index 0000000..140ce42
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/AttributeArray.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\AttributeArray.
+ */
+
+/**
+ * A class that defines a type of Attribute that can be added to as an array.
+ *
+ * To use with Attribute, the array must be specified.
+ * Correct:
+ * @code
+ *  $attributes = new Attribute(array());
+ *  $attributes['class'] = array();
+ *  $attributes['class'][] = 'cat';
+ * @endcode
+ * Incorrect:
+ * @code
+ *  $attributes = new Attribute(array());
+ *  $attributes['class'][] = 'cat';
+ * @endcode
+ *
+ * @see Drupal\Core\Template\Attribute
+ */
+namespace Drupal\Core\Template;
+use ArrayAccess;
+
+class AttributeArray extends AttributeValue implements ArrayAccess {
+  function offsetGet($offset) {
+    return $this->value[$offset];
+  }
+
+  function offsetSet($offset, $value) {
+    if (isset($offset)) {
+      $this->value[$offset] = $value;
+    }
+    else {
+      $this->value[] = $value;
+    }
+  }
+
+  function offsetUnset($offset) {
+    unset($this->value[$offset]);
+  }
+
+  function offsetExists($offset) {
+    return isset($this->value[$offset]);
+  }
+  function value() {
+    return $this->value;
+  }
+
+  function __toString() {
+    $this->printed = TRUE;
+    return implode(' ', array_map('check_plain', $this->value));
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/AttributeBoolean.php b/core/lib/Drupal/Core/Template/AttributeBoolean.php
new file mode 100644
index 0000000..722520b
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/AttributeBoolean.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\AttributeBoolean.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * A class that defines a type of boolean HTML attribute.
+ *
+ * Boolean HTML attributes are not attributes with values of TRUE/FALSE.
+ * They are attributes that if they exist in the tag, they are TRUE.
+ * Examples include selected, disabled, checked, readonly.
+ *
+ * To set a boolean attribute on the Attribute class, set it to TRUE.
+ * @code
+ *  $attributes = new Attribute(array());
+ *  $attributes['disabled'] = TRUE;
+ *  echo '<select ' . $attributes . '/>';
+ *  // produces <select disabled>;
+ *  $attributes['disabled'] = FALSE;
+ *  echo '<select ' . $attributes . '/>';
+ *  // produces <select>;
+ * @endcode
+ *
+ * @see Drupal\Core\Template\Attribute
+ */
+class AttributeBoolean extends AttributeValue {
+  function render() {
+    return $this->__toString();
+  }
+  function __toString() {
+    $this->printed = TRUE;
+    return $this->value === FALSE ? '' : check_plain($this->name);
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/AttributeString.php b/core/lib/Drupal/Core/Template/AttributeString.php
new file mode 100644
index 0000000..3e380a2
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/AttributeString.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\AttributeString.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * A class that the most standard HTML attribute.
+ *
+ * To use with the Attribute class, set the key to be the attribute name
+ * and the value the attribute value.
+ * @code
+ *  $attributes = new Attribute(array());
+ *  $attributes['id'] = 'socks';
+ *  $attributes['style'] = 'background-color:white';
+ *  echo '<cat ' . $attributes . '>';
+ *  // Produces: <cat id="socks" style="background-color:white">.
+ * @endcode
+ *
+ * @see Drupal\Core\Template\Attribute
+ */
+class AttributeString extends AttributeValue {
+  function __toString() {
+    $this->printed = TRUE;
+    return check_plain($this->value);
+  }
+}
diff --git a/core/lib/Drupal/Core/Template/AttributeValue.php b/core/lib/Drupal/Core/Template/AttributeValue.php
new file mode 100644
index 0000000..7f95e15
--- /dev/null
+++ b/core/lib/Drupal/Core/Template/AttributeValue.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Template\AttributeValue.
+ */
+
+namespace Drupal\Core\Template;
+
+/**
+ * Defines the base class for an attribute type.
+ *
+ * @see Drupal\Core\Template\Attribute
+ */
+abstract class AttributeValue {
+  protected $printed = FALSE, $value, $name;
+
+  function __construct($name, $value) {
+    $this->name = $name;
+    $this->value = $value;
+  }
+
+  function render() {
+    return check_plain($this->name) . '="' . $this . '"';
+  }
+
+  function printed() {
+    return $this->printed;
+  }
+  abstract function __toString();
+}
diff --git a/core/modules/aggregator/aggregator-wrapper.tpl.php b/core/modules/aggregator/aggregator-wrapper.tpl.php
index 7cac5bf..0e97ba4 100644
--- a/core/modules/aggregator/aggregator-wrapper.tpl.php
+++ b/core/modules/aggregator/aggregator-wrapper.tpl.php
@@ -14,7 +14,7 @@
  * @ingroup themeable
  */
 ?>
-<div class="<?php print $classes; ?>">
+<div class="<?php print $attributes['class']; ?>">
   <?php print $content; ?>
   <?php print $pager; ?>
 </div>
diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module
index 0626f72..3e9850c 100644
--- a/core/modules/aggregator/aggregator.module
+++ b/core/modules/aggregator/aggregator.module
@@ -793,6 +793,6 @@ function _aggregator_items($count) {
  */
 function aggregator_preprocess_block(&$variables) {
   if ($variables['block']->module == 'aggregator') {
-    $variables['attributes_array']['role'] = 'complementary';
+    $variables['attributes']['role'] = 'complementary';
   }
 }
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 97f59e9..bc63939 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -998,10 +998,10 @@ function template_preprocess_block(&$variables) {
   // Create the $content variable that templates expect.
   $variables['content'] = $variables['elements']['#children'];
 
-  $variables['classes_array'][] = drupal_html_class('block-' . $variables['block']->module);
+  $variables['attributes']['class'][] = drupal_html_class('block-' . $variables['block']->module);
 
   // Add default class for block content.
-  $variables['content_attributes_array']['class'][] = 'content';
+  $variables['content_attributes']['class'][] = 'content';
 
   $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->region;
   $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module;
diff --git a/core/modules/block/block.tpl.php b/core/modules/block/block.tpl.php
index 78387a8..2b32f65 100644
--- a/core/modules/block/block.tpl.php
+++ b/core/modules/block/block.tpl.php
@@ -10,10 +10,9 @@
  * - $block->module: Module that generated the block.
  * - $block->delta: An ID for the block, unique within each module.
  * - $block->region: The block region embedding the current block.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - block: The current template type, i.e., "theming hook".
  *   - block-[module]: The module generating the block. For example, the user
  *     module is responsible for handling the default user navigation block. In
@@ -26,8 +25,6 @@
  *   the template.
  *
  * Helper variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
  * - $zebra: Same output as $block_zebra but independent of any block region.
  * - $block_id: Counter dependent on each block region.
@@ -44,7 +41,7 @@
  * @ingroup themeable
  */
 ?>
-<div id="<?php print $block_html_id; ?>" class="<?php print $classes; ?>"<?php print $attributes; ?>>
+<div id="<?php print $block_html_id; ?>" <?php print $attributes; ?>>
 
   <?php print render($title_prefix); ?>
 <?php if ($block->subject): ?>
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index bbdfab3..a453354 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -1069,7 +1069,7 @@ function _book_link_defaults($nid) {
  */
 function book_preprocess_block(&$variables) {
   if ($variables['block']-> module == 'book') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
 
@@ -1233,8 +1233,8 @@ function template_preprocess_book_export_html(&$variables) {
   $variables['head'] = drupal_get_html_head();
 
   // HTML element attributes.
-  $variables['html_attributes_array']['lang'] = $language_interface->langcode;
-  $variables['html_attributes_array']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
+  $variables['html_attributes']['lang'] = $language_interface->langcode;
+  $variables['html_attributes']['dir'] = $language_interface->direction ? 'rtl' : 'ltr';
 }
 
 /**
@@ -1244,7 +1244,7 @@ function template_preprocess_book_export_html(&$variables) {
  */
 function template_process_book_export_html(&$variables) {
   // Flatten out html_attributes
-  $variables['html_attributes'] = drupal_attributes($variables['html_attributes_array']);
+  $variables['html_attributes'] = drupal_attributes($variables['html_attributes']);
 }
 
 /**
diff --git a/core/modules/comment/comment-wrapper.tpl.php b/core/modules/comment/comment-wrapper.tpl.php
index 1f97851..1e2e10f 100644
--- a/core/modules/comment/comment-wrapper.tpl.php
+++ b/core/modules/comment/comment-wrapper.tpl.php
@@ -8,9 +8,9 @@
  * - $content: The array of content-related elements for the node. Use
  *   render($content) to print them all, or
  *   print a subset such as render($content['comment_form']).
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default value has the following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - comment-wrapper: The current template type, i.e., "theming hook".
  * - $title_prefix (array): An array containing additional output populated by
  *   modules, intended to be displayed in front of the main title tag that
@@ -27,15 +27,11 @@
  *   - COMMENT_MODE_FLAT
  *   - COMMENT_MODE_THREADED
  *
- * Other variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess_comment_wrapper()
  * @see theme_comment_wrapper()
  */
 ?>
-<section id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
+<section id="comments" <?php print $attributes; ?>>
   <?php if ($content['comments'] && $node->type != 'forum'): ?>
     <?php print render($title_prefix); ?>
     <h2 class="title"><?php print t('Comments'); ?></h2>
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 58ea4a6..3438787 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -2101,7 +2101,7 @@ function comment_form_submit($form, &$form_state) {
  */
 function comment_preprocess_block(&$variables) {
   if ($variables['block']->module == 'comment') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
 
@@ -2149,20 +2149,20 @@ function template_preprocess_comment(&$variables) {
   // Gather comment classes.
   // 'published' class is not needed, it is either 'preview' or 'unpublished'.
   if ($variables['status'] != 'published') {
-    $variables['classes_array'][] = $variables['status'];
+    $variables['attributes']['class'][] = $variables['status'];
   }
   if ($variables['new']) {
-    $variables['classes_array'][] = 'new';
+    $variables['attributes']['class'][] = 'new';
   }
   if (!$comment->uid) {
-    $variables['classes_array'][] = 'by-anonymous';
+    $variables['attributes']['class'][] = 'by-anonymous';
   }
   else {
     if ($comment->uid == $variables['node']->uid) {
-      $variables['classes_array'][] = 'by-node-author';
+      $variables['attributes']['class'][] = 'by-node-author';
     }
     if ($comment->uid == $variables['user']->uid) {
-      $variables['classes_array'][] = 'by-viewer';
+      $variables['attributes']['class'][] = 'by-viewer';
     }
   }
 }
diff --git a/core/modules/comment/comment.tpl.php b/core/modules/comment/comment.tpl.php
index e94e6e4..897d0f4 100644
--- a/core/modules/comment/comment.tpl.php
+++ b/core/modules/comment/comment.tpl.php
@@ -25,10 +25,9 @@
  * - $status: Comment status. Possible values are:
  *   unpublished, published, or preview.
  * - $title: Linked title.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - comment: The current template type; e.g., 'theming hook'.
  *   - by-anonymous: Comment by an unregistered user.
  *   - by-node-author: Comment by the author of the parent node.
@@ -48,17 +47,13 @@
  * - $comment: Full comment object.
  * - $node: Node entity the comments are attached to.
  *
- * Other variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess()
  * @see template_preprocess_comment()
  * @see template_process()
  * @see theme_comment()
  */
 ?>
-<article class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+<article class="<?php print $attributes['class']; ?> clearfix"<?php print $attributes; ?>>
 
   <?php print render($title_prefix); ?>
   <?php if ($new): ?>
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index 844e9ee..a09d09f 100644
--- a/core/modules/contextual/contextual.module
+++ b/core/modules/contextual/contextual.module
@@ -108,7 +108,7 @@ function contextual_preprocess(&$variables, $hook) {
       '#element' => $element,
     );
     // Mark this element as potentially having contextual links attached to it.
-    $variables['classes_array'][] = 'contextual-region';
+    $variables['attributes']['class'][] = 'contextual-region';
   }
 }
 
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index e0229a6..32ff01e 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -1037,7 +1037,7 @@ function template_preprocess_field(&$variables, $hook) {
   // drupal_html_class().
   $variables['field_name_css'] = strtr($element['#field_name'], '_', '-');
   $variables['field_type_css'] = strtr($element['#field_type'], '_', '-');
-  $variables['classes_array'] = array(
+  $variables['attributes']['class'] = array(
     'field',
     'field-name-' . $variables['field_name_css'],
     'field-type-' . $variables['field_type_css'],
@@ -1046,7 +1046,7 @@ function template_preprocess_field(&$variables, $hook) {
   // Add a "clearfix" class to the wrapper since we float the label and the
   // field items in field.css if the label is inline.
   if ($element['#label_display'] == 'inline') {
-    $variables['classes_array'][] = 'clearfix';
+    $variables['attributes']['class'][] = 'clearfix';
   }
 
   // Add specific suggestions that can override the default implementation.
@@ -1069,13 +1069,12 @@ function template_process_field(&$variables, $hook) {
   // not automatically run, so we need to flatten the classes and attributes
   // here. For best performance, only call drupal_attributes() when needed, and
   // note that template_preprocess_field() does not initialize the
-  // *_attributes_array variables.
-  $variables['classes'] = implode(' ', $variables['classes_array']);
-  $variables['attributes'] = empty($variables['attributes_array']) ? '' : drupal_attributes($variables['attributes_array']);
-  $variables['title_attributes'] = empty($variables['title_attributes_array']) ? '' : drupal_attributes($variables['title_attributes_array']);
-  $variables['content_attributes'] = empty($variables['content_attributes_array']) ? '' : drupal_attributes($variables['content_attributes_array']);
+  // *_attributes variables.
+  $variables['attributes'] = empty($variables['attributes']) ? '' : drupal_attributes($variables['attributes']);
+  $variables['title_attributes'] = empty($variables['title_attributes']) ? '' : drupal_attributes($variables['title_attributes']);
+  $variables['content_attributes'] = empty($variables['content_attributes']) ? '' : drupal_attributes($variables['content_attributes']);
   foreach ($variables['items'] as $delta => $item) {
-    $variables['item_attributes'][$delta] = empty($variables['item_attributes_array'][$delta]) ? '' : drupal_attributes($variables['item_attributes_array'][$delta]);
+    $variables['item_attributes'][$delta] = empty($variables['item_attributes'][$delta]) ? '' : drupal_attributes($variables['item_attributes'][$delta]);
   }
 }
 /**
@@ -1159,7 +1158,7 @@ function theme_field($variables) {
   $output .= '</div>';
 
   // Render the top-level DIV.
-  $output = '<div class="' . $variables['classes'] . '"' . $variables['attributes'] . '>' . $output . '</div>';
+  $output = '<div ' . $variables['attributes'] . '>' . $output . '</div>';
 
   return $output;
 }
diff --git a/core/modules/field/theme/field.tpl.php b/core/modules/field/theme/field.tpl.php
index c496908..0743062 100644
--- a/core/modules/field/theme/field.tpl.php
+++ b/core/modules/field/theme/field.tpl.php
@@ -11,10 +11,9 @@
  * - $items: An array of field values. Use render() to output them.
  * - $label: The item label.
  * - $label_hidden: Whether the label display is set to 'hidden'.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - field: The current template type, i.e., "theming hook".
  *   - field-name-[field_name]: The current field name. For example, if the
  *     field name is "field_description" it would result in
@@ -35,8 +34,6 @@
  *   hidden.
  * - $field_name_css: The css-compatible field name.
  * - $field_type_css: The css-compatible field type.
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  *
  * @see template_preprocess_field()
  * @see theme_field()
@@ -48,7 +45,7 @@ See http://api.drupal.org/api/function/theme_field/8 for details.
 After copying this file to your theme's folder and customizing it, remove this
 HTML comment.
 -->
-<div class="<?php print $classes; ?>"<?php print $attributes; ?>>
+<div class="<?php print $attributes['class']; ?>"<?php print $attributes; ?>>
   <?php if (!$label_hidden): ?>
     <div class="field-label"<?php print $title_attributes; ?>><?php print $label ?>:&nbsp;</div>
   <?php endif; ?>
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 28e7f17..384ef36 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -997,7 +997,7 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
  */
 function forum_preprocess_block(&$variables) {
   if ($variables['block']->module == 'forum') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
 
diff --git a/core/modules/help/help.module b/core/modules/help/help.module
index dbc836c..26ef533 100644
--- a/core/modules/help/help.module
+++ b/core/modules/help/help.module
@@ -70,6 +70,6 @@ function help_help($path, $arg) {
  */
 function help_preprocess_block(&$variables) {
   if ($variables['block']->module == 'system' && $variables['block']->delta == 'help') {
-    $variables['attributes_array']['role'] = 'complementary';
+    $variables['attributes']['role'] = 'complementary';
   }
 }
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 7acc783..72737b4 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -481,7 +481,7 @@ function language_block_view($type) {
  */
 function language_preprocess_block(&$variables) {
   if ($variables['block']->module == 'language') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
 
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 35f8032..6484861 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -792,12 +792,12 @@ function locale_preprocess_node(&$variables) {
       // If the node language was different from the page language, we should
       // add markup to identify the language. Otherwise the page language is
       // inherited.
-      $variables['attributes_array']['lang'] = $variables['langcode'];
+      $variables['attributes']['lang'] = $variables['langcode'];
       if ($node_language->direction != $language_interface->direction) {
         // If text direction is different form the page's text direction, add
         // direction information as well.
         $dir = array('ltr', 'rtl');
-        $variables['attributes_array']['dir'] = $dir[$node_language->direction];
+        $variables['attributes']['dir'] = $dir[$node_language->direction];
       }
     }
   }
diff --git a/core/modules/menu/menu.module b/core/modules/menu/menu.module
index 466cd88..803b9e8 100644
--- a/core/modules/menu/menu.module
+++ b/core/modules/menu/menu.module
@@ -800,6 +800,6 @@ function menu_get_menus($all = TRUE) {
  */
 function menu_preprocess_block(&$variables) {
   if ($variables['block']->module == 'menu') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index d2d4bad..edd3ead 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1291,10 +1291,10 @@ function node_preprocess_block(&$variables) {
   if ($variables['block']->module == 'node') {
     switch ($variables['block']->delta) {
       case 'syndicate':
-        $variables['attributes_array']['role'] = 'complementary';
+        $variables['attributes']['role'] = 'complementary';
         break;
       case 'recent':
-        $variables['attributes_array']['role'] = 'navigation';
+        $variables['attributes']['role'] = 'navigation';
         break;
     }
   }
@@ -1358,24 +1358,24 @@ function template_preprocess_node(&$variables) {
   }
 
   // Add article ARIA role.
-  $variables['attributes_array']['role'] = 'article';
+  $variables['attributes']['role'] = 'article';
 
   // Gather node classes.
-  $variables['classes_array'][] = drupal_html_class('node-' . $node->type);
+  $variables['attributes']['class'][] = drupal_html_class('node-' . $node->type);
   if ($variables['promote']) {
-    $variables['classes_array'][] = 'promoted';
+    $variables['attributes']['class'][] = 'promoted';
   }
   if ($variables['sticky']) {
-    $variables['classes_array'][] = 'sticky';
+    $variables['attributes']['class'][] = 'sticky';
   }
   if (!$variables['status']) {
-    $variables['classes_array'][] = 'unpublished';
+    $variables['attributes']['class'][] = 'unpublished';
   }
   if ($variables['view_mode']) {
-    $variables['classes_array'][] = drupal_html_class('view-mode-' . $variables['view_mode']);
+    $variables['attributes']['class'][] = drupal_html_class('view-mode-' . $variables['view_mode']);
   }
   if (isset($variables['preview'])) {
-    $variables['classes_array'][] = 'preview';
+    $variables['attributes']['class'][] = 'preview';
   }
 
   // Clean up name so there are no underscores.
diff --git a/core/modules/node/node.tpl.php b/core/modules/node/node.tpl.php
index c3db5ae..67efca8 100644
--- a/core/modules/node/node.tpl.php
+++ b/core/modules/node/node.tpl.php
@@ -18,10 +18,9 @@
  * - $display_submitted: Whether submission information should be displayed.
  * - $submitted: Submission information created from $name and $date during
  *   template_preprocess_node().
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - node: The current template type, i.e., "theming hook".
  *   - node-[type]: The current node type. For example, if the node is a
  *     "Article" it would result in "node-article". Note that the machine
@@ -46,8 +45,6 @@
  * - $comment_count: Number of comments attached to the node.
  * - $uid: User ID of the node author.
  * - $created: Time the node was published formatted in Unix timestamp.
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
  *   teaser listings.
  * - $id: Position of the node. Increments each time it's output.
@@ -78,7 +75,7 @@
  * @see template_process()
  */
 ?>
-<article id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+<article id="node-<?php print $node->nid; ?>" class="<?php print $attributes['class']; ?> clearfix"<?php print $attributes; ?>>
 
   <?php print render($title_prefix); ?>
   <?php if (!$page): ?>
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index 5fdd453..3014b89 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -480,7 +480,7 @@ function overlay_system_info_alter(&$info, $file, $type) {
 function overlay_preprocess_html(&$variables) {
   if (overlay_get_mode() == 'child') {
     // Add overlay class, so themes can react to being displayed in the overlay.
-    $variables['classes_array'][] = 'overlay';
+    $variables['attributes']['class'][] = 'overlay';
   }
 }
 
@@ -503,7 +503,7 @@ function template_preprocess_overlay(&$variables) {
   $variables['tabs'] = menu_primary_local_tasks();
   $variables['title'] = drupal_get_title();
   $variables['disable_overlay'] = overlay_disable_message();
-  $variables['content_attributes_array']['class'][] = 'clearfix';
+  $variables['content_attributes']['class'][] = 'clearfix';
 }
 
 /**
diff --git a/core/modules/overlay/overlay.tpl.php b/core/modules/overlay/overlay.tpl.php
index 54b10af..00fa36c 100644
--- a/core/modules/overlay/overlay.tpl.php
+++ b/core/modules/overlay/overlay.tpl.php
@@ -10,10 +10,6 @@
  * - $tabs (array): Tabs linking to any sub-pages beneath the current page
  *   (e.g., the view and edit tabs when displaying a node).
  *
- * Helper variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess()
  * @see template_preprocess_overlay()
  * @see template_process()
diff --git a/core/modules/poll/poll.module b/core/modules/poll/poll.module
index 2e36e0b..f7dc477 100644
--- a/core/modules/poll/poll.module
+++ b/core/modules/poll/poll.module
@@ -777,7 +777,7 @@ function poll_vote($form, &$form_state) {
  */
 function poll_preprocess_block(&$variables) {
   if ($variables['block']->module == 'poll') {
-    $variables['attributes_array']['role'] = 'complementary';
+    $variables['attributes']['role'] = 'complementary';
   }
 }
 
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 43ee4ed..1f7b268 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -438,8 +438,8 @@ function rdf_process(&$variables, $hook) {
   // and field items. It does this by adjusting the variable sent to the
   // template so that the template doesn't have to worry about it. See
   // theme_rdf_template_variable_wrapper().
-  if (!empty($variables['rdf_template_variable_attributes_array'])) {
-    foreach ($variables['rdf_template_variable_attributes_array'] as $variable_name => $attributes) {
+  if (!empty($variables['rdf_template_variable_attributes'])) {
+    foreach ($variables['rdf_template_variable_attributes'] as $variable_name => $attributes) {
       $context = array(
         'hook' => $hook,
         'variable_name' => $variable_name,
@@ -452,11 +452,11 @@ function rdf_process(&$variables, $hook) {
   // reasons, can't be placed into that template's $attributes variable. This
   // is "meta" information that is related to particular content, so render it
   // close to that content.
-  if (!empty($variables['rdf_metadata_attributes_array'])) {
+  if (!empty($variables['rdf_metadata_attributes'])) {
     if (!isset($variables['content']['#prefix'])) {
       $variables['content']['#prefix'] = '';
     }
-    $variables['content']['#prefix'] = theme('rdf_metadata', array('metadata' => $variables['rdf_metadata_attributes_array'])) . $variables['content']['#prefix'];
+    $variables['content']['#prefix'] = theme('rdf_metadata', array('metadata' => $variables['rdf_metadata_attributes'])) . $variables['content']['#prefix'];
   }
 }
 
@@ -468,7 +468,7 @@ function rdf_preprocess_html(&$variables) {
   // attribute inside the html element.
   $prefixes = array();
   foreach(rdf_get_namespaces() as $prefix => $uri) {
-    $variables['html_attributes_array']['prefix'][] = $prefix . ': ' . $uri . "\n";
+    $variables['html_attributes']['prefix'][] = $prefix . ': ' . $uri . "\n";
   }
 }
 
@@ -480,15 +480,15 @@ function rdf_preprocess_node(&$variables) {
   // URI of the resource described within the HTML element, while the @typeof
   // attribute indicates its RDF type (e.g., foaf:Document, sioc:Person, and so
   // on.)
-  $variables['attributes_array']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
-  $variables['attributes_array']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
+  $variables['attributes']['about'] = empty($variables['node_url']) ? NULL: $variables['node_url'];
+  $variables['attributes']['typeof'] = empty($variables['node']->rdf_mapping['rdftype']) ? NULL : $variables['node']->rdf_mapping['rdftype'];
 
   // Adds RDFa markup to the title of the node. Because the RDFa markup is
   // added to the <h2> tag which might contain HTML code, we specify an empty
   // datatype to ensure the value of the title read by the RDFa parsers is a
   // literal.
-  $variables['title_attributes_array']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates'];
-  $variables['title_attributes_array']['datatype'] = '';
+  $variables['title_attributes']['property'] = empty($variables['node']->rdf_mapping['title']['predicates']) ? NULL : $variables['node']->rdf_mapping['title']['predicates'];
+  $variables['title_attributes']['datatype'] = '';
 
   // In full node mode, the title is not displayed by node.tpl.php so it is
   // added in the <head> tag of the HTML page.
@@ -508,17 +508,17 @@ function rdf_preprocess_node(&$variables) {
 
   // Adds RDFa markup for the date.
   if (!empty($variables['rdf_mapping']['created'])) {
-    $date_attributes_array = rdf_rdfa_attributes($variables['rdf_mapping']['created'], $variables['created']);
-    $variables['rdf_template_variable_attributes_array']['date'] = $date_attributes_array;
+    $date_attributes = rdf_rdfa_attributes($variables['rdf_mapping']['created'], $variables['created']);
+    $variables['rdf_template_variable_attributes']['date'] = $date_attributes;
     if ($variables['submitted']) {
-      $variables['rdf_template_variable_attributes_array']['submitted'] = $date_attributes_array;
+      $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
     }
   }
   // Adds RDFa markup for the relation between the node and its author.
   if (!empty($variables['rdf_mapping']['uid'])) {
-    $variables['rdf_template_variable_attributes_array']['name']['rel'] = $variables['rdf_mapping']['uid']['predicates'];
+    $variables['rdf_template_variable_attributes']['name']['rel'] = $variables['rdf_mapping']['uid']['predicates'];
     if ($variables['submitted']) {
-      $variables['rdf_template_variable_attributes_array']['submitted']['rel'] = $variables['rdf_mapping']['uid']['predicates'];
+      $variables['rdf_template_variable_attributes']['submitted']['rel'] = $variables['rdf_mapping']['uid']['predicates'];
     }
   }
 
@@ -565,7 +565,7 @@ function rdf_preprocess_field(&$variables) {
 
   if (!empty($mapping) && !empty($mapping[$field_name])) {
     foreach ($element['#items'] as $delta => $item) {
-      $variables['item_attributes_array'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
+      $variables['item_attributes'][$delta] = rdf_rdfa_attributes($mapping[$field_name], $item);
       // If this field is an image, RDFa will not output correctly when the
       // image is in a containing <a> tag. If the field is a file, RDFa will
       // not output correctly if the filetype icon comes before the link to the
@@ -573,10 +573,10 @@ function rdf_preprocess_field(&$variables) {
       // this field has a URI.
       if (isset($item['uri'])) {
         if (!empty($element[$delta]['#image_style'])) {
-          $variables['item_attributes_array'][$delta]['resource'] = image_style_url($element[$delta]['#image_style'], $item['uri']);
+          $variables['item_attributes'][$delta]['resource'] = image_style_url($element[$delta]['#image_style'], $item['uri']);
         }
         else {
-          $variables['item_attributes_array'][$delta]['resource'] = file_create_url($item['uri']);
+          $variables['item_attributes'][$delta]['resource'] = file_create_url($item['uri']);
         }
       }
     }
@@ -593,8 +593,8 @@ function rdf_preprocess_user_profile(&$variables) {
   // Adds RDFa markup to the user profile page. Fields displayed in this page
   // will automatically describe the user.
   if (!empty($account->rdf_mapping['rdftype'])) {
-    $variables['attributes_array']['typeof'] = $account->rdf_mapping['rdftype'];
-    $variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
+    $variables['attributes']['typeof'] = $account->rdf_mapping['rdftype'];
+    $variables['attributes']['about'] = url($uri['path'], $uri['options']);
   }
   // Adds the relationship between the sioc:UserAccount and the foaf:Person who
   // holds the account.
@@ -629,8 +629,8 @@ function rdf_preprocess_username(&$variables) {
   // might not be transliterated to the same language that the content is in,
   // we do not want it to inherit the language attribute, so we set the
   // attribute to an empty string.
-  if (empty($variables['attributes_array']['lang'])) {
-    $variables['attributes_array']['lang'] = '';
+  if (empty($variables['attributes']['lang'])) {
+    $variables['attributes']['lang'] = '';
   }
 
   // $variables['account'] is a pseudo account object, and as such, does not
@@ -649,7 +649,7 @@ function rdf_preprocess_username(&$variables) {
   // a user profile URI for it (only a homepage which cannot be used as user
   // profile in RDF.)
   if ($variables['uid'] > 0) {
-    $variables['attributes_array']['about'] = url('user/' . $variables['uid']);
+    $variables['attributes']['about'] = url('user/' . $variables['uid']);
   }
 
   $attributes = array();
@@ -672,7 +672,7 @@ function rdf_preprocess_username(&$variables) {
   // (see http://www.w3.org/TR/rdfa-syntax/#rdfa-attributes).
   // Therefore, merge rather than override so as not to clobber values set by
   // earlier preprocess functions.
-  $variables['attributes_array'] = array_merge_recursive($variables['attributes_array'], $attributes);
+  $variables['attributes'] = array_merge_recursive($variables['attributes'], $attributes);
 }
 
 /**
@@ -686,30 +686,30 @@ function rdf_preprocess_comment(&$variables) {
     // typeof attribute indicates its RDF type (e.g., sioc:Post, foaf:Document,
     // and so on.)
     $uri = entity_uri('comment', $comment);
-    $variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
-    $variables['attributes_array']['typeof'] = $comment->rdf_mapping['rdftype'];
+    $variables['attributes']['about'] = url($uri['path'], $uri['options']);
+    $variables['attributes']['typeof'] = $comment->rdf_mapping['rdftype'];
   }
 
   // Adds RDFa markup for the date of the comment.
   if (!empty($comment->rdf_mapping['created'])) {
     // The comment date is precomputed as part of the rdf_data so that it can be
     // cached as part of the entity.
-    $date_attributes_array = $comment->rdf_data['date'];
-    $variables['rdf_template_variable_attributes_array']['created'] = $date_attributes_array;
-    $variables['rdf_template_variable_attributes_array']['submitted'] = $date_attributes_array;
+    $date_attributes = $comment->rdf_data['date'];
+    $variables['rdf_template_variable_attributes']['created'] = $date_attributes;
+    $variables['rdf_template_variable_attributes']['submitted'] = $date_attributes;
   }
   // Adds RDFa markup for the relation between the comment and its author.
   if (!empty($comment->rdf_mapping['uid'])) {
-    $variables['rdf_template_variable_attributes_array']['author']['rel'] = $comment->rdf_mapping['uid']['predicates'];
-    $variables['rdf_template_variable_attributes_array']['submitted']['rel'] = $comment->rdf_mapping['uid']['predicates'];
+    $variables['rdf_template_variable_attributes']['author']['rel'] = $comment->rdf_mapping['uid']['predicates'];
+    $variables['rdf_template_variable_attributes']['submitted']['rel'] = $comment->rdf_mapping['uid']['predicates'];
   }
   if (!empty($comment->rdf_mapping['title'])) {
     // Adds RDFa markup to the subject of the comment. Because the RDFa markup
     // is added to an <h3> tag which might contain HTML code, we specify an
     // empty datatype to ensure the value of the title read by the RDFa parsers
     // is a literal.
-    $variables['title_attributes_array']['property'] = $comment->rdf_mapping['title']['predicates'];
-    $variables['title_attributes_array']['datatype'] = '';
+    $variables['title_attributes']['property'] = $comment->rdf_mapping['title']['predicates'];
+    $variables['title_attributes']['datatype'] = '';
   }
 
   // Annotates the parent relationship between the current comment and the node
@@ -720,7 +720,7 @@ function rdf_preprocess_comment(&$variables) {
     // The parent node URI is precomputed as part of the rdf_data so that it can
     // be cached as part of the entity.
     $parent_node_attributes['resource'] = $comment->rdf_data['nid_uri'];
-    $variables['rdf_metadata_attributes_array'][] = $parent_node_attributes;
+    $variables['rdf_metadata_attributes'][] = $parent_node_attributes;
 
     // Adds the relation to parent comment, if it exists.
     if ($comment->pid != 0) {
@@ -728,7 +728,7 @@ function rdf_preprocess_comment(&$variables) {
       // The parent comment URI is precomputed as part of the rdf_data so that
       // it can be cached as part of the entity.
       $parent_comment_attributes['resource'] = $comment->rdf_data['pid_uri'];
-      $variables['rdf_metadata_attributes_array'][] = $parent_comment_attributes;
+      $variables['rdf_metadata_attributes'][] = $parent_comment_attributes;
     }
   }
 }
@@ -805,7 +805,7 @@ function rdf_preprocess_image(&$variables) {
  * an extra wrapper element, you can override this function to not wrap that
  * variable and instead print the following inside your template file:
  * @code
- *   drupal_attributes($rdf_template_variable_attributes_array[$variable_name])
+ *   drupal_attributes($rdf_template_variable_attributes[$variable_name])
  * @endcode
  *
  * @param $variables
@@ -828,7 +828,7 @@ function rdf_preprocess_image(&$variables) {
  *     therefore can be validly wrapped by a <span> tag. FALSE if the content
  *     might contain block level HTML elements and therefore cannot be validly
  *     wrapped by a <span> tag. Modules implementing preprocess functions that
- *     set 'rdf_template_variable_attributes_array' for a particular template
+ *     set 'rdf_template_variable_attributes' for a particular template
  *     variable that might contain block level HTML must also implement
  *     hook_preprocess_HOOK() for theme_rdf_template_variable_wrapper() and set
  *     'inline' to FALSE for that context. Themes that render normally inline
diff --git a/core/modules/search/search-result.tpl.php b/core/modules/search/search-result.tpl.php
index 949452a..cd44d1e 100644
--- a/core/modules/search/search-result.tpl.php
+++ b/core/modules/search/search-result.tpl.php
@@ -33,11 +33,9 @@
  *   being the count. Depends on comment.module.
  *
  * Other variables:
- * - $classes_array: Array of HTML class attribute values. It is flattened
- *   into a string within the variable $classes.
- * - $title_attributes_array: Array of HTML attributes for the title. It is
+ * - $title_attributes: Array of HTML attributes for the title. It is
  *   flattened into a string within the variable $title_attributes.
- * - $content_attributes_array: Array of HTML attributes for the content. It is
+ * - $content_attributes: Array of HTML attributes for the content. It is
  *   flattened into a string within the variable $content_attributes.
  *
  * Since $info_split is keyed, a direct print of the item is possible.
@@ -62,7 +60,7 @@
  * @see template_process()
  */
 ?>
-<li class="<?php print $classes; ?>"<?php print $attributes; ?>>
+<li <?php print $attributes; ?>>
   <?php print render($title_prefix); ?>
   <h3 class="title"<?php print $title_attributes; ?>>
     <a href="<?php print $url; ?>"><?php print $title; ?></a>
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 1ad7a85..c6245f8 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -160,8 +160,8 @@ function search_block_view($delta = '') {
  */
 function search_preprocess_block(&$variables) {
   if ($variables['block']->module == 'search' && $variables['block']->delta == 'form') {
-    $variables['attributes_array']['role'] = 'search';
-    $variables['content_attributes_array']['class'][] = 'container-inline';
+    $variables['attributes']['role'] = 'search';
+    $variables['content_attributes']['class'][] = 'container-inline';
   }
 }
 
diff --git a/core/modules/search/search.pages.inc b/core/modules/search/search.pages.inc
index ff0d271..56d3bea 100644
--- a/core/modules/search/search.pages.inc
+++ b/core/modules/search/search.pages.inc
@@ -110,8 +110,8 @@ function template_preprocess_search_result(&$variables) {
   $variables['url'] = check_url($result['link']);
   $variables['title'] = check_plain($result['title']);
   if (isset($result['language']) && $result['language'] != $language_interface->langcode && $result['language'] != LANGUAGE_NOT_SPECIFIED) {
-    $variables['title_attributes_array']['lang'] = $result['language'];
-    $variables['content_attributes_array']['lang'] = $result['language'];
+    $variables['title_attributes']['lang'] = $result['language'];
+    $variables['content_attributes']['lang'] = $result['language'];
   }
 
   $info = array();
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index be29dce..27eb8c2 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -644,7 +644,7 @@ function shortcut_renderable_links($shortcut_set = NULL) {
  */
 function shortcut_preprocess_block(&$variables) {
   if ($variables['block']->module == 'shortcut') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
 
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index ef1bceb..c960a91 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -453,6 +453,6 @@ function statistics_update_index() {
  */
 function statistics_preprocess_block(&$variables) {
   if ($variables['block']->module == 'statistics') {
-    $variables['attributes_array']['role'] = 'navigation';
+    $variables['attributes']['role'] = 'navigation';
   }
 }
diff --git a/core/modules/system/html.tpl.php b/core/modules/system/html.tpl.php
index 59a52b9..9b619a7 100644
--- a/core/modules/system/html.tpl.php
+++ b/core/modules/system/html.tpl.php
@@ -55,7 +55,7 @@
     <?php print $styles; ?>
     <?php print $scripts; ?>
   </head>
-  <body class="<?php print $classes; ?>" <?php print $body_attributes;?>>
+  <body class="<?php print $attributes['class']; ?>" <?php print $attributes;?>>
     <div id="skip-link">
       <a href="#main-content" class="element-invisible element-focusable"><?php print t('Skip to main content'); ?></a>
     </div>
diff --git a/core/modules/system/maintenance-page.tpl.php b/core/modules/system/maintenance-page.tpl.php
index 5cde0ff..6730bb9 100644
--- a/core/modules/system/maintenance-page.tpl.php
+++ b/core/modules/system/maintenance-page.tpl.php
@@ -21,7 +21,7 @@
   <?php print $styles; ?>
   <?php print $scripts; ?>
 </head>
-<body class="<?php print $classes; ?>">
+<body class="<?php print $attributes['class']; ?>">
   <div id="page">
     <div id="header">
       <div id="logo-title">
diff --git a/core/modules/system/region.tpl.php b/core/modules/system/region.tpl.php
index b29e24f..265efef 100644
--- a/core/modules/system/region.tpl.php
+++ b/core/modules/system/region.tpl.php
@@ -6,17 +6,15 @@
  *
  * Available variables:
  * - $content: The content for this region, typically blocks.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - region: The current template type, i.e., "theming hook".
  *   - region-[name]: The name of the region with underscores replaced with
  *     dashes. For example, the page_top region would have a region-page-top class.
  * - $region: The name of the region variable as defined in the theme's .info file.
  *
  * Helper variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  * - $is_admin: Flags true when the current user is an administrator.
  * - $is_front: Flags true when presented in the front page.
  * - $logged_in: Flags true when the current user is a logged-in member.
@@ -27,7 +25,7 @@
  */
 ?>
 <?php if ($content): ?>
-  <div class="<?php print $classes; ?>">
+  <div <?php print $attributes; ?>>
     <?php print $content; ?>
   </div>
 <?php endif; ?>
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 5394830..246e3a9 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2175,17 +2175,17 @@ function system_preprocess_block(&$variables) {
 
     switch ($variables['block']->delta) {
       case 'powered-by':
-        $variables['attributes_array']['role'] = 'complementary';
+        $variables['attributes']['role'] = 'complementary';
         break;
       case 'help':
-        $variables['attributes_array']['role'] = 'complementary';
+        $variables['attributes']['role'] = 'complementary';
         break;
 
       // System menu blocks should get the same class as menu module blocks.
       default:
         if (in_array($variables['block']->delta, array_keys(menu_list_system_menus()))) {
-          $variables['attributes_array']['role'] = 'navigation';
-          $variables['classes_array'][] = 'block-menu';
+          $variables['attributes']['role'] = 'navigation';
+          $variables['attributes']['class'][] = 'block-menu';
         }
     }
   }
diff --git a/core/modules/system/tests/common.test b/core/modules/system/tests/common.test
index 15286b6..cc34f8f 100644
--- a/core/modules/system/tests/common.test
+++ b/core/modules/system/tests/common.test
@@ -2537,15 +2537,15 @@ class CommonDrupalAttributesUnitTestCase extends UnitTestBase {
    */
   function testDrupalAttributes() {
     // Verify that special characters are HTML encoded.
-    $this->assertIdentical(drupal_attributes(array('title' => '&"\'<>')), ' title="&amp;&quot;&#039;&lt;&gt;"', t('HTML encode attribute values.'));
+    $this->assertIdentical((string) drupal_attributes(array('title' => '&"\'<>')), ' title="&amp;&quot;&#039;&lt;&gt;"', t('HTML encode attribute values.'));
 
     // Verify multi-value attributes are concatenated with spaces.
     $attributes = array('class' => array('first', 'last'));
-    $this->assertIdentical(drupal_attributes(array('class' => array('first', 'last'))), ' class="first last"', t('Concatenate multi-value attributes.'));
+    $this->assertIdentical((string) drupal_attributes(array('class' => array('first', 'last'))), ' class="first last"', t('Concatenate multi-value attributes.'));
 
     // Verify empty attribute values are rendered.
-    $this->assertIdentical(drupal_attributes(array('alt' => '')), ' alt=""', t('Empty attribute value #1.'));
-    $this->assertIdentical(drupal_attributes(array('alt' => NULL)), ' alt=""', t('Empty attribute value #2.'));
+    $this->assertIdentical((string) drupal_attributes(array('alt' => '')), ' alt=""', t('Empty attribute value #1.'));
+    $this->assertIdentical((string) drupal_attributes(array('alt' => NULL)), ' alt=""', t('Empty attribute value #2.'));
 
     // Verify multiple attributes are rendered.
     $attributes = array(
@@ -2553,10 +2553,10 @@ class CommonDrupalAttributesUnitTestCase extends UnitTestBase {
       'class' => array('first', 'last'),
       'alt' => 'Alternate',
     );
-    $this->assertIdentical(drupal_attributes($attributes), ' id="id-test" class="first last" alt="Alternate"', t('Multiple attributes.'));
+    $this->assertIdentical((string) drupal_attributes($attributes), ' id="id-test" class="first last" alt="Alternate"', t('Multiple attributes.'));
 
     // Verify empty attributes array is rendered.
-    $this->assertIdentical(drupal_attributes(array()), '', t('Empty attributes array.'));
+    $this->assertIdentical((string) drupal_attributes(array()), '', t('Empty attributes array.'));
   }
 }
 
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module
index 4ed90d2..59ff629 100644
--- a/core/modules/system/tests/modules/theme_test/theme_test.module
+++ b/core/modules/system/tests/modules/theme_test/theme_test.module
@@ -142,8 +142,8 @@ function _theme_test_suggestion() {
  * Implements hook_preprocess_HOOK() for html.tpl.php.
  */
 function theme_test_preprocess_html(&$variables) {
-  $variables['html_attributes_array']['theme_test_html_attribute'] = 'theme test html attribute value';
-  $variables['body_attributes_array']['theme_test_body_attribute'] = 'theme test body attribute value';
+  $variables['html_attributes']['theme_test_html_attribute'] = 'theme test html attribute value';
+  $variables['attributes']['theme_test_body_attribute'] = 'theme test body attribute value';
 }
 
 /**
diff --git a/core/modules/system/theme.api.php b/core/modules/system/theme.api.php
index 7fee81c..4803698 100644
--- a/core/modules/system/theme.api.php
+++ b/core/modules/system/theme.api.php
@@ -135,7 +135,7 @@ function hook_preprocess(&$variables, $hook) {
   if (isset($element) && is_array($element) && !empty($element['#contextual_links'])) {
     $variables['title_suffix']['contextual_links'] = contextual_links_view($element);
     if (!empty($variables['title_suffix']['contextual_links'])) {
-      $variables['classes_array'][] = 'contextual-links-region';
+      $variables['attributes']['class'][] = 'contextual-links-region';
     }
   }
 }
@@ -174,8 +174,8 @@ function hook_preprocess_HOOK(&$variables) {
  */
 function hook_process(&$variables, $hook) {
   // Wraps variables in RDF wrappers.
-  if (!empty($variables['rdf_template_variable_attributes_array'])) {
-    foreach ($variables['rdf_template_variable_attributes_array'] as $variable_name => $attributes) {
+  if (!empty($variables['rdf_template_variable_attributes'])) {
+    foreach ($variables['rdf_template_variable_attributes'] as $variable_name => $attributes) {
       $context = array(
         'hook' => $hook,
         'variable_name' => $variable_name,
diff --git a/core/modules/taxonomy/taxonomy-term.tpl.php b/core/modules/taxonomy/taxonomy-term.tpl.php
index b1ff20e..2fcf3f7 100644
--- a/core/modules/taxonomy/taxonomy-term.tpl.php
+++ b/core/modules/taxonomy/taxonomy-term.tpl.php
@@ -13,9 +13,9 @@
  *   given element.
  * - $term_url: Direct url of the current term.
  * - $term_name: Name of the current term.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - taxonomy-term: The current template type, i.e., "theming hook".
  *   - vocabulary-[vocabulary-name]: The vocabulary to which the term belongs to.
  *     For example, if the term is a "Tag" it would result in "vocabulary-tag".
@@ -24,8 +24,6 @@
  * - $term: Full term object. Contains data that may not be safe.
  * - $view_mode: View mode, e.g. 'full', 'teaser'...
  * - $page: Flag for the full page state.
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
  *   teaser listings.
  * - $id: Position of the term. Increments each time it's output.
@@ -38,7 +36,7 @@
  * @see template_process()
  */
 ?>
-<div id="taxonomy-term-<?php print $term->tid; ?>" class="<?php print $classes; ?>">
+<div id="taxonomy-term-<?php print $term->tid; ?>"<?php print $attributes; ?>>
 
   <?php if (!$page): ?>
     <h2><a href="<?php print $term_url; ?>"><?php print $term_name; ?></a></h2>
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index b536b08..bc5c2c7 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -648,7 +648,7 @@ function template_preprocess_taxonomy_term(&$variables) {
 
   // Gather classes, and clean up name so there are no underscores.
   $vocabulary_name_css = str_replace('_', '-', $term->vocabulary_machine_name);
-  $variables['classes_array'][] = 'vocabulary-' . $vocabulary_name_css;
+  $variables['attributes']['class'][] = 'vocabulary-' . $vocabulary_name_css;
 
   $variables['theme_hook_suggestions'][] = 'taxonomy_term__' . $term->vocabulary_machine_name;
   $variables['theme_hook_suggestions'][] = 'taxonomy_term__' . $term->tid;
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 904a2f8..70f12bf 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -146,9 +146,9 @@ function toolbar_pre_render($toolbar) {
  */
 function toolbar_preprocess_html(&$vars) {
   if (isset($vars['page']['page_top']['toolbar']) && user_access('access toolbar')) {
-    $vars['classes_array'][] = 'toolbar';
+    $vars['attributes']['class'][] = 'toolbar';
     if (!_toolbar_is_collapsed()) {
-      $vars['classes_array'][] = 'toolbar-drawer';
+      $vars['attributes']['class'][] = 'toolbar-drawer';
     }
   }
 }
@@ -160,7 +160,7 @@ function toolbar_preprocess_html(&$vars) {
  * down, so it appears below the toolbar.
  */
 function toolbar_preprocess_toolbar(&$variables) {
-  $variables['classes_array'][] = "overlay-displace-top";
+  $variables['attributes']['class'][] = "overlay-displace-top";
 }
 
 /**
diff --git a/core/modules/toolbar/toolbar.tpl.php b/core/modules/toolbar/toolbar.tpl.php
index 6f303b1..2384b38 100644
--- a/core/modules/toolbar/toolbar.tpl.php
+++ b/core/modules/toolbar/toolbar.tpl.php
@@ -5,23 +5,19 @@
  * Default template for admin toolbar.
  *
  * Available variables:
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default value has the following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - toolbar: The current template type, i.e., "theming hook".
  * - $toolbar['toolbar_user']: User account / logout links.
  * - $toolbar['toolbar_menu']: Top level management menu links.
  * - $toolbar['toolbar_drawer']: A place for extended toolbar content.
  *
- * Other variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess()
  * @see template_preprocess_toolbar()
  */
 ?>
-<nav id="toolbar" role="navigation" class="<?php print $classes; ?> clearfix">
+<nav id="toolbar" role="navigation" class="<?php print $attributes['class']; ?> clearfix" <?php print $attributes; ?>>
   <div class="toolbar-menu clearfix">
     <?php print render($toolbar['toolbar_home']); ?>
     <?php print render($toolbar['toolbar_user']); ?>
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 09ef3f5..d427c97 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1178,13 +1178,13 @@ function user_preprocess_block(&$variables) {
   if ($variables['block']->module == 'user') {
     switch ($variables['block']->delta) {
       case 'login':
-        $variables['attributes_array']['role'] = 'form';
+        $variables['attributes']['role'] = 'form';
         break;
       case 'new':
-        $variables['attributes_array']['role'] = 'complementary';
+        $variables['attributes']['role'] = 'complementary';
         break;
       case 'online':
-        $variables['attributes_array']['role'] = 'complementary';
+        $variables['attributes']['role'] = 'complementary';
         break;
     }
   }
@@ -1315,7 +1315,7 @@ function template_preprocess_username(&$variables) {
   // We do not want the l() function to check_plain() a second time.
   $variables['link_options']['html'] = TRUE;
   // Set a default class.
-  $variables['attributes_array'] = array('class' => array('username'));
+  $variables['attributes'] = array('class' => array('username'));
 }
 
 /**
@@ -1328,14 +1328,14 @@ function template_process_username(&$variables) {
   // This is done in the process phase so that attributes may be added by
   // modules or the theme during the preprocess phase.
   if (isset($variables['link_path'])) {
-    // $variables['attributes_array'] contains attributes that should be applied
+    // $variables['attributes'] contains attributes that should be applied
     // regardless of whether a link is being rendered or not.
     // $variables['link_attributes'] contains attributes that should only be
     // applied if a link is being rendered. Preprocess functions are encouraged
     // to use the former unless they want to add attributes on the link only.
     // If a link is being rendered, these need to be merged. Some attributes are
     // themselves arrays, so the merging needs to be recursive.
-    $variables['link_options']['attributes'] = array_merge_recursive($variables['link_attributes'], $variables['attributes_array']);
+    $variables['link_options']['attributes'] = array_merge_recursive($variables['link_attributes'], $variables['attributes']);
   }
 }
 
@@ -1351,7 +1351,7 @@ function template_process_username(&$variables) {
  *     other desired page to link to for more information about the user.
  *   - link_options: An array of options to pass to the l() function's $options
  *     parameter if linking the user's name to the user's page.
- *   - attributes_array: An array of attributes to pass to the
+ *   - attributes: An array of attributes to pass to the
  *     drupal_attributes() function if not linking to the user's page.
  *
  * @see template_preprocess_username()
@@ -1367,8 +1367,8 @@ function theme_username($variables) {
   else {
     // Modules may have added important attributes so they must be included
     // in the output. Additional classes may be added as array elements like
-    // $variables['attributes_array']['class'][] = 'myclass';
-    $output = '<span' . drupal_attributes($variables['attributes_array']) . '>' . $variables['name'] . $variables['extra'] . '</span>';
+    // $variables['attributes']['class'][] = 'myclass';
+    $output = '<span' . drupal_attributes($variables['attributes']) . '>' . $variables['name'] . $variables['extra'] . '</span>';
   }
   return $output;
 }
diff --git a/core/themes/bartik/template.php b/core/themes/bartik/template.php
index 7db1a31..b39563d 100644
--- a/core/themes/bartik/template.php
+++ b/core/themes/bartik/template.php
@@ -12,20 +12,20 @@
  */
 function bartik_preprocess_html(&$variables) {
   if (!empty($variables['page']['featured'])) {
-    $variables['classes_array'][] = 'featured';
+    $variables['attributes']['class'][] = 'featured';
   }
 
   if (!empty($variables['page']['triptych_first'])
     || !empty($variables['page']['triptych_middle'])
     || !empty($variables['page']['triptych_last'])) {
-    $variables['classes_array'][] = 'triptych';
+    $variables['attributes']['class'][] = 'triptych';
   }
 
   if (!empty($variables['page']['footer_firstcolumn'])
     || !empty($variables['page']['footer_secondcolumn'])
     || !empty($variables['page']['footer_thirdcolumn'])
     || !empty($variables['page']['footer_fourthcolumn'])) {
-    $variables['classes_array'][] = 'footer-columns';
+    $variables['attributes']['class'][] = 'footer-columns';
   }
 }
 
@@ -114,7 +114,7 @@ function bartik_process_maintenance_page(&$variables) {
 function bartik_preprocess_block(&$variables) {
   // In the header region visually hide block titles.
   if ($variables['block']->region == 'header') {
-    $variables['title_attributes_array']['class'][] = 'element-invisible';
+    $variables['title_attributes']['class'][] = 'element-invisible';
   }
 }
 
@@ -144,7 +144,7 @@ function bartik_field__taxonomy_term_reference($variables) {
   $output .= '</ul>';
 
   // Render the top-level DIV.
-  $output = '<div class="' . $variables['classes'] . (!in_array('clearfix', $variables['classes_array']) ? ' clearfix' : '') . '">' . $output . '</div>';
+  $output = '<div class="' . $variables['attributes']['class'] . (!in_array('clearfix', (array) $variables['attributes']['class']) ? ' clearfix' : '') . '">' . $output . '</div>';
 
   return $output;
 }
diff --git a/core/themes/bartik/templates/comment-wrapper.tpl.php b/core/themes/bartik/templates/comment-wrapper.tpl.php
index dc06cf2..a9f423c 100644
--- a/core/themes/bartik/templates/comment-wrapper.tpl.php
+++ b/core/themes/bartik/templates/comment-wrapper.tpl.php
@@ -8,9 +8,9 @@
  * - $content: The array of content-related elements for the node. Use
  *   render($content) to print them all, or
  *   print a subset such as render($content['comment_form']).
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default value has the following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - comment-wrapper: The current template type, i.e., "theming hook".
  * - $title_prefix (array): An array containing additional output populated by
  *   modules, intended to be displayed in front of the main title tag that
@@ -27,17 +27,13 @@
  *   - COMMENT_MODE_FLAT
  *   - COMMENT_MODE_THREADED
  *
- * Other variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess_comment_wrapper()
  * @see theme_comment_wrapper()
  *
  * @ingroup themeable
  */
 ?>
-<div id="comments" class="<?php print $classes; ?>"<?php print $attributes; ?>>
+<div id="comments" <?php print $attributes; ?>>
   <?php if ($content['comments'] && $node->type != 'forum'): ?>
     <?php print render($title_prefix); ?>
     <h2 class="title"><?php print t('Comments'); ?></h2>
diff --git a/core/themes/bartik/templates/comment.tpl.php b/core/themes/bartik/templates/comment.tpl.php
index 0b70594..e994d24 100644
--- a/core/themes/bartik/templates/comment.tpl.php
+++ b/core/themes/bartik/templates/comment.tpl.php
@@ -25,10 +25,9 @@
  * - $status: Comment status. Possible values are:
  *   unpublished, published, or preview.
  * - $title: Linked title.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - comment: The current template type; e.g., 'theming hook'.
  *   - by-anonymous: Comment by an unregistered user.
  *   - by-node-author: Comment by the author of the parent node.
@@ -48,10 +47,6 @@
  * - $comment: Full comment object.
  * - $node: Node entity the comments are attached to.
  *
- * Other variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
- *
  * @see template_preprocess()
  * @see template_preprocess_comment()
  * @see template_process()
@@ -60,7 +55,7 @@
  * @ingroup themeable
  */
 ?>
-<div class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+<div class="<?php print $attributes['class']; ?> clearfix"<?php print $attributes; ?>>
 
   <div class="attribution">
 
diff --git a/core/themes/bartik/templates/maintenance-page.tpl.php b/core/themes/bartik/templates/maintenance-page.tpl.php
index 9cdeff7..caf1611 100644
--- a/core/themes/bartik/templates/maintenance-page.tpl.php
+++ b/core/themes/bartik/templates/maintenance-page.tpl.php
@@ -22,7 +22,7 @@
   <?php print $styles; ?>
   <?php print $scripts; ?>
 </head>
-<body class="<?php print $classes; ?>" <?php print $attributes;?>>
+<body class="<?php print $attributes['class']; ?>" <?php print $attributes;?>>
 
   <div id="skip-link">
     <a href="#main-content" class="element-invisible element-focusable"><?php print t('Skip to main content'); ?></a>
diff --git a/core/themes/bartik/templates/node.tpl.php b/core/themes/bartik/templates/node.tpl.php
index 318197c..4b4d7df 100644
--- a/core/themes/bartik/templates/node.tpl.php
+++ b/core/themes/bartik/templates/node.tpl.php
@@ -19,10 +19,9 @@
  * - $display_submitted: Whether submission information should be displayed.
  * - $submitted: Submission information created from $name and $date during
  *   template_preprocess_node().
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the
- *   following:
+ * - $attributes: An object of HTML attributes that can be manipulated as an
+ *    array and printed as a string.
+ *    It includes the 'class' information, which includes:
  *   - node: The current template type, i.e., "theming hook".
  *   - node-[type]: The current node type. For example, if the node is a
  *     "Article" it would result in "node-article". Note that the machine
@@ -47,8 +46,6 @@
  * - $comment_count: Number of comments attached to the node.
  * - $uid: User ID of the node author.
  * - $created: Time the node was published formatted in Unix timestamp.
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
  * - $zebra: Outputs either "even" or "odd". Useful for zebra striping in
  *   teaser listings.
  * - $id: Position of the node. Increments each time it's output.
@@ -81,7 +78,7 @@
  * @ingroup themeable
  */
 ?>
-<div id="node-<?php print $node->nid; ?>" class="<?php print $classes; ?> clearfix"<?php print $attributes; ?>>
+<div id="node-<?php print $node->nid; ?>" class="<?php print $attributes['class']; ?> clearfix"<?php print $attributes; ?>>
 
   <?php print render($title_prefix); ?>
   <?php if (!$page): ?>
diff --git a/core/themes/seven/maintenance-page.tpl.php b/core/themes/seven/maintenance-page.tpl.php
index 12c0f9e..09d33a1 100644
--- a/core/themes/seven/maintenance-page.tpl.php
+++ b/core/themes/seven/maintenance-page.tpl.php
@@ -22,7 +22,7 @@
     <?php print $styles; ?>
     <?php print $scripts; ?>
   </head>
-  <body class="<?php print $classes; ?>">
+  <body class="<?php print $attributes['class']; ?>">
 
   <?php print $page_top; ?>
 
