diff --git a/core/modules/comment/src/Tests/CommentFieldsTest.php b/core/modules/comment/src/Tests/CommentFieldsTest.php
index a5efac0..ede2e91 100644
--- a/core/modules/comment/src/Tests/CommentFieldsTest.php
+++ b/core/modules/comment/src/Tests/CommentFieldsTest.php
@@ -165,12 +165,12 @@ function testCommentInstallAfterContentModule() {
     // Install core content type module (book).
     $edit = array();
     $edit['modules[Core][book][enable]'] = 'book';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Now install the comment module.
     $edit = array();
     $edit['modules[Core][comment][enable]'] = 'comment';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->rebuildContainer();
     $this->assertTrue($this->container->get('module_handler')->moduleExists('comment'), 'Comment module enabled.');
 
diff --git a/core/modules/config/src/Tests/ConfigInstallWebTest.php b/core/modules/config/src/Tests/ConfigInstallWebTest.php
index cff60a4..221d09f 100644
--- a/core/modules/config/src/Tests/ConfigInstallWebTest.php
+++ b/core/modules/config/src/Tests/ConfigInstallWebTest.php
@@ -127,7 +127,7 @@ public function testPreExistingConfigInstall() {
     // will install the config_test module first because it is a dependency of
     // config_install_fail_test.
     // @see \Drupal\system\Form\ModulesListForm::submitForm()
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE, 'modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE, 'modules[Testing][config_install_fail_test][enable]' => TRUE), t('Install'));
     $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default</em> already exists in active configuration.');
 
     // Uninstall the config_test module to test the confirm form.
@@ -138,7 +138,7 @@ public function testPreExistingConfigInstall() {
     // The user is shown a confirm form because the config_test module is a
     // dependency.
     // @see \Drupal\system\Form\ModulesListConfirmForm::submitForm()
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Install'));
     $this->drupalPostForm(NULL, array(), t('Continue'));
     $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default</em> already exists in active configuration.');
 
@@ -152,7 +152,7 @@ public function testPreExistingConfigInstall() {
       ->set('label', 'Je suis Charlie')
       ->save();
 
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_fail_test][enable]' => TRUE), t('Install'));
     $this->assertRaw('Unable to install Configuration install fail test, <em class="placeholder">config_test.dynamic.dotted.default, language/fr/config_test.dynamic.dotted.default</em> already exist in active configuration.');
 
     // Test installing a theme through the UI that has existing configuration.
@@ -183,12 +183,12 @@ public function testUnmetDependenciesInstall() {
     $this->drupalLogin($this->adminUser);
     // We need to install separately since config_install_dependency_test does
     // not depend on config_test and order is important.
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE), t('Save configuration'));
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_test][enable]' => TRUE), t('Install'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Install'));
     $this->assertRaw('Unable to install Config install dependency test, <em class="placeholder">config_test.dynamic.other_module_test_with_dependency</em> has unmet dependencies.');
 
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_other_module_config_test][enable]' => TRUE), t('Save configuration'));
-    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_other_module_config_test][enable]' => TRUE), t('Install'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][config_install_dependency_test][enable]' => TRUE), t('Install'));
     $this->rebuildContainer();
     $this->assertTrue(entity_load('config_test', 'other_module_test_with_dependency'), 'The config_test.dynamic.other_module_test_with_dependency configuration has been created during install.');
   }
diff --git a/core/modules/language/src/Tests/LanguageListModuleInstallTest.php b/core/modules/language/src/Tests/LanguageListModuleInstallTest.php
index eae3f1a..00a7677 100644
--- a/core/modules/language/src/Tests/LanguageListModuleInstallTest.php
+++ b/core/modules/language/src/Tests/LanguageListModuleInstallTest.php
@@ -34,7 +34,7 @@ function testModuleInstallLanguageList() {
     $this->drupalLogin($admin_user);
     $edit = array();
     $edit['modules[Multilingual][language][enable]'] = 'language';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     $this->assertEqual(\Drupal::state()->get('language_test.language_count_preinstall', 0), 1, 'Using LanguageManager::getLanguages() returns 1 language during Language installation.');
 
diff --git a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
index 64ea797..39fcccd 100644
--- a/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
+++ b/core/modules/locale/src/Tests/LocaleConfigTranslationTest.php
@@ -125,7 +125,7 @@ public function testConfigTranslation() {
     $this->assertFalse($string, 'Configuration strings have been created upon installation.');
 
     // Enable the image module.
-    $this->drupalPostForm('admin/modules', array('modules[Field types][image][enable]' => "1"), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Field types][image][enable]' => "1"), t('Install'));
     $this->rebuildContainer();
 
     $string = $this->storage->findString(array('source' => 'Medium (220×220)', 'context' => '', 'type' => 'configuration'));
@@ -204,12 +204,12 @@ public function testConfigTranslation() {
   public function testOptionalConfiguration() {
     $this->assertNodeConfig(FALSE, FALSE);
     // Enable the node module.
-    $this->drupalPostForm('admin/modules', ['modules[Core][node][enable]' => "1"], t('Save configuration'));
+    $this->drupalPostForm('admin/modules', ['modules[Core][node][enable]' => "1"], t('Install'));
     $this->drupalPostForm(NULL, [], t('Continue'));
     $this->rebuildContainer();
     $this->assertNodeConfig(TRUE, FALSE);
     // Enable the views module (which node provides some optional config for).
-    $this->drupalPostForm('admin/modules', ['modules[Core][views][enable]' => "1"], t('Save configuration'));
+    $this->drupalPostForm('admin/modules', ['modules[Core][views][enable]' => "1"], t('Install'));
     $this->rebuildContainer();
     $this->assertNodeConfig(TRUE, TRUE);
   }
diff --git a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
index ef53b8c..3870cb0 100644
--- a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
+++ b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
@@ -42,7 +42,7 @@ public function setUp() {
    */
   public function testCircularDependency() {
     // Ensure that we can enable early_translation_test on a non-english site.
-    $this->drupalPostForm('admin/modules', array('modules[Testing][early_translation_test][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Testing][early_translation_test][enable]' => TRUE), t('Install'));
     $this->assertResponse(200);
   }
 
diff --git a/core/modules/locale/src/Tests/LocaleUpdateTest.php b/core/modules/locale/src/Tests/LocaleUpdateTest.php
index c4f4fe8..494c433 100644
--- a/core/modules/locale/src/Tests/LocaleUpdateTest.php
+++ b/core/modules/locale/src/Tests/LocaleUpdateTest.php
@@ -315,7 +315,7 @@ public function testEnableUninstallModule() {
     $edit = array(
       'modules[Testing][locale_test_translate][enable]' => 'locale_test_translate',
     );
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Check if translations have been imported.
     $this->assertRaw(t('One translation file imported. %number translations were added, %update translations were updated and %delete translations were removed.',
@@ -350,7 +350,7 @@ public function testEnableLanguage() {
     $edit = array(
       'modules[Testing][locale_test_translate][enable]' => 'locale_test_translate',
     );
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Check if there is no Dutch translation yet.
     $this->assertTranslation('Extraday', '', 'nl');
@@ -394,7 +394,7 @@ public function testEnableCustomLanguage() {
     $edit = array(
       'modules[Testing][locale_test_translate][enable]' => 'locale_test_translate',
     );
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Create a custom language with language code 'xx' and a random
     // name.
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..dea5207 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($this->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 73b32ec..289928f 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -183,14 +183,15 @@ 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' => $this->t('Enter a part of the module name or description'),
       '#attributes' => array(
         'class' => array('table-filter-text'),
         'data-table' => '#system-modules',
         'autocomplete' => 'off',
-        'title' => $this->t('Enter a part of the module name or description to filter by.'),
       ),
     );
 
@@ -238,7 +239,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $form['actions'] = array('#type' => 'actions');
     $form['actions']['submit'] = array(
       '#type' => 'submit',
-      '#value' => $this->t('Save configuration'),
+      '#value' => $this->t('Install'),
       '#button_type' => 'primary',
     );
 
@@ -515,13 +516,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($this->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());
@@ -546,12 +549,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 c74439e..c59b146 100644
--- a/core/modules/system/src/Form/ModulesUninstallForm.php
+++ b/core/modules/system/src/Form/ModulesUninstallForm.php
@@ -99,14 +99,15 @@ 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' => $this->t('Enter a part of the module name or description'),
       '#attributes' => array(
         'class' => array('table-filter-text'),
         'data-table' => '#system-modules-uninstall',
         'autocomplete' => 'off',
-        'title' => $this->t('Enter a part of the module name or description to filter by.'),
       ),
     );
 
diff --git a/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageTest.php b/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageTest.php
index 53538b1..3a0852b 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTranslationMultipleLanguageTest.php
@@ -125,7 +125,7 @@ public function testTranslationsLoaded() {
         'modules[Core][views][enable]' => TRUE,
         'modules[Core][filter][enable]' => TRUE,
       );
-      $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+      $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
       // Verify the strings from the translation are still as expected.
       $this->verifyImportedStringsTranslated();
diff --git a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
index 215f60e..b0e6597 100644
--- a/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
+++ b/core/modules/system/src/Tests/Installer/InstallerTranslationTest.php
@@ -68,7 +68,7 @@ public function testInstaller() {
     $this->assertEqual($account->language()->getId(), 'de', 'New user is German.');
 
     // Ensure that we can enable basic_auth on a non-english site.
-    $this->drupalPostForm('admin/modules', array('modules[Web services][basic_auth][enable]' => TRUE), t('Save configuration'));
+    $this->drupalPostForm('admin/modules', array('modules[Web services][basic_auth][enable]' => TRUE), t('Install'));
     $this->assertResponse(200);
 
     // Assert that the theme CSS was added to the page.
diff --git a/core/modules/system/src/Tests/Module/DependencyTest.php b/core/modules/system/src/Tests/Module/DependencyTest.php
index 13a722d..e9162a8 100644
--- a/core/modules/system/src/Tests/Module/DependencyTest.php
+++ b/core/modules/system/src/Tests/Module/DependencyTest.php
@@ -21,12 +21,12 @@ function testProjectNamespaceForDependencies() {
     $edit = array(
       'modules[Core][filter][enable]' => TRUE,
     );
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     // Enable module with project namespace to ensure nothing breaks.
     $edit = array(
       'modules[Testing][system_project_namespace_test][enable]' => TRUE,
     );
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->assertModules(array('system_project_namespace_test'), TRUE);
   }
 
@@ -37,7 +37,7 @@ function testEnableWithoutDependency() {
     // Attempt to enable Content Translation without Language enabled.
     $edit = array();
     $edit['modules[Multilingual][content_translation][enable]'] = 'content_translation';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->assertText(t('Some required modules must be enabled'), 'Dependency required.');
 
     $this->assertModules(array('content_translation', 'language'), FALSE);
@@ -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.
@@ -109,7 +108,7 @@ function testEnableRequirementsFailureDependency() {
     $edit = array();
     $edit['modules[Testing][requirements1_test][enable]'] = 'requirements1_test';
     $edit['modules[Testing][requirements2_test][enable]'] = 'requirements2_test';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Makes sure the modules were NOT installed.
     $this->assertText(t('Requirements 1 Test failed requirements'), 'Modules status has been updated.');
@@ -140,7 +139,7 @@ function testModuleEnableOrder() {
     // is correct.
     $edit = array();
     $edit['modules[Core][color][enable]'] = 'color';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->assertModules(array('color'), FALSE);
     // Note that dependencies are sorted alphabetically in the confirmation
     // message.
@@ -148,7 +147,7 @@ function testModuleEnableOrder() {
 
     $edit['modules[Core][config][enable]'] = 'config';
     $edit['modules[Core][help][enable]'] = 'help';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->assertModules(array('color', 'config', 'help'), TRUE);
 
     // Check the actual order which is saved by module_test_modules_enabled().
@@ -162,7 +161,7 @@ function testModuleEnableOrder() {
   function testUninstallDependents() {
     // Enable the forum module.
     $edit = array('modules[Core][forum][enable]' => 'forum');
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->drupalPostForm(NULL, array(), t('Continue'));
     $this->assertModules(array('forum'), TRUE);
 
diff --git a/core/modules/system/src/Tests/Module/HookRequirementsTest.php b/core/modules/system/src/Tests/Module/HookRequirementsTest.php
index ad87960..83fdce9 100644
--- a/core/modules/system/src/Tests/Module/HookRequirementsTest.php
+++ b/core/modules/system/src/Tests/Module/HookRequirementsTest.php
@@ -22,7 +22,7 @@ function testHookRequirementsFailure() {
     // Attempt to install the requirements1_test module.
     $edit = array();
     $edit['modules[Testing][requirements1_test][enable]'] = 'requirements1_test';
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
     // Makes sure the module was NOT installed.
     $this->assertText(t('Requirements 1 Test failed requirements'), 'Modules status has been updated.');
diff --git a/core/modules/system/src/Tests/Module/InstallUninstallTest.php b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
index b26cb7c..2295b75 100644
--- a/core/modules/system/src/Tests/Module/InstallUninstallTest.php
+++ b/core/modules/system/src/Tests/Module/InstallUninstallTest.php
@@ -77,7 +77,7 @@ public function testInstallUninstall() {
       $edit = array();
       $package = $module->info['package'];
       $edit["modules[$package][$name][enable]"] = TRUE;
-      $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+      $this->drupalPostForm('admin/modules', $edit, t('Install'));
 
       // Handle the case where modules were installed along with this one and
       // where we therefore hit a confirmation screen.
@@ -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
@@ -138,8 +147,8 @@ public function testInstallUninstall() {
     foreach ($all_modules as $name => $module) {
       $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->drupalPostForm('admin/modules', $edit, t('Install'));
+    $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..963bb76 100644
--- a/core/modules/system/src/Tests/System/MainContentFallbackTest.php
+++ b/core/modules/system/src/Tests/System/MainContentFallbackTest.php
@@ -70,8 +70,8 @@ function testMainContentFallback() {
     $this->drupalLogin($this->adminUser);
     $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->drupalPostForm('admin/modules', $edit, t('Install'));
+    $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..a88fade 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,
     );
@@ -332,7 +332,7 @@ function theme_system_modules_uninstall($variables) {
       array(
         'data' => array(
           '#type' => 'inline_template',
-          '#template' => '{{ module_description }} {% if disabled_header is not empty %} <div class="admin-requirements">{{ disabled_header }}{{ disabled_reasons }}</div> {% endif %}',
+          '#template' => '<span class="text module-description">{{ module_description }}</span>{% if disabled_header is not empty %}<div class="admin-requirements">{{ disabled_header }}{{ disabled_reasons }}</div>{% endif %}',
           '#context' => array(
             'module_description' => drupal_render($form['modules'][$module]['description']),
             'disabled_header' => $disabled_header,
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:
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 732e27b..d547da3 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -125,7 +125,7 @@ function system_help($route_name, RouteMatchInterface $route_match) {
         }
       }
       else {
-        $output .= '<p>' . t('Regularly review available updates to maintain a secure and current site. Always run the <a href="!update-php">update script</a> each time a module is updated. Enable the Update Manager module to update and install modules and themes.', array('!update-php' => \Drupal::url('system.db_update'))) . '</p>';
+        $output .= '<p>' . t('Regularly review available updates to maintain a secure and current site. Always run the <a href="!update-php">update script</a> each time a module is updated. Enable the <a href="!update-manager">Update Manager module</a> to update and install modules and themes.', array('!update-php' => \Drupal::url('system.db_update'), '!update-manager' => \Drupal::url('system.modules_list', [], ['fragment' => 'module-update']))) . '</p>';
       }
       return $output;
 
diff --git a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
index 0f8ad49..8980191 100644
--- a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
+++ b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php
@@ -118,7 +118,7 @@ function testModuleStatusChangeSubtreesHashCacheClear() {
     // Enable a module.
     $edit = array();
     $edit['modules[Core][taxonomy][enable]'] = TRUE;
-    $this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
+    $this->drupalPostForm('admin/modules', $edit, t('Install'));
     $this->rebuildContainer();
 
     // Assert that the subtrees hash has been altered because the subtrees
