diff --git a/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php b/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php
index b99e472..7126eff 100644
--- a/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php
+++ b/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php
@@ -19,4 +19,18 @@ class ConfigEntityType extends EntityType {
    */
   public $entity_type_class = 'Drupal\Core\Config\Entity\ConfigEntityType';
 
+  /**
+   * {@inheritdoc}
+   */
+  public $group = 'configuration';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get() {
+    $this->definition['group_label'] = $this->t('Configuration', array(), array('context' => 'Entity type group'));
+
+    return parent::get();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php b/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php
index e9ae852..ddf05c9 100644
--- a/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php
+++ b/core/lib/Drupal/Core/Entity/Annotation/ContentEntityType.php
@@ -19,4 +19,18 @@ class ContentEntityType extends EntityType {
    */
   public $entity_type_class = 'Drupal\Core\Entity\ContentEntityType';
 
+  /**
+   * {@inheritdoc}
+   */
+  public $group = 'content';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get() {
+    $this->definition['group_label'] = $this->t('Content', array(), array('context' => 'Entity type group'));
+
+    return parent::get();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php
index 76e51e4..6301f80 100644
--- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Entity\Annotation;
 
 use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 
 /**
  * Defines an Entity type annotation object.
@@ -24,6 +25,8 @@
  */
 class EntityType extends Plugin {
 
+  use StringTranslationTrait;
+
   /**
    * The class used to represent the entity type.
    *
@@ -34,6 +37,20 @@ class EntityType extends Plugin {
   public $entity_type_class = 'Drupal\Core\Entity\EntityType';
 
   /**
+   * The group machine name.
+   */
+  public $group = 'default';
+
+  /**
+   * The group label.
+   *
+   * @var \Drupal\Core\Annotation\Translation
+   *
+   * @ingroup plugin_translatable
+   */
+  public $group_label = '';
+
+  /**
    * {@inheritdoc}
    */
   public function get() {
diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php
index fb1a786..bc3e563 100644
--- a/core/lib/Drupal/Core/Entity/EntityManager.php
+++ b/core/lib/Drupal/Core/Entity/EntityManager.php
@@ -22,6 +22,7 @@
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\InfoHookDecorator;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\StringTranslation\TranslationInterface;
 use Drupal\Core\TypedData\TranslatableInterface;
 use Symfony\Component\DependencyInjection\ContainerAwareInterface;
@@ -44,6 +45,7 @@
 class EntityManager extends PluginManagerBase implements EntityManagerInterface, ContainerAwareInterface  {
 
   use ContainerAwareTrait;
+  use StringTranslationTrait;
 
   /**
    * Extra fields by bundle.
@@ -638,10 +640,28 @@ public function getExtraFields($entity_type_id, $bundle) {
   /**
    * {@inheritdoc}
    */
-  public function getEntityTypeLabels() {
+  public function getEntityTypeLabels($group = FALSE) {
     $options = array();
-    foreach ($this->getDefinitions() as $entity_type => $definition) {
-      $options[$entity_type] = $definition->getLabel();
+    $definitions = $this->getDefinitions();
+
+    foreach ($definitions as $entity_type_id => $definition) {
+      if ($group) {
+        $options[$definition->getGroupLabel()][$entity_type_id] = $definition->getLabel();
+      }
+      else {
+        $options[$entity_type_id] = $definition->getLabel();
+      }
+    }
+
+    if ($group) {
+      foreach ($options as &$group_options) {
+        // Sort the list alphabetically by group label.
+        array_multisort($group_options, SORT_ASC, SORT_NATURAL);
+      }
+
+      // Make sure that the 'Content' group is situated at the top.
+      $content = $this->t('Content', array(), array('context' => 'Entity type group'));
+      $options = array($content => $options[$content]) + $options;
     }
 
     return $options;
diff --git a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
index 7ee0255..7d2c547 100644
--- a/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
+++ b/core/lib/Drupal/Core/Entity/EntityManagerInterface.php
@@ -17,10 +17,14 @@
   /**
    * Builds a list of entity type labels suitable for a Form API options list.
    *
+   * @param bool $group
+   *   (optional) Whether to group entity types by plugin group (e.g. 'content',
+   *   'config'). Defaults to FALSE.
+   *
    * @return array
    *   An array of entity type labels, keyed by entity type name.
    */
-  public function getEntityTypeLabels();
+  public function getEntityTypeLabels($group = FALSE);
 
   /**
    * Gets the base field definitions for a content entity type.
diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php
index de4411c..5be662f 100644
--- a/core/lib/Drupal/Core/Entity/EntityType.php
+++ b/core/lib/Drupal/Core/Entity/EntityType.php
@@ -10,12 +10,15 @@
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\Exception\EntityTypeIdLengthException;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 
 /**
  * Provides an implementation of an entity type and its metadata.
  */
 class EntityType implements EntityTypeInterface {
 
+  use StringTranslationTrait;
+
   /**
    * Indicates whether entities should be statically cached.
    *
@@ -180,6 +183,16 @@ class EntityType implements EntityTypeInterface {
   protected $uri_callback;
 
   /**
+   * The machine name of the entity type group.
+   */
+  protected $group;
+
+  /**
+   * The human-readable name of the entity type group.
+   */
+  protected $group_label;
+
+  /**
    * Constructs a new EntityType.
    *
    * @param array $definition
@@ -602,4 +615,19 @@ public function setUriCallback($callback) {
     return $this;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getGroup() {
+    return $this->group;
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getGroupLabel() {
+    return !empty($this->group_label) ? $this->group_label : $this->t('Other', array(), array('context' => 'Entity type group'));
+  }
+
 }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
index 4757302..e5ad209 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/ConfigurableEntityReferenceItem.php
@@ -163,7 +163,7 @@ public function settingsForm(array $form, array &$form_state, $has_data) {
     $element['target_type'] = array(
       '#type' => 'select',
       '#title' => t('Type of item to reference'),
-      '#options' => \Drupal::entityManager()->getEntityTypeLabels(),
+      '#options' => \Drupal::entityManager()->getEntityTypeLabels(TRUE),
       '#default_value' => $this->getSetting('target_type'),
       '#required' => TRUE,
       '#disabled' => $has_data,
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
index 8466bf2..60d55ba 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAdminTest.php
@@ -127,7 +127,7 @@ protected function assertFieldSelectOptions($name, array $expected_options) {
     if ($fields) {
       $field = $fields[0];
       $options = $this->getAllOptionsList($field);
-      return $this->assertIdentical($options, $expected_options);
+      return $this->assertIdentical(sort($options), sort($expected_options));
     }
     else {
       return $this->fail('Unable to find field ' . $name);
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index 20fb54f..340b555 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -3141,7 +3141,7 @@ protected function assertFieldByXPath($xpath, $value = NULL, $message = '', $gro
             // Input element with correct value.
             $found = TRUE;
           }
-          elseif (isset($field->option)) {
+          elseif (isset($field->option) || isset($field->optgroup)) {
             // Select element found.
             $selected = $this->getSelectedItem($field);
             if ($selected === FALSE) {
