diff --git a/core/includes/update.inc b/core/includes/update.inc
index 299a81caf419d5743255b32b41a16731fd53b617..3d33e4401d56a19c879188a9d62267b9211e3a71 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -1254,6 +1254,26 @@ function update_variables_to_config($config_name, array $variable_map) {
   db_delete('variable')->condition('name', array_keys($variable_map), 'IN')->execute();
 }
 
+/**
+ * Adds entries in a configuration entity manifest file during updates.
+ *
+ * @param string $config_prefix
+ *   The configuration entity prefix from the annotation.
+ * @param array $ids
+ *   An array of configuration entities to add to the manifest.
+ */
+function update_config_manifest_add($config_prefix, array $ids) {
+  $manifest = config('manifest.' . $config_prefix);
+
+  foreach ($ids as $id) {
+    // Add record to manifest for each config entity.
+    $manifest->set($id, array('name' => $config_prefix . '.' . $id));
+  }
+
+  // Write manifest to disk.
+  $manifest->save();
+}
+
 /**
  * Updates 7.x variables to state records.
  *
diff --git a/core/modules/contact/contact.install b/core/modules/contact/contact.install
index 8f97f0c802eb41e96acac5bc716bd657f9c50de3..d35abe95a592457fca9b35e229f90047a6dab7d5 100644
--- a/core/modules/contact/contact.install
+++ b/core/modules/contact/contact.install
@@ -5,6 +5,8 @@
  * Install, update and uninstall functions for the contact module.
  */
 
+use Drupal\Component\Uuid\Uuid;
+
 /**
  * Implements hook_install().
  */
@@ -51,10 +53,14 @@ function contact_update_8000() {
  * @ingroup config_upgrade
  */
 function contact_update_8001() {
+  $uuid = new Uuid();
   $result = db_query('SELECT * FROM {contact}');
+  $ids = array();
   foreach ($result as $category) {
     // Take over the category's serial ID as new machine name.
     $category->id = $category->cid;
+    // Save the id to add to the manifest file.
+    $ids[] = $category->id;
     // Save default category setting.
     if ($category->selected) {
       config('contact.settings')
@@ -64,12 +70,16 @@ function contact_update_8001() {
     // Save the config object.
     config('contact.category.' . $category->id)
       ->set('id', $category->id)
+      ->set('uuid', $uuid->generate())
       ->set('label', $category->category)
       ->set('recipients', explode(',', $category->recipients))
       ->set('reply', $category->reply)
       ->set('weight', $category->weight)
+      ->set('langcode', LANGUAGE_NOT_SPECIFIED)
       ->save();
   }
+
+  update_config_manifest_add('contact.category', $ids);
 }
 
 /**
diff --git a/core/modules/contact/lib/Drupal/contact/Tests/ContactUpgradePathTest.php b/core/modules/contact/lib/Drupal/contact/Tests/ContactUpgradePathTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..de5d00208d9555da43de853c6e7904dc9117bee4
--- /dev/null
+++ b/core/modules/contact/lib/Drupal/contact/Tests/ContactUpgradePathTest.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\contact\Tests\ContactUpgradePathTest.
+ */
+
+namespace Drupal\contact\Tests;
+
+use Drupal\system\Tests\Upgrade\UpgradePathTestBase;
+
+/**
+ * Tests upgrade of contact.
+ */
+class ContactUpgradePathTest extends UpgradePathTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Contact upgrade test',
+      'description' => 'Tests upgrade of contact to the configuration system.',
+      'group' => 'Contact',
+    );
+  }
+
+  public function setUp() {
+    $this->databaseDumpFiles = array(
+      drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz',
+      drupal_get_path('module', 'contact') . '/tests/drupal-7.contact.database.php',
+    );
+    parent::setUp();
+  }
+
+  /**
+   * Tests upgrade of contact table to configuration entities.
+   */
+  public function testContactUpgrade() {
+    $default_contact_category = db_query('SELECT cid FROM {contact} WHERE selected = 1')->fetchField();
+
+    $this->assertTrue(db_table_exists('contact'), 'Contact table exists.');
+    $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.');
+
+    // Test that the contact form is available.
+    $this->assertFalse(db_table_exists('contact'), 'Contact table has been deleted.');
+    $this->drupalGet('contact');
+    $this->assertText(t('Your e-mail address'));
+
+    // Ensure that the Drupal 7 default contact category has been created.
+    $contact_category = entity_load('contact_category', '1');
+    $this->assertTrue(isset($contact_category->uuid), 'Converted contact category has a UUID');
+    $this->assertEqual($contact_category->label, 'Website feedback');
+    $this->assertEqual($contact_category->reply, '');
+    $this->assertEqual($contact_category->weight, 0);
+    $this->assertEqual($contact_category->recipients, array('admin@example.com'));
+
+    // Test that the custom contact category has been updated.
+    $contact_category = entity_load('contact_category', '2');
+    $this->assertTrue(isset($contact_category->uuid), 'Converted contact category has a UUID');
+    $this->assertEqual($contact_category->label, 'Upgrade test');
+    $this->assertEqual($contact_category->reply, 'Test reply');
+    $this->assertEqual($contact_category->weight, 1);
+    $this->assertEqual($contact_category->recipients, array('test1@example.com', 'test2@example.com'));
+
+    // Ensure that the default category has been maintained.
+    $this->assertEqual(config('contact.settings')->get('default_category'), $default_contact_category, 'Default category upgraded.');
+
+    // Check that no default config imported on upgrade.
+    $this->assertFalse(entity_load('contact_category', 'feedback'));
+
+    // Assert that manifest has been created and contains the expected records.
+    $manifest = config('manifest.contact.category');
+    $this->assertEqual($manifest->get('1.name'), 'contact.category.1');
+    $this->assertEqual($manifest->get('2.name'), 'contact.category.2');
+  }
+}
diff --git a/core/modules/contact/tests/drupal-7.contact.database.php b/core/modules/contact/tests/drupal-7.contact.database.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed8e5bae5c878d1528e440cb3f10cb6683a5430f
--- /dev/null
+++ b/core/modules/contact/tests/drupal-7.contact.database.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Database additions for Drupal\contact\Tests\ContactUpgradePathTest.
+ *
+ * This dump only contains data for the contact module. The
+ * drupal-7.filled.bare.php file is imported before this dump, so the two form
+ * the database structure expected in tests altogether.
+ */
+
+// Update the default category to that it is not selected.
+db_update('contact')
+  ->fields(array('selected' => '0'))
+  ->condition('cid', '1')
+  ->execute();
+
+// Add a custom contact category.
+db_insert('contact')->fields(array(
+  'category',
+  'recipients',
+  'reply',
+  'weight',
+  'selected'
+))
+->values(array(
+  'category' => 'Upgrade test',
+  'recipients'=> 'test1@example.com,test2@example.com',
+  'reply' => 'Test reply',
+  'weight' => 1,
+  'selected' => 1,
+))
+->execute();