diff --git a/core/modules/system/js/system.modules.js b/core/modules/system/js/system.modules.js
index 49a9879..add01b9 100644
--- a/core/modules/system/js/system.modules.js
+++ b/core/modules/system/js/system.modules.js
@@ -3,7 +3,7 @@
  * Module page behaviors.
  */
 
-(function ($, Drupal) {
+(function ($, Drupal, debounce) {
 
   "use strict";
 
@@ -15,7 +15,7 @@
    *
    * Text search input: input.table-filter-text
    * Target table:      input.table-filter-text[data-table]
-   * Source text:       .table-filter-text-source
+   * Source text:       .table-filter-text-source, .module-name, .module-description
    *
    * @type {Drupal~behavior}
    */
@@ -30,17 +30,19 @@
 
       function hidePackageDetails(index, element) {
         var $packDetails = $(element);
-        var $visibleRows = $packDetails.find('table:not(.sticky-header)').find('tbody tr:visible');
+        var $visibleRows = $packDetails.find('tbody tr:visible');
         $packDetails.toggle($visibleRows.length > 0);
       }
 
       function filterModuleList(e) {
-        var query = $(e.target).val().toLowerCase();
+        var query = $(e.target).val();
+        // Case insensitive search expression to find query at the beginning of a word.
+        var re = new RegExp('\\b' + query, 'i');
 
         function showModuleRow(index, row) {
           var $row = $(row);
-          var $sources = $row.find('.table-filter-text-source');
-          var textMatch = $sources.text().toLowerCase().indexOf(query) !== -1;
+          var $sources = $row.find('.table-filter-text-source, .module-name, .module-description');
+          var textMatch = $sources.text().search(re) !== -1;
           $row.closest('tr').toggle(textMatch);
         }
         // Search over all rows and packages.
@@ -59,6 +61,13 @@
           // Hide the package <details> if they don't have any visible rows.
           // Note that we first show() all <details> to be able to use ':visible'.
           $details.attr('open', true).each(hidePackageDetails);
+
+          Drupal.announce(
+            Drupal.t(
+              '!modules modules are available in the modified list.',
+              { '!modules': $rowsAndDetails.find('tbody tr:visible').length }
+            )
+          );
         }
         else if (searching) {
           searching = false;
@@ -71,14 +80,24 @@
         }
       }
 
+      function preventEnterKey(event) {
+        if (event.which === 13) {
+          event.preventDefault();
+          event.stopPropagation();
+        }
+      }
+
       if ($table.length) {
         $rowsAndDetails = $table.find('tr, details');
         $rows = $table.find('tbody tr');
         $details = $rowsAndDetails.filter('.package-listing');
 
-        $input.on('keyup', filterModuleList);
+        $input.on({
+          keyup: debounce(filterModuleList, 200),
+          keydown: preventEnterKey
+        });
       }
     }
   };
 
-}(jQuery, Drupal));
+}(jQuery, Drupal, Drupal.debounce));
diff --git a/core/modules/system/src/Form/ModulesListConfirmForm.php b/core/modules/system/src/Form/ModulesListConfirmForm.php
index 5449b41..42694dc 100644
--- a/core/modules/system/src/Form/ModulesListConfirmForm.php
+++ b/core/modules/system/src/Form/ModulesListConfirmForm.php
@@ -150,16 +150,13 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     $account = $this->currentUser()->id();
     $this->keyValueExpirable->delete($account);
 
-    // Gets list of modules prior to install process.
-    $before = $this->moduleHandler->getModuleList();
-
-    // Install the given modules.
     if (!empty($this->modules['install'])) {
       // Don't catch the exception that this can throw for missing dependencies:
       // the form doesn't allow modules with unmet dependencies, so the only way
       // this can happen is if the filesystem changed between form display and
       // submit, in which case the user has bigger problems.
       try {
+        // Install the given modules.
         $this->moduleInstaller->install(array_keys($this->modules['install']));
       }
       catch (PreExistingConfigException $e) {
@@ -184,12 +181,12 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         );
         return;
       }
-    }
 
-    // Gets module list after install process, flushes caches and displays a
-    // message if there are changes.
-    if ($before != $this->moduleHandler->getModuleList()) {
-      drupal_set_message($this->t('The configuration options have been saved.'));
+      $module_names = array_values($this->modules['install']);
+      drupal_set_message(\Drupal::translation()->formatPlural(count($module_names), 'Module %name has been enabled.', '@count modules have been enabled: %names.', array(
+        '%name' => $module_names[0],
+        '%names' => implode(', ', $module_names),
+      )));
     }
 
     $form_state->setRedirectUrl($this->getCancelUrl());
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 173fcc7..5af04c5 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -171,9 +171,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['filters']['text'] = array(
       '#type' => 'search',
-      '#title' => $this->t('Search'),
+      '#title' => $this->t('Filter modules'),
+      '#title_display' => 'invisible',
       '#size' => 30,
-      '#placeholder' => $this->t('Enter module name'),
+      '#placeholder' => $this->t('Filter by name or description'),
+      '#description' => t('Enter all or part of a module name.'),
       '#attributes' => array(
         'class' => array('table-filter-text'),
         'data-table' => '#system-modules',
@@ -503,13 +505,15 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       return;
     }
 
-    // Gets list of modules prior to install process.
-    $before = $this->moduleHandler->getModuleList();
-
-    // There seem to be no dependencies that would need approval.
+    // Install the given modules.
     if (!empty($modules['install'])) {
       try {
         $this->moduleInstaller->install(array_keys($modules['install']));
+        $module_names = array_values($modules['install']);
+        drupal_set_message(\Drupal::translation()->formatPlural(count($module_names), 'Module %name has been enabled.', '@count modules have been enabled: %names.', array(
+          '%name' => $module_names[0],
+          '%names' => implode(', ', $module_names),
+        )));
       }
       catch (PreExistingConfigException $e) {
         $config_objects = $e->flattenConfigObjects($e->getConfigObjects());
@@ -534,12 +538,6 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
         return;
       }
     }
-
-    // Gets module list after install process, flushes caches and displays a
-    // message if there are changes.
-    if ($before != $this->moduleHandler->getModuleList()) {
-      drupal_set_message(t('The configuration options have been saved.'));
-    }
   }
 
 }
diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php
index f72fa43..39252c6 100644
--- a/core/modules/system/src/Form/ModulesUninstallForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallForm.php
@@ -99,9 +99,11 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     $form['filters']['text'] = array(
       '#type' => 'search',
-      '#title' => $this->t('Search'),
+      '#title' => $this->t('Filter modules'),
+      '#title_display' => 'invisible',
       '#size' => 30,
-      '#placeholder' => $this->t('Enter module name'),
+      '#placeholder' => $this->t('Filter by name or description'),
+      '#description' => t('Enter all or part of a module name.'),
       '#attributes' => array(
         'class' => array('table-filter-text'),
         'data-table' => '#system-modules-uninstall',
diff --git a/core/modules/system/src/Tests/Module/DependencyTest.php b/core/modules/system/src/Tests/Module/DependencyTest.php
index 13a722d..24d18c3 100644
--- a/core/modules/system/src/Tests/Module/DependencyTest.php
+++ b/core/modules/system/src/Tests/Module/DependencyTest.php
@@ -46,8 +46,7 @@ function testEnableWithoutDependency() {
     $this->assertTableCount('language', FALSE);
 
     $this->drupalPostForm(NULL, NULL, t('Continue'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
-
+    $this->assertText(t('2 modules have been enabled: Content Translation, Language.'), 'Modules status has been updated.');
     $this->assertModules(array('content_translation', 'language'), TRUE);
 
     // Assert that the language YAML files were created.
diff --git a/core/modules/system/src/Tests/Module/InstallUninstallTest.php b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
index b26cb7c..5e3f58a 100644
--- a/core/modules/system/src/Tests/Module/InstallUninstallTest.php
+++ b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
@@ -85,7 +85,16 @@ public function testInstallUninstall() {
         $this->drupalPostForm(NULL, array(), t('Continue'));
       }
 
-      $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+      // List the module display names to check the confirmation message.
+      $module_names = array();
+      foreach ($modules_to_install as $module_to_install) {
+        $module_names[] = $all_modules[$module_to_install]->info['name'];
+      }
+      $expected_text = \Drupal::translation()->formatPlural(count($module_names), 'Module @name has been enabled.', '@count modules have been enabled: @names.', array(
+        '@name' => $module_names[0],
+        '@names' => implode(', ', $module_names),
+      ));
+      $this->assertText($expected_text, 'Modules status has been updated.');
 
       // Check that hook_modules_installed() was invoked with the expected list
       // of modules, that each module's database tables now exist, and that
@@ -139,7 +148,7 @@ public function testInstallUninstall() {
       $edit['modules[' . $module->info['package'] . '][' . $name . '][enable]'] = TRUE;
     }
     $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+    $this->assertText(t('@count modules have been enabled: ', array('@count' => count($all_modules))), 'Modules status has been updated.');
   }
 
   /**
diff --git a/core/modules/system/src/Tests/System/MainContentFallbackTest.php b/core/modules/system/src/Tests/System/MainContentFallbackTest.php
index 56a7e85..6d214e8 100644
--- a/core/modules/system/src/Tests/System/MainContentFallbackTest.php
+++ b/core/modules/system/src/Tests/System/MainContentFallbackTest.php
@@ -71,7 +71,7 @@ function testMainContentFallback() {
     $edit = array();
     $edit['modules[Core][block][enable]'] = 'block';
     $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
-    $this->assertText(t('The configuration options have been saved.'), 'Modules status has been updated.');
+    $this->assertText(t('Module Block has been enabled.'), 'Modules status has been updated.');
     $this->rebuildContainer();
     $this->assertTrue(\Drupal::moduleHandler()->moduleExists('block'), 'Block module re-enabled.');
   }
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 276e393..091077a 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -259,7 +259,7 @@ function theme_system_modules_details($variables) {
     }
     $details = array(
       '#type' => 'details',
-      '#title' => SafeMarkup::set('<span class="text"> ' . drupal_render($module['description']) . '</span>'),
+      '#title' => SafeMarkup::set('<span class="text module-description"> ' . drupal_render($module['description']) . '</span>'),
       '#attributes' => array('id' => $module['enable']['#id'] . '-description'),
       '#description' => $description,
     );
diff --git a/core/modules/system/system.libraries.yml b/core/modules/system/system.libraries.yml
index b440e15..06762f7 100644
--- a/core/modules/system/system.libraries.yml
+++ b/core/modules/system/system.libraries.yml
@@ -43,6 +43,7 @@ drupal.system.modules:
   dependencies:
     - core/jquery
     - core/drupal
+    - core/drupal.debounce
     - core/jquery.once
 
 diff:
