diff --git a/core/lib/Drupal/Core/Field/FieldConfigInterface.php b/core/lib/Drupal/Core/Field/FieldConfigInterface.php
index 11da0df..13ac848 100644
--- a/core/lib/Drupal/Core/Field/FieldConfigInterface.php
+++ b/core/lib/Drupal/Core/Field/FieldConfigInterface.php
@@ -178,7 +178,7 @@ public function addPropertyConstraints($name, array $constraints);
    * @code
    *   // Add a constraint to the 'field_username' FieldItemList.
    *   // e.g. $node->field_username
-   *   $fields['field_username']->addConstraint('UserNameUnique', []);
+   *   $fields['field_username']->addConstraint('UniqueField', []);
    * @endcode
    *
    * If you wish to apply a constraint to a \Drupal\Core\Field\FieldItem instead
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldConstraint.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldConstraint.php
new file mode 100644
index 0000000..c917cc9
--- /dev/null
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldConstraint.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldConstraint.
+ */
+
+namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Checks if an entity field has a unique value.
+ *
+ * @Plugin(
+ *   id = "UniqueField",
+ *   label = @Translation("Unique field constraint", context = "Validation"),
+ * )
+ */
+class UniqueFieldConstraint extends Constraint {
+
+  public $message = 'The @entity_type with the @field_name %value already exists.';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validatedBy() {
+    return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php
index d6c3910..1917c5c 100644
--- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php
+++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Validation\Plugin\Validation\Constraint;
 
+use Drupal\Component\Utility\Unicode;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidator;
 
@@ -37,7 +38,11 @@ public function validate($items, Constraint $constraint) {
       ->execute();
 
     if ($value_taken) {
-      $this->context->addViolation($constraint->message, array("%value" => $item->value));
+      $this->context->addViolation($constraint->message, [
+        '%value' => $item->value,
+        '@entity_type' => $entity->getEntityType()->getLowercaseLabel(),
+        '@field_name' => Unicode::strtolower($items->getFieldDefinition()->getLabel()),
+      ]);
     }
   }
 }
diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php
index a5ed081..a442005 100644
--- a/core/modules/aggregator/src/Entity/Feed.php
+++ b/core/modules/aggregator/src/Entity/Feed.php
@@ -151,7 +151,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         'weight' => -5,
       ))
       ->setDisplayConfigurable('form', TRUE)
-      ->addConstraint('FeedTitle', []);
+      ->addConstraint('UniqueField', ['message' => 'A feed named %value already exists. Enter a unique title.']);
 
     $fields['langcode'] = BaseFieldDefinition::create('language')
       ->setLabel(t('Language code'))
@@ -173,7 +173,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         'weight' => -3,
       ))
       ->setDisplayConfigurable('form', TRUE)
-      ->addConstraint('FeedUrl', []);
+      ->addConstraint('UniqueField', ['message' => 'A feed with this URL %value already exists. Enter a unique URL.']);
 
     $intervals = array(900, 1800, 3600, 7200, 10800, 21600, 32400, 43200, 64800, 86400, 172800, 259200, 604800, 1209600, 2419200);
     $period = array_map(array(\Drupal::service('date.formatter'), 'formatInterval'), array_combine($intervals, $intervals));
diff --git a/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedTitleConstraint.php b/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedTitleConstraint.php
deleted file mode 100644
index 47d16ac..0000000
--- a/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedTitleConstraint.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\aggregator\Plugin\Validation\Constraint\FeedTitleConstraint.
- */
-
-namespace Drupal\aggregator\Plugin\Validation\Constraint;
-
-use Symfony\Component\Validator\Constraint;
-
-/**
- * Supports validating feed titles.
- *
- * @Plugin(
- *   id = "FeedTitle",
- *   label = @Translation("Feed title", context = "Validation")
- * )
- */
-class FeedTitleConstraint extends Constraint {
-
-  public $message = 'A feed named %value already exists. Enter a unique title.';
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validatedBy() {
-    return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
-  }
-
-}
diff --git a/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedUrlConstraint.php b/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedUrlConstraint.php
deleted file mode 100644
index 0e2ce1d..0000000
--- a/core/modules/aggregator/src/Plugin/Validation/Constraint/FeedUrlConstraint.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\aggregator\Plugin\Validation\Constraint\FeedUrlConstraint.
- */
-
-namespace Drupal\aggregator\Plugin\Validation\Constraint;
-
-use Symfony\Component\Validator\Constraint;
-
-/**
- * Supports validating feed URLs.
- *
- * @Plugin(
- *   id = "FeedUrl",
- *   label = @Translation("Feed URL", context = "Validation")
- * )
- */
-class FeedUrlConstraint extends Constraint {
-
-  public $message = 'A feed with this URL %value already exists. Enter a unique URL.';
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validatedBy() {
-    return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
-  }
-
-}
diff --git a/core/modules/block_content/src/BlockContentForm.php b/core/modules/block_content/src/BlockContentForm.php
index 379e576..088c4d7 100644
--- a/core/modules/block_content/src/BlockContentForm.php
+++ b/core/modules/block_content/src/BlockContentForm.php
@@ -220,18 +220,4 @@ public function save(array $form, FormStateInterface $form_state) {
     }
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function validateForm(array &$form, FormStateInterface $form_state) {
-    if ($this->entity->isNew()) {
-      $exists = $this->blockContentStorage->loadByProperties(array('info' => $form_state->getValue(['info', 0, 'value'])));
-      if (!empty($exists)) {
-        $form_state->setErrorByName('info', $this->t('A block with description %name already exists.', array(
-          '%name' => $form_state->getValue(array('info', 0, 'value')),
-        )));
-      }
-    }
-  }
-
 }
diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php
index 046640c..40c19e9 100644
--- a/core/modules/block_content/src/Entity/BlockContent.php
+++ b/core/modules/block_content/src/Entity/BlockContent.php
@@ -187,7 +187,8 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         'type' => 'string_textfield',
         'weight' => -5,
       ))
-      ->setDisplayConfigurable('form', TRUE);
+      ->setDisplayConfigurable('form', TRUE)
+      ->addConstraint('UniqueField');
 
     $fields['type'] = BaseFieldDefinition::create('entity_reference')
       ->setLabel(t('Block type'))
diff --git a/core/modules/block_content/src/Tests/BlockContentCreationTest.php b/core/modules/block_content/src/Tests/BlockContentCreationTest.php
index 6bf250c..66c259a 100644
--- a/core/modules/block_content/src/Tests/BlockContentCreationTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentCreationTest.php
@@ -66,8 +66,8 @@ public function testBlockContentCreation() {
     $this->drupalPostForm('block/add/basic', $edit, t('Save'));
 
     // Check that the Basic block has been created.
-    $this->assertRaw(format_string('A block with description %name already exists.', array(
-      '%name' => $edit['info[0][value]']
+    $this->assertRaw(format_string('The custom block with the block description %value already exists.', array(
+      '%value' => $edit['info[0][value]']
     )));
     $this->assertResponse(200);
   }
@@ -124,8 +124,8 @@ public function testBlockContentCreationMultipleViewModes() {
     $this->drupalPostForm('block/add/basic', $edit, t('Save'));
 
     // Check that the Basic block has been created.
-    $this->assertRaw(format_string('A block with description %name already exists.', array(
-      '%name' => $edit['info[0][value]']
+    $this->assertRaw(format_string('The custom block with the block description %value already exists.', array(
+      '%value' => $edit['info[0][value]']
     )));
     $this->assertResponse(200);
   }
diff --git a/core/modules/block_content/src/Tests/BlockContentTestBase.php b/core/modules/block_content/src/Tests/BlockContentTestBase.php
index 82139c0..9cff6c0 100644
--- a/core/modules/block_content/src/Tests/BlockContentTestBase.php
+++ b/core/modules/block_content/src/Tests/BlockContentTestBase.php
@@ -70,17 +70,20 @@ protected function setUp() {
    *   Defaults to FALSE.
    * @param string $bundle
    *   (optional) Bundle name. Defaults to 'basic'.
+   * @param bool $save
+   *   (optional) Whether to save the block. Defaults to TRUE.
    *
    * @return \Drupal\block_content\Entity\BlockContent
    *   Created custom block.
    */
-  protected function createBlockContent($title = FALSE, $bundle = 'basic') {
+  protected function createBlockContent($title = FALSE, $bundle = 'basic', $save = TRUE) {
     $title = ($title ? : $this->randomMachineName());
-    if ($block_content = entity_create('block_content', array(
+    $block_content = entity_create('block_content', array(
       'info' => $title,
       'type' => $bundle,
       'langcode' => 'en'
-    ))) {
+    ));
+    if ($block_content && $save === TRUE) {
       $block_content->save();
     }
     return $block_content;
diff --git a/core/modules/block_content/src/Tests/BlockContentValidationTest.php b/core/modules/block_content/src/Tests/BlockContentValidationTest.php
new file mode 100644
index 0000000..e13f010
--- /dev/null
+++ b/core/modules/block_content/src/Tests/BlockContentValidationTest.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\block_content\Tests\BlockContentValidationTest.
+ */
+
+namespace Drupal\block_content\Tests;
+
+/**
+ * Tests block content validation constraints.
+ *
+ * @group block_content
+ */
+class BlockContentValidationTest extends BlockContentTestBase {
+
+  /**
+   * Tests the block content validation constraints.
+   */
+  public function testValidation() {
+    // Add a block.
+    $description = $this->randomMachineName();
+    $block = $this->createBlockContent($description, 'basic', FALSE);
+    // Validate the block.
+    $violations = $block->validate();
+    // Make sure we have no violations.
+    $this->assertEqual(count($violations), 0);
+    // Save the block.
+    $block->save();
+
+    // Add another block with the same description.
+    $block = $this->createBlockContent($description, 'basic', FALSE);
+    // Validate this block.
+    $violations = $block->validate();
+    // Make sure we have 1 violation.
+    $this->assertEqual(count($violations), 1);
+    // Make sure the violation is on the info property
+    $this->assertEqual($violations[0]->getPropertyPath(), 'info');
+    // Make sure the message is correct.
+    $this->assertEqual($violations[0]->getMessage(), format_string('The custom block with the block description %value already exists.', [
+      '%value' => $block->label(),
+    ]));
+  }
+
+}
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index fa4db6f..2952bce 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -465,7 +465,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
         // No Length constraint here because the UserName constraint also covers
         // that.
         'UserName' => array(),
-        'UserNameUnique' => array(),
+        'UniqueField' => array(),
       ));
 
     $fields['pass'] = BaseFieldDefinition::create('password')
@@ -477,7 +477,7 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setLabel(t('Email'))
       ->setDescription(t('The email of this user.'))
       ->setDefaultValue('')
-      ->addConstraint('UserMailUnique')
+      ->addConstraint('UniqueField')
       ->addConstraint('UserMailRequired')
       ->addConstraint('ProtectedUserField');
 
diff --git a/core/modules/user/src/Plugin/Validation/Constraint/UserMailUnique.php b/core/modules/user/src/Plugin/Validation/Constraint/UserMailUnique.php
deleted file mode 100644
index e541518..0000000
--- a/core/modules/user/src/Plugin/Validation/Constraint/UserMailUnique.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Plugin\Validation\Constraint\UserMailUnique.
- */
-
-namespace Drupal\user\Plugin\Validation\Constraint;
-
-use Symfony\Component\Validator\Constraint;
-
-/**
- * Checks if a user's email address is unique on the site.
- *
- * @Plugin(
- *   id = "UserMailUnique",
- *   label = @Translation("User email unique", context = "Validation")
- * )
- */
-class UserMailUnique extends Constraint {
-
-  public $message = 'The email address %value is already taken.';
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validatedBy() {
-    return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
-  }
-}
diff --git a/core/modules/user/src/Plugin/Validation/Constraint/UserNameUnique.php b/core/modules/user/src/Plugin/Validation/Constraint/UserNameUnique.php
deleted file mode 100644
index 0a65d32..0000000
--- a/core/modules/user/src/Plugin/Validation/Constraint/UserNameUnique.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Plugin\Validation\Constraint\UserNameUnique.
- */
-
-namespace Drupal\user\Plugin\Validation\Constraint;
-
-use Symfony\Component\Validator\Constraint;
-
-/**
- * Checks if a user name is unique on the site.
- *
- * @Plugin(
- *   id = "UserNameUnique",
- *   label = @Translation("User name unique", context = "Validation"),
- * )
- */
-class UserNameUnique extends Constraint {
-
-  public $message = 'The username %value is already taken.';
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validatedBy() {
-    return '\Drupal\Core\Validation\Plugin\Validation\Constraint\UniqueFieldValueValidator';
-  }
-}
diff --git a/core/modules/user/src/Tests/UserEditTest.php b/core/modules/user/src/Tests/UserEditTest.php
index 46502f4..8883381 100644
--- a/core/modules/user/src/Tests/UserEditTest.php
+++ b/core/modules/user/src/Tests/UserEditTest.php
@@ -28,7 +28,7 @@ function testUserEdit() {
     // Test that error message appears when attempting to use a non-unique user name.
     $edit['name'] = $user2->getUsername();
     $this->drupalPostForm("user/" . $user1->id() . "/edit", $edit, t('Save'));
-    $this->assertRaw(t('The username %name is already taken.', array('%name' => $edit['name'])));
+    $this->assertRaw(t('The user with the name %name already exists.', array('%name' => $edit['name'])));
 
     // Check that filling out a single password field does not validate.
     $edit = array();
diff --git a/core/modules/user/src/Tests/UserRegistrationTest.php b/core/modules/user/src/Tests/UserRegistrationTest.php
index ff3fa30..e7ee6f3 100644
--- a/core/modules/user/src/Tests/UserRegistrationTest.php
+++ b/core/modules/user/src/Tests/UserRegistrationTest.php
@@ -141,13 +141,13 @@ function testRegistrationEmailDuplicates() {
 
     // Attempt to create a new account using an existing email address.
     $this->drupalPostForm('user/register', $edit, t('Create new account'));
-    $this->assertText(t('The email address @email is already taken.', array('@email' => $duplicate_user->getEmail())), 'Supplying an exact duplicate email address displays an error message');
+    $this->assertText(t('The user with the email @email already exists.', array('@email' => $duplicate_user->getEmail())), 'Supplying an exact duplicate email address displays an error message');
 
     // Attempt to bypass duplicate email registration validation by adding spaces.
     $edit['mail'] = '   ' . $duplicate_user->getEmail() . '   ';
 
     $this->drupalPostForm('user/register', $edit, t('Create new account'));
-    $this->assertText(t('The email address @email is already taken.', array('@email' => $duplicate_user->getEmail())), 'Supplying a duplicate email address with added whitespace displays an error message');
+    $this->assertText(t('The user with the email @email already exists.', array('@email' => $duplicate_user->getEmail())), 'Supplying a duplicate email address with added whitespace displays an error message');
   }
 
   function testRegistrationDefaultValues() {
diff --git a/core/modules/user/src/Tests/UserValidationTest.php b/core/modules/user/src/Tests/UserValidationTest.php
index ec44a79..c6512f1 100644
--- a/core/modules/user/src/Tests/UserValidationTest.php
+++ b/core/modules/user/src/Tests/UserValidationTest.php
@@ -102,7 +102,7 @@ function testValidation() {
     $violations = $user->validate();
     $this->assertEqual(count($violations), 1, 'Violation found on name collision.');
     $this->assertEqual($violations[0]->getPropertyPath(), 'name');
-    $this->assertEqual($violations[0]->getMessage(), t('The username %name is already taken.', array('%name' => 'existing')));
+    $this->assertEqual($violations[0]->getMessage(), t('The user with the name %name already exists.', array('%name' => 'existing')));
 
     // Make the name valid.
     $user->set('name', $this->randomMachineName());
@@ -131,7 +131,7 @@ function testValidation() {
     $violations = $user->validate();
     $this->assertEqual(count($violations), 1, 'Violation found when email already exists.');
     $this->assertEqual($violations[0]->getPropertyPath(), 'mail');
-    $this->assertEqual($violations[0]->getMessage(), t('The email address %mail is already taken.', array('%mail' => 'existing@example.com')));
+    $this->assertEqual($violations[0]->getMessage(), t('The user with the email %mail already exists.', array('%mail' => 'existing@example.com')));
     $user->set('mail', NULL);
     $violations = $user->validate();
     $this->assertEqual(count($violations), 1, 'E-mail addresses may not be removed');
