diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index f1e0be1..e78e40f 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1550,12 +1550,12 @@ function install_import_translations(&$install_state) {
 
   $langcode = $install_state['parameters']['langcode'];
   $language = ConfigurableLanguage::createFromLangcode($langcode);
-  $language->set('default', TRUE);
   $language->save();
 
-  // If a non-English language was selected, remove English and import the
-  // translations.
+  // If a non-English language was selected, change the default language,
+  // remove English and import the translations.
   if ($langcode != 'en') {
+    \Drupal::config('system.site')->set('langcode', $langcode)->save();
     entity_delete_multiple('configurable_language', array('en'));
 
     // Set up a batch to import translations for the newly added language.
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index c1069a1..a5bd308 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -1037,7 +1037,7 @@ protected function compileContainer() {
     $default_language_values = Language::$defaultValues;
     if ($system = $this->getConfigStorage()->read('system.site')) {
       if ($default_language_values['id'] != $system['langcode']) {
-        $default_language_values = array('id' => $system['langcode'], 'default' => TRUE);
+        $default_language_values = array('id' => $system['langcode']);
       }
     }
     $container->setParameter('language.default_values', $default_language_values);
diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index 0797003..9bf085a 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -25,7 +25,6 @@ class Language implements LanguageInterface {
     'direction' => self::DIRECTION_LTR,
     'weight' => 0,
     'locked' => FALSE,
-    'default' => TRUE,
   );
 
   // Properties within the Language are set up as the default language.
@@ -61,13 +60,6 @@ class Language implements LanguageInterface {
   public $weight = 0;
 
   /**
-   * Flag indicating if this is the only site default language.
-   *
-   * @var bool
-   */
-  public $default = FALSE;
-
-  /**
    * The language negotiation method used when a language was detected.
    *
    * The method ID, for example
@@ -146,7 +138,7 @@ public function getWeight() {
    * {@inheritdoc}
    */
   public function isDefault() {
-    return $this->default;
+    return static::getDefaultLangcode() == $this->getId();
   }
 
   /**
@@ -166,4 +158,15 @@ public static function sort(&$languages) {
     });
   }
 
+  /**
+   * Gets the default langcode.
+   *
+   * @return string
+   *   The current default langcode.
+   */
+  protected static function getDefaultLangcode() {
+    $language = \Drupal::service('language.default')->get();
+    return $language->getId();
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Language/LanguageDefault.php b/core/lib/Drupal/Core/Language/LanguageDefault.php
index 1ca8009..4454489 100644
--- a/core/lib/Drupal/Core/Language/LanguageDefault.php
+++ b/core/lib/Drupal/Core/Language/LanguageDefault.php
@@ -53,7 +53,6 @@ public function get() {
    *   The default language.
    */
   public function set(LanguageInterface $language) {
-    $language->default = TRUE;
     $this->language = $language;
   }
 
diff --git a/core/lib/Drupal/Core/Path/PathValidator.php b/core/lib/Drupal/Core/Path/PathValidator.php
index 1b519c7..b6c3a5a 100644
--- a/core/lib/Drupal/Core/Path/PathValidator.php
+++ b/core/lib/Drupal/Core/Path/PathValidator.php
@@ -102,7 +102,6 @@ public function getUrlIfValid($path) {
       return Url::createFromPath($path);
     }
 
-    $path = ltrim($path, '/');
     $request = Request::create('/' . $path);
     $attributes = $this->getPathAttributes($path, $request);
 
diff --git a/core/modules/action/action.module b/core/modules/action/action.module
index f1cde81..5e0412e 100644
--- a/core/modules/action/action.module
+++ b/core/modules/action/action.module
@@ -35,6 +35,17 @@ function action_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function action_permission() {
+  return array(
+    'administer actions' => array(
+      'title' => t('Administer actions'),
+    ),
+  );
+}
+
+/**
  * Implements hook_entity_type_build().
  */
 function action_entity_type_build(array &$entity_types) {
diff --git a/core/modules/action/action.permissions.yml b/core/modules/action/action.permissions.yml
deleted file mode 100644
index 0f00dcd..0000000
--- a/core/modules/action/action.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer actions:
-  title: 'Administer actions'
diff --git a/core/modules/aggregator/aggregator.module b/core/modules/aggregator/aggregator.module
index 7361345..64eb275 100644
--- a/core/modules/aggregator/aggregator.module
+++ b/core/modules/aggregator/aggregator.module
@@ -93,6 +93,20 @@ function aggregator_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function aggregator_permission() {
+  return array(
+    'administer news feeds' => array(
+      'title' => t('Administer news feeds'),
+    ),
+    'access news feeds' => array(
+      'title' => t('View news feeds'),
+    ),
+  );
+}
+
+/**
  * Implements hook_cron().
  *
  * Queues news feeds for updates once their refresh interval has elapsed.
diff --git a/core/modules/aggregator/aggregator.permissions.yml b/core/modules/aggregator/aggregator.permissions.yml
deleted file mode 100644
index e96ddb4..0000000
--- a/core/modules/aggregator/aggregator.permissions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-administer news feeds:
-  title: 'Administer news feeds'
-access news feeds:
-  title: 'View news feeds'
diff --git a/core/modules/ban/ban.module b/core/modules/ban/ban.module
index b6270af..2d048d4 100644
--- a/core/modules/ban/ban.module
+++ b/core/modules/ban/ban.module
@@ -27,3 +27,14 @@ function ban_help($route_name, RouteMatchInterface $route_match) {
       return '<p>' . t('IP addresses listed here are banned from your site. Banned addresses are completely forbidden from accessing the site and instead see a brief message explaining the situation.') . '</p>';
   }
 }
+
+/**
+ * Implements hook_permission().
+ */
+function ban_permission() {
+  return array(
+    'ban IP addresses' => array(
+      'title' => t('Ban IP addresses'),
+    ),
+  );
+}
diff --git a/core/modules/ban/ban.permissions.yml b/core/modules/ban/ban.permissions.yml
deleted file mode 100644
index 7f385fd..0000000
--- a/core/modules/ban/ban.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-ban IP addresses:
-  title: 'Ban IP addresses'
diff --git a/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php b/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
index 1c4a919..62346a1 100644
--- a/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
+++ b/core/modules/basic_auth/src/Tests/Authentication/BasicAuthTest.php
@@ -119,7 +119,8 @@ function testPerUserLoginFloodControl() {
    * Tests compatibility with locale/UI translation.
    */
   function testLocale() {
-    ConfigurableLanguage::create(array('id' => 'de', 'label' => 'German', 'default' => TRUE))->save();
+    ConfigurableLanguage::createFromLangcode('de')->save();
+    \Drupal::config('system.site')->set('langcode', 'de')->save();
 
     $account = $this->drupalCreateUser();
 
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 9d31839..339d163 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -63,6 +63,17 @@ function block_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function block_permission() {
+  return array(
+    'administer blocks' => array(
+      'title' => t('Administer blocks'),
+    ),
+  );
+}
+
+/**
  * Implements hook_page_build().
  *
  * Renders blocks into their regions.
diff --git a/core/modules/block/block.permissions.yml b/core/modules/block/block.permissions.yml
deleted file mode 100644
index 83f35cd..0000000
--- a/core/modules/block/block.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer blocks:
-  title: 'Administer blocks'
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 861ed73..e67b279 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -83,6 +83,27 @@ function book_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function book_permission() {
+  return array(
+    'administer book outlines' => array(
+      'title' => t('Administer book outlines'),
+    ),
+    'create new books' => array(
+      'title' => t('Create new books'),
+    ),
+    'add content to books' => array(
+      'title' => t('Add content and child pages to books'),
+    ),
+    'access printer-friendly version' => array(
+      'title' => t('View printer-friendly books'),
+      'description' => t('View a book page and all of its sub-pages as a single document for ease of printing. Can be performance heavy.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_entity_type_build().
  */
 function book_entity_type_build(array &$entity_types) {
diff --git a/core/modules/book/book.permissions.yml b/core/modules/book/book.permissions.yml
deleted file mode 100644
index 52dd9d0..0000000
--- a/core/modules/book/book.permissions.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-administer book outlines:
-  title: 'Administer book outlines'
-create new books:
-  title: 'Create new books'
-add content to books:
-  title: 'Add content and child pages to books'
-access printer-friendly version:
-  title: 'View printer-friendly books'
-  description: 'View a book page and all of its sub-pages as a single document for ease of printing. Can be performance heavy.'
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index b13d881..dbe3bee 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -198,6 +198,33 @@ function comment_field_instance_config_delete(FieldInstanceConfigInterface $inst
 }
 
 /**
+ * Implements hook_permission().
+ */
+function comment_permission() {
+  return array(
+    'administer comments' => array(
+      'title' => t('Administer comments and comment settings'),
+    ),
+    'administer comment types' => array(
+      'title' => t('Administer comment types and settings'),
+      'restrict access' => TRUE,
+    ),
+    'access comments' => array(
+      'title' => t('View comments'),
+    ),
+    'post comments' => array(
+      'title' => t('Post comments'),
+    ),
+    'skip comment approval' => array(
+      'title' => t('Skip comment approval'),
+    ),
+    'edit own comments' => array(
+      'title' => t('Edit own comments'),
+    ),
+  );
+}
+
+/**
  * Implements hook_entity_build_defaults_alter().
  */
 function comment_entity_build_defaults_alter(array &$build, EntityInterface $entity, $view_mode = 'full', $langcode = NULL) {
diff --git a/core/modules/comment/comment.permissions.yml b/core/modules/comment/comment.permissions.yml
deleted file mode 100644
index 664b5e1..0000000
--- a/core/modules/comment/comment.permissions.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-administer comments:
-  title: 'Administer comments and comment settings'
-administer comment types:
-  title: 'Administer comment types and settings'
-  restrict access: true
-access comments:
-  title: 'View comments'
-post comments:
-  title: 'Post comments'
-skip comment approval:
-  title: 'Skip comment approval'
-edit own comments:
-  title: 'Edit own comments'
diff --git a/core/modules/config/config.module b/core/modules/config/config.module
index 84e0210..e22b71b 100644
--- a/core/modules/config/config.module
+++ b/core/modules/config/config.module
@@ -28,6 +28,25 @@ function config_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function config_permission() {
+  $permissions['synchronize configuration'] = array(
+    'title' => t('Synchronize configuration'),
+    'restrict access' => TRUE,
+  );
+  $permissions['export configuration'] = array(
+    'title' => t('Export configuration'),
+    'restrict access' => TRUE,
+  );
+  $permissions['import configuration'] = array(
+    'title' => t('Import configuration'),
+    'restrict access' => TRUE,
+  );
+  return $permissions;
+}
+
+/**
  * Implements hook_file_download().
  */
 function config_file_download($uri) {
diff --git a/core/modules/config/config.permissions.yml b/core/modules/config/config.permissions.yml
deleted file mode 100644
index ee24216..0000000
--- a/core/modules/config/config.permissions.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-synchronize configuration:
-  title: 'Synchronize configuration'
-  restrict access: true
-export configuration:
-  title: 'Export configuration'
-  restrict access: true
-import configuration:
-  title: 'Import configuration'
-  restrict access: true
diff --git a/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php b/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
index 82f4d37..be24fb9 100644
--- a/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
+++ b/core/modules/config/src/Tests/ConfigLanguageOverrideWebTest.php
@@ -67,9 +67,7 @@ function testSiteNameTranslation() {
     // overrides still work.
     $language_manager = \Drupal::languageManager()->reset();
     $this->assertTrue($language_manager->isMultilingual(), 'The test site is multilingual.');
-    $language = ConfigurableLanguage::load('xx');
-    $language->set('default', TRUE);
-    $language->save();
+    \Drupal::config('system.site')->set('langcode', 'xx')->save();
 
     ConfigurableLanguage::load('en')->delete();
     $this->assertFalse($language_manager->isMultilingual(), 'The test site is monolingual.');
diff --git a/core/modules/config_translation/config_translation.module b/core/modules/config_translation/config_translation.module
index 6958c80..43aa754 100644
--- a/core/modules/config_translation/config_translation.module
+++ b/core/modules/config_translation/config_translation.module
@@ -37,6 +37,18 @@ function config_translation_help($route_name, RouteMatchInterface $route_match)
 }
 
 /**
+ * Implements hook_permission().
+ */
+function config_translation_permission() {
+  return array(
+    'translate configuration' => array(
+      'title' => t('Translate user edited configuration'),
+      'description' => t('Translate any configuration not shipped with modules and themes.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function config_translation_theme() {
diff --git a/core/modules/config_translation/config_translation.permissions.yml b/core/modules/config_translation/config_translation.permissions.yml
deleted file mode 100644
index bbba883..0000000
--- a/core/modules/config_translation/config_translation.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-translate configuration:
-  title: 'Translate user edited configuration'
-  description: 'Translate any configuration not shipped with modules and themes.'
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index f1dfca7..3a72233 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -39,6 +39,23 @@ function contact_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function contact_permission() {
+  return array(
+    'administer contact forms' => array(
+      'title' => t('Administer contact forms and contact form settings'),
+    ),
+    'access site-wide contact form' => array(
+      'title' => t('Use the site-wide contact form'),
+    ),
+    'access user contact forms' => array(
+      'title' => t("Use users' personal contact forms"),
+    ),
+  );
+}
+
+/**
  * Implements hook_entity_type_alter().
  */
 function contact_entity_type_alter(array &$entity_types) {
diff --git a/core/modules/contact/contact.permissions.yml b/core/modules/contact/contact.permissions.yml
deleted file mode 100644
index c04534d..0000000
--- a/core/modules/contact/contact.permissions.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-administer contact forms:
-  title: 'Administer contact forms and contact form settings'
-access site-wide contact form:
-  title: 'Use the site-wide contact form'
-access user contact forms:
-  title: 'Use users'' personal contact forms'
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 570bd4d..f1a1b60 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -361,6 +361,61 @@ function content_translation_access(EntityInterface $entity, $op) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function content_translation_permission() {
+  $permission = array(
+    'administer content translation' => array(
+      'title' => t('Administer translation settings'),
+      'description' => t('Configure translatability of entities and fields.'),
+    ),
+    'create content translations' => array(
+      'title' => t('Create translations'),
+    ),
+    'update content translations' => array(
+      'title' => t('Edit translations'),
+    ),
+    'delete content translations' => array(
+      'title' => t('Delete translations'),
+    ),
+    'translate any entity' => array(
+      'title' => t('Translate any entity'),
+    ),
+  );
+
+  // Create a translate permission for each enabled entity type and (optionally)
+  // bundle.
+  foreach (\Drupal::entityManager()->getDefinitions() as $entity_type_id => $entity_type) {
+    if ($permission_granularity = $entity_type->getPermissionGranularity()) {
+      $t_args = array('@entity_label' => $entity_type->getLowercaseLabel());
+
+      switch ($permission_granularity) {
+        case 'bundle':
+          foreach (entity_get_bundles($entity_type_id) as $bundle => $bundle_info) {
+            if (content_translation_enabled($entity_type_id, $bundle)) {
+              $t_args['%bundle_label'] = isset($bundle_info['label']) ? $bundle_info['label'] : $bundle;
+              $permission["translate $bundle $entity_type_id"] = array(
+                'title' => t('Translate %bundle_label @entity_label', $t_args),
+              );
+            }
+          }
+          break;
+
+        case 'entity_type':
+          if (content_translation_enabled($entity_type_id)) {
+            $permission["translate $entity_type_id"] = array(
+              'title' => t('Translate @entity_label', $t_args),
+            );
+          }
+          break;
+      }
+    }
+  }
+
+  return $permission;
+}
+
+/**
  * Implements hook_form_alter().
  */
 function content_translation_form_alter(array &$form, FormStateInterface $form_state) {
diff --git a/core/modules/content_translation/content_translation.permissions.yml b/core/modules/content_translation/content_translation.permissions.yml
deleted file mode 100644
index 79f30a4..0000000
--- a/core/modules/content_translation/content_translation.permissions.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-administer content translation:
-  title: 'Administer translation settings'
-  description: 'Configure translatability of entities and fields.'
-create content translations:
-  title: 'Create translations'
-update content translations:
-  title: 'Edit translations'
-delete content translations:
-  title: 'Delete translations'
-translate any entity:
-  title: 'Translate any entity'
-
-permission_callbacks:
-  - \Drupal\content_translation\ContentTranslationPermissions::contentPermissions
diff --git a/core/modules/content_translation/src/ContentTranslationPermissions.php b/core/modules/content_translation/src/ContentTranslationPermissions.php
deleted file mode 100644
index 35a664a..0000000
--- a/core/modules/content_translation/src/ContentTranslationPermissions.php
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\content_translation\ContentTranslationPermissions.
- */
-
-namespace Drupal\content_translation;
-
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides dynamic permissions for the content_translation module.
- */
-class ContentTranslationPermissions implements ContainerInjectionInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a ContentTranslationPermissions instance.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static($container->get('entity.manager'));
-  }
-
-  /**
-   * Returns an array of content translation permissions.
-   *
-   * @return array
-   */
-  public function contentPermissions() {
-    $permission = [];
-    // Create a translate permission for each enabled entity type and (optionally)
-    // bundle.
-    foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
-      if ($permission_granularity = $entity_type->getPermissionGranularity()) {
-        $t_args = ['@entity_label' => $entity_type->getLowercaseLabel()];
-
-        switch ($permission_granularity) {
-          case 'bundle':
-            foreach ($this->entityManager->getBundleInfo($entity_type_id) as $bundle => $bundle_info) {
-              if (content_translation_enabled($entity_type_id, $bundle)) {
-                $t_args['%bundle_label'] = isset($bundle_info['label']) ? $bundle_info['label'] : $bundle;
-                $permission["translate $bundle $entity_type_id"] = [
-                  'title' => $this->t('Translate %bundle_label @entity_label', $t_args),
-                ];
-              }
-            }
-            break;
-
-          case 'entity_type':
-            if (content_translation_enabled($entity_type_id)) {
-              $permission["translate $entity_type_id"] = [
-                'title' => $this->t('Translate @entity_label', $t_args),
-              ];
-            }
-            break;
-        }
-      }
-    }
-
-    return $permission;
-  }
-
-}
diff --git a/core/modules/contextual/contextual.module b/core/modules/contextual/contextual.module
index 47dc049..b799a5a 100644
--- a/core/modules/contextual/contextual.module
+++ b/core/modules/contextual/contextual.module
@@ -87,6 +87,18 @@ function contextual_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function contextual_permission() {
+  return array(
+    'access contextual links' => array(
+      'title' => t('Use contextual links'),
+      'description' => t('Use contextual links to perform actions related to elements on a page.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_element_info().
  */
 function contextual_element_info() {
diff --git a/core/modules/contextual/contextual.permissions.yml b/core/modules/contextual/contextual.permissions.yml
deleted file mode 100644
index 1798b1f..0000000
--- a/core/modules/contextual/contextual.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-access contextual links:
-  title: 'Use contextual links'
-  description: 'Use contextual links to perform actions related to elements on a page.'
diff --git a/core/modules/entity/entity.permissions.yml b/core/modules/entity/entity.permissions.yml
deleted file mode 100644
index 8149e15..0000000
--- a/core/modules/entity/entity.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer display modes:
-  title: 'Add, edit, and delete custom display modes.'
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index a419156..499c883 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -21,6 +21,23 @@
 require_once __DIR__ . '/field_test.field.inc';
 
 /**
+ * Implements hook_permission().
+ */
+function field_test_permission() {
+  $perms = array(
+    'view test_view_field content' => array(
+      'title' => t('View test field content'),
+      'description' => t('View published test_view_field content.'),
+    ),
+    'administer field_test content' => array(
+      'title' => t('Administer field_test content'),
+      'description' => t('Manage field_test content'),
+    ),
+  );
+  return $perms;
+}
+
+/**
  * Store and retrieve keyed data for later verification by unit tests.
  *
  * This function is a simple in-memory key-value store with the
diff --git a/core/modules/field/tests/modules/field_test/field_test.permissions.yml b/core/modules/field/tests/modules/field_test/field_test.permissions.yml
deleted file mode 100644
index a950bc7..0000000
--- a/core/modules/field/tests/modules/field_test/field_test.permissions.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-view test_view_field content:
-  title: 'View test field content'
-  description: 'View published test_view_field content.'
-administer field_test content:
-  title: 'Administer field_test content'
-  description: 'Manage field_test content'
diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module
index 822a38c..9dbcbd2 100644
--- a/core/modules/field_ui/field_ui.module
+++ b/core/modules/field_ui/field_ui.module
@@ -60,6 +60,36 @@ function field_ui_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function field_ui_permission() {
+  $permissions = array();
+
+  foreach (\Drupal::entityManager()->getDefinitions() as $entity_type_id => $entity_type) {
+    if ($entity_type->isFieldable()) {
+      // Create a permission for each fieldable entity to manage
+      // the fields and the display.
+      $permissions['administer ' . $entity_type_id . ' fields'] = array(
+        'title' => t('%entity_label: Administer fields', array('%entity_label' => $entity_type->getLabel())),
+        'restrict access' => TRUE,
+      );
+      $permissions['administer ' . $entity_type_id . ' form display'] = array(
+        'title' => t('%entity_label: Administer form display', array('%entity_label' => $entity_type->getLabel()))
+      );
+      $permissions['administer ' . $entity_type_id . ' display'] = array(
+        'title' => t('%entity_label: Administer display', array('%entity_label' => $entity_type->getLabel()))
+      );
+    }
+  }
+
+  $permissions['administer display modes'] = array(
+    'title' => t('Add, edit, and delete custom display modes.'),
+  );
+
+  return $permissions;
+}
+
+/**
  * Implements hook_theme().
  */
 function field_ui_theme() {
diff --git a/core/modules/field_ui/field_ui.permissions.yml b/core/modules/field_ui/field_ui.permissions.yml
deleted file mode 100644
index ae9d900..0000000
--- a/core/modules/field_ui/field_ui.permissions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-administer display modes:
-  title: 'Add, edit, and delete custom display modes.'
-
-permission_callbacks:
-  - Drupal\field_ui\FieldUiPermissions::fieldPermissions
diff --git a/core/modules/field_ui/src/FieldUiPermissions.php b/core/modules/field_ui/src/FieldUiPermissions.php
deleted file mode 100644
index c71e938..0000000
--- a/core/modules/field_ui/src/FieldUiPermissions.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\field_ui\FieldUiPermissions.
- */
-
-namespace Drupal\field_ui;
-
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides dynamic permissions of the field_ui module.
- */
-class FieldUiPermissions implements ContainerInjectionInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a new FieldUiPermissions instance.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static($container->get('entity.manager'));
-  }
-
-  /**
-   * Returns an array of field UI permissions.
-   *
-   * @return array
-   */
-  public function fieldPermissions() {
-    $permissions = [];
-
-    foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
-      if ($entity_type->isFieldable()) {
-        // Create a permission for each fieldable entity to manage
-        // the fields and the display.
-        $permissions['administer ' . $entity_type_id . ' fields'] = [
-          'title' => $this->t('%entity_label: Administer fields', ['%entity_label' => $entity_type->getLabel()]),
-          'restrict access' => TRUE,
-        ];
-        $permissions['administer ' . $entity_type_id . ' form display'] = [
-          'title' => $this->t('%entity_label: Administer form display', ['%entity_label' => $entity_type->getLabel()])
-        ];
-        $permissions['administer ' . $entity_type_id . ' display'] = [
-          'title' => $this->t('%entity_label: Administer display', ['%entity_label' => $entity_type->getLabel()])
-        ];
-      }
-    }
-
-    return $permissions;
-  }
-
-}
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index a516836..03e10bf 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -1890,6 +1890,20 @@ function file_get_file_references(FileInterface $file, FieldDefinitionInterface
 }
 
 /**
+ * Implements hook_permission().
+ */
+function file_permission() {
+  $perms = array(
+    'access files overview' => array(
+      'title' => t('Access the Files overview page'),
+      'description' => t('Get an overview of <a href="!url">all files</a>.', array('!url' => url('admin/content/files'))),
+    ),
+  );
+
+  return $perms;
+}
+
+/**
  * Formats human-readable version of file status.
  *
  * @param int $choice
diff --git a/core/modules/file/file.permissions.yml b/core/modules/file/file.permissions.yml
deleted file mode 100644
index 0572874..0000000
--- a/core/modules/file/file.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-access files overview:
-  title: 'Access the Files overview page'
-  description: 'Get an overview of all files.'
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 1423f5e..d31cca1 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -225,6 +225,32 @@ function filter_pre_render_text(array $element) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function filter_permission() {
+  $perms['administer filters'] = array(
+    'title' => t('Administer text formats and filters'),
+    'description' => t('Define how text is handled by combining filters into <a href="@url">text formats</a>.', array(
+      '@url' => url('admin/config/content/formats'),
+    )),
+    'restrict access' => TRUE,
+  );
+
+  // Generate permissions for each text format. Warn the administrator that any
+  // of them are potentially unsafe.
+  foreach (filter_formats() as $format) {
+    if ($permission = $format->getPermissionName()) {
+      $format_name_replacement = l($format->label(), 'admin/config/content/formats/manage/' . $format->id());
+      $perms[$permission] = array(
+        'title' => t("Use the !text_format text format", array('!text_format' => $format_name_replacement,)),
+        'description' => String::placeholder(t('Warning: This permission may have security implications depending on how the text format is configured.')),
+      );
+    }
+  }
+  return $perms;
+}
+
+/**
  * Retrieves a list of enabled text formats, ordered by weight.
  *
  * @param \Drupal\Core\Session\AccountInterface|null $account
diff --git a/core/modules/filter/filter.permissions.yml b/core/modules/filter/filter.permissions.yml
deleted file mode 100644
index 53d84b5..0000000
--- a/core/modules/filter/filter.permissions.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-administer filters:
-  title: 'Administer text formats and filters'
-  description: 'Define how text is handled by combining filters into text formats.'
-  restrict access: true
-
-permission_callbacks:
-  - Drupal\filter\FilterPermissions::permissions
diff --git a/core/modules/filter/src/Entity/FilterFormat.php b/core/modules/filter/src/Entity/FilterFormat.php
index 1f38428..c293025 100644
--- a/core/modules/filter/src/Entity/FilterFormat.php
+++ b/core/modules/filter/src/Entity/FilterFormat.php
@@ -210,8 +210,8 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
       // apply the defined user role permissions when a new format is inserted
       // and has a non-empty $roles property.
       // Note: user_role_change_permissions() triggers a call chain back into
-      // \Drupal\filter\FilterPermissions::permissions() and lastly
-      // filter_formats(), so its cache must be reset upfront.
+      // filter_permission() and lastly filter_formats(), so its cache must be
+      // reset upfront.
       if (($roles = $this->get('roles')) && $permission = $this->getPermissionName()) {
         foreach (user_roles() as $rid => $name) {
           $enabled = in_array($rid, $roles, TRUE);
diff --git a/core/modules/filter/src/FilterPermissions.php b/core/modules/filter/src/FilterPermissions.php
deleted file mode 100644
index 6e3fe7b..0000000
--- a/core/modules/filter/src/FilterPermissions.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\filter\FilterPermissions.
- */
-
-namespace Drupal\filter;
-
-use Drupal\Component\Utility\String;
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides dynamic permissions of the filter module.
- */
-class FilterPermissions implements ContainerInjectionInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a new FilterPermissions instance.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static($container->get('entity.manager'));
-  }
-
-  /**
-   * Returns an array of filter permissions.
-   *
-   * @return array
-   */
-  public function permissions() {
-    $permissions = [];
-    // Generate permissions for each text format. Warn the administrator that any
-    // of them are potentially unsafe.
-    /** @var \Drupal\filter\FilterFormatInterface[] $formats */
-    $formats = $this->entityManager->getStorage('filter_format')->loadByProperties(['status' => TRUE]);
-    uasort($formats, 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
-    foreach ($formats as $format) {
-      if ($permission = $format->getPermissionName()) {
-        $permissions[$permission] = [
-          'title' => $this->t('Use the <a href="@url">@label</a> text format', ['@url' => $format->url(), '@label' => $format->label()]),
-          'description' => String::placeholder($this->t('Warning: This permission may have security implications depending on how the text format is configured.')),
-        ];
-      }
-    }
-    return $permissions;
-  }
-
-}
diff --git a/core/modules/filter/src/Tests/FilterDefaultConfigTest.php b/core/modules/filter/src/Tests/FilterDefaultConfigTest.php
index 79a1160..1392e76 100644
--- a/core/modules/filter/src/Tests/FilterDefaultConfigTest.php
+++ b/core/modules/filter/src/Tests/FilterDefaultConfigTest.php
@@ -21,8 +21,7 @@ class FilterDefaultConfigTest extends DrupalUnitTestBase {
   protected function setUp() {
     parent::setUp();
 
-    // Drupal\filter\FilterPermissions::permissions() calls into url() to output
-    // a link in the description.
+    // filter_permission() calls into url() to output a link in the description.
     $this->installSchema('system', 'url_alias');
 
     $this->installEntitySchema('user');
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 0e7087d..039c305 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -344,6 +344,18 @@ function forum_node_storage_load($nodes) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function forum_permission() {
+  $perms = array(
+    'administer forums' => array(
+      'title' => t('Administer forums'),
+    ),
+  );
+  return $perms;
+}
+
+/**
  * Implements hook_ENTITY_TYPE_update() for comment entities.
  */
 function forum_comment_update(CommentInterface $comment) {
diff --git a/core/modules/forum/forum.permissions.yml b/core/modules/forum/forum.permissions.yml
deleted file mode 100644
index ed8ddb4..0000000
--- a/core/modules/forum/forum.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer forums:
-  title: 'Administer forums'
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index 998db33..a6ce171 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -153,6 +153,18 @@ function image_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function image_permission() {
+  return array(
+    'administer image styles' => array(
+      'title' => t('Administer image styles'),
+      'description' => t('Create and modify styles for generating image modifications such as thumbnails.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_file_download().
  *
  * Control the access to files underneath the styles directory.
diff --git a/core/modules/image/image.permissions.yml b/core/modules/image/image.permissions.yml
deleted file mode 100644
index bc07792..0000000
--- a/core/modules/image/image.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-administer image styles:
-  title: 'Administer image styles'
-  description: 'Create and modify styles for generating image modifications such as thumbnails.'
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 96c0a3f..a2f2396 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -88,6 +88,17 @@ function language_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function language_permission() {
+  return array(
+    'administer languages' => array(
+      'title' => t('Administer languages'),
+    ),
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function language_theme() {
@@ -444,10 +455,10 @@ function language_negotiation_url_prefixes_update() {
   foreach (\Drupal::languageManager()->getLanguages() as $language) {
     // The prefix for this language should be updated if it's not assigned yet
     // or the prefix is set to the empty string.
-    if (empty($prefixes[$language->id])) {
+    if (empty($prefixes[$language->getId()])) {
       // For the default language, set the prefix to the empty string,
       // otherwise use the langcode.
-      $prefixes[$language->id] = !empty($language->default) ? '' : $language->id;
+      $prefixes[$language->getId()] = $language->isDefault() ? '' : $language->id;
     }
     // Otherwise we keep the configured prefix.
   }
@@ -592,9 +603,7 @@ function language_form_system_regional_settings_alter(&$form, FormStateInterface
  * @see language_form_system_regional_settings_alter()
  */
 function language_system_regional_settings_form_submit($form, FormStateInterface $form_state) {
-  $default_language = ConfigurableLanguage::load($form_state->getValue('site_default_language'));
-  $default_language->set('default', TRUE);
-  $default_language->save();
+  \Drupal::config('system.site')->set('langcode', $form_state->getValue('site_default_language'))->save();
 }
 
 /**
diff --git a/core/modules/language/language.permissions.yml b/core/modules/language/language.permissions.yml
deleted file mode 100644
index 85c3b91..0000000
--- a/core/modules/language/language.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer languages:
-  title: 'Administer languages'
diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml
index 1eeb597..eae3af5 100644
--- a/core/modules/language/language.services.yml
+++ b/core/modules/language/language.services.yml
@@ -9,6 +9,7 @@ services:
       - [initLanguageManager]
   language.config_subscriber:
     class: Drupal\language\EventSubscriber\ConfigSubscriber
+    arguments: ['@language_manager', '@language.default']
     tags:
       - { name: event_subscriber }
   language.config_factory_override:
diff --git a/core/modules/language/src/Entity/ConfigurableLanguage.php b/core/modules/language/src/Entity/ConfigurableLanguage.php
index 6caf782..1b613de 100644
--- a/core/modules/language/src/Entity/ConfigurableLanguage.php
+++ b/core/modules/language/src/Entity/ConfigurableLanguage.php
@@ -7,12 +7,10 @@
 
 namespace Drupal\language\Entity;
 
-use Drupal\Core\Language\Language as LanguageObject;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Language\LanguageManager;
 use Drupal\language\ConfigurableLanguageManager;
-use Drupal\Core\Language\Language;
 use Drupal\language\ConfigurableLanguageManagerInterface;
 use Drupal\language\Exception\DeleteDefaultLanguageException;
 use Drupal\language\ConfigurableLanguageInterface;
@@ -83,21 +81,6 @@ class ConfigurableLanguage extends ConfigEntityBase implements ConfigurableLangu
   public $locked = FALSE;
 
   /**
-   * Flag to indicate if the language entity is the default site language.
-   *
-   * This property is not saved to the language entity since there can be only
-   * one default language. It is saved to system.site:langcode and set on the
-   * container using the language.default service in when the entity is saved.
-   * The value is set correctly when a language entity is created or loaded.
-   *
-   * @see \Drupal\language\Entity\ConfigurableLanguage::postSave()
-   * @see \Drupal\language\Entity\ConfigurableLanguage::isDefault()
-   *
-   * @var bool
-   */
-  protected $default;
-
-  /**
    * Used during saving to detect when the site becomes multilingual.
    *
    * This property is not saved to the language entity, but is needed for
@@ -121,16 +104,10 @@ class ConfigurableLanguage extends ConfigEntityBase implements ConfigurableLangu
   public $method_id;
 
   /**
-   * Checks if the language entity is the site default language.
-   *
-   * @return bool
-   *   TRUE if the language entity is the site default language, FALSE if not.
+   * {@inheritdoc}
    */
   public function isDefault() {
-    if (!isset($this->default)) {
-      return static::getDefaultLangcode() == $this->id();
-    }
-    return $this->default;
+    return static::getDefaultLangcode() == $this->id();
   }
 
   /**
@@ -154,24 +131,14 @@ public function preSave(EntityStorageInterface $storage) {
   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
     parent::postSave($storage, $update);
 
-    // Only set the default language and save it to system.site configuration if
-    // it needs to updated.
-    if ($this->isDefault() && static::getDefaultLangcode() != $this->id()) {
-      // Update the config. Saving the configuration fires and event that causes
-      // the container to be rebuilt.
-      \Drupal::config('system.site')->set('langcode', $this->id())->save();
-      \Drupal::service('language.default')->set($this->toLanguageObject());
-    }
-
     $language_manager = \Drupal::languageManager();
     $language_manager->reset();
     if ($language_manager instanceof ConfigurableLanguageManagerInterface) {
       $language_manager->updateLockedLanguageWeights();
     }
 
-    // Update URL Prefixes for all languages after the new default language is
-    // propagated and the LanguageManagerInterface::getLanguages() cache is
-    // flushed.
+    // Update URL Prefixes for all languages after the
+    // LanguageManagerInterface::getLanguages() cache is flushed.
     language_negotiation_url_prefixes_update();
 
     // If after adding this language the site will become multilingual, we need
@@ -186,26 +153,6 @@ public function postSave(EntityStorageInterface $storage, $update = TRUE) {
   }
 
   /**
-   * Converts the ConfigurableLanguage entity to a Core Language value object.
-   *
-   * @todo fix return type hint after https://drupal.org/node/2246665 and
-   *   https://drupal.org/node/2246679.
-   *
-   * @return \Drupal\Core\Language\LanguageInterface
-   *   The language configuration entity expressed as a Language value object.
-   */
-  protected function toLanguageObject() {
-    return new LanguageObject(array(
-      'id' => $this->id(),
-      'name' => $this->label(),
-      'direction' => $this->direction,
-      'weight' => $this->weight,
-      'locked' => $this->locked,
-      'default' => $this->default,
-    ));
-  }
-
-  /**
    * {@inheritdoc}
    *
    * @throws \DeleteDefaultLanguageException
@@ -239,18 +186,6 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function get($property_name) {
-    if ($property_name == 'default') {
-      return $this->isDefault();
-    }
-    else {
-      return parent::get($property_name);
-    }
-  }
-
-  /**
    * Gets the default langcode.
    *
    * @return string
diff --git a/core/modules/language/src/EventSubscriber/ConfigSubscriber.php b/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
index 1373a25..2b1c73c 100644
--- a/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
+++ b/core/modules/language/src/EventSubscriber/ConfigSubscriber.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\language\EventSubscriber;
 
+use Drupal\Core\Language\LanguageDefault;
+use Drupal\Core\Language\LanguageManagerInterface;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Config\ConfigCrudEvent;
 use Drupal\Core\Config\ConfigEvents;
@@ -18,6 +20,33 @@
 class ConfigSubscriber implements EventSubscriberInterface {
 
   /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * The default language.
+   *
+   * @var \Drupal\Core\Language\LanguageDefault
+   */
+  protected $languageDefault;
+
+  /**
+   * Constructs a new class object.
+   *
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   * @param \Drupal\Core\Language\LanguageDefault $language_default
+   *   The default language.
+   */
+  public function __construct(LanguageManagerInterface $language_manager, LanguageDefault $language_default) {
+    $this->languageManager = $language_manager;
+    $this->languageDefault = $language_default;
+  }
+
+  /**
    * Causes the container to be rebuilt on the next request.
    *
    * @param ConfigCrudEvent $event
@@ -26,6 +55,13 @@ class ConfigSubscriber implements EventSubscriberInterface {
   public function onConfigSave(ConfigCrudEvent $event) {
     $saved_config = $event->getConfig();
     if ($saved_config->getName() == 'system.site' && $event->isChanged('langcode')) {
+      $language = $this->languageManager->getLanguage($saved_config->get('langcode'));
+      // During an import the language might not exist yet.
+      if ($language) {
+        $this->languageDefault->set($language);
+        $this->languageManager->reset();
+        language_negotiation_url_prefixes_update();
+      }
       // Trigger a container rebuild on the next request by deleting compiled
       // from PHP storage.
       PhpStorageFactory::get('service_container')->deleteAll();
diff --git a/core/modules/language/src/Form/NegotiationUrlForm.php b/core/modules/language/src/Form/NegotiationUrlForm.php
index e2e241e..f28a53d 100644
--- a/core/modules/language/src/Form/NegotiationUrlForm.php
+++ b/core/modules/language/src/Form/NegotiationUrlForm.php
@@ -76,7 +76,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       $t_args = array('%language' => $language->name, '%langcode' => $language->id);
       $form['prefix'][$langcode] = array(
         '#type' => 'textfield',
-        '#title' => $language->default ? $this->t('%language (%langcode) path prefix (Default language)', $t_args) : $this->t('%language (%langcode) path prefix', $t_args),
+        '#title' => $language->isDefault() ? $this->t('%language (%langcode) path prefix (Default language)', $t_args) : $this->t('%language (%langcode) path prefix', $t_args),
         '#maxlength' => 64,
         '#default_value' => isset($prefixes[$langcode]) ? $prefixes[$langcode] : '',
         '#field_prefix' => $base_url . '/',
@@ -106,7 +106,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
       $value = $form_state->getValue(array('prefix', $langcode));
 
       if ($value === '') {
-        if (!$language->default && $form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) {
+        if (!$language->isDefault() && $form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_PATH_PREFIX) {
           // Throw a form error if the prefix is blank for a non-default language,
           // although it is required for selected negotiation type.
           $form_state->setErrorByName("prefix][$langcode", $this->t('The prefix may only be left blank for the default language.'));
@@ -130,7 +130,7 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
       $value = $form_state->getValue(array('domain', $langcode));
 
       if ($value === '') {
-        if (!$language->default && $form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_DOMAIN) {
+        if (!$language->isDefault() && $form_state->getValue('language_negotiation_url_part') == LanguageNegotiationUrl::CONFIG_DOMAIN) {
           // Throw a form error if the domain is blank for a non-default language,
           // although it is required for selected negotiation type.
           $form_state->setErrorByName("domain][$langcode", $this->t('The domain may only be left blank for the default language.'));
diff --git a/core/modules/language/src/LanguageServiceProvider.php b/core/modules/language/src/LanguageServiceProvider.php
index 0561814..be89900 100644
--- a/core/modules/language/src/LanguageServiceProvider.php
+++ b/core/modules/language/src/LanguageServiceProvider.php
@@ -100,7 +100,7 @@ protected function getDefaultLanguageValues() {
     $system = $config_storage->read('system.site');
     $default_language = $config_storage->read(static::CONFIG_PREFIX . $system['langcode']);
     if (is_array($default_language)) {
-      return $default_language + array('default' => TRUE);
+      return $default_language;
     }
     return FALSE;
   }
diff --git a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
index 4f3d880..6815955 100644
--- a/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
+++ b/core/modules/language/src/Tests/LanguageConfigurationElementTest.php
@@ -83,18 +83,16 @@ public function testDefaultLangcode() {
     $old_default = \Drupal::languageManager()->getDefaultLanguage();
     // Ensure the language entity default value is correct.
     $configurable_language = entity_load('configurable_language', $old_default->getId());
-    $this->assertTrue($configurable_language->get('default'), 'The en language entity is flagged as the default language.');
+    $this->assertTrue($configurable_language->isDefault(), 'The en language entity is flagged as the default language.');
 
-    $new_default = ConfigurableLanguage::load('cc');
-    $new_default->set('default', TRUE);
-    $new_default->save();
+    \Drupal::config('system.site')->set('langcode', 'cc')->save();
     language_save_default_configuration('custom_type', 'custom_bundle', array('langcode' => 'site_default', 'language_show' => TRUE));
     $langcode = language_get_default_langcode('custom_type', 'custom_bundle');
     $this->assertEqual($langcode, 'cc');
 
     // Ensure the language entity default value is correct.
     $configurable_language = entity_load('configurable_language', $old_default->getId());
-    $this->assertFalse($configurable_language->get('default'), 'The en language entity is not flagged as the default language.');
+    $this->assertFalse($configurable_language->isDefault(), 'The en language entity is not flagged as the default language.');
     $configurable_language = entity_load('configurable_language', 'cc');
     // Check calling the
     // \Drupal\language\Entity\ConfigurableLanguage::isDefault() method
diff --git a/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php b/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
index 44776bb..70b0d69 100644
--- a/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
+++ b/core/modules/language/src/Tests/LanguageDependencyInjectionTest.php
@@ -42,13 +42,8 @@ function testDependencyInjectedNewLanguage() {
   function testDependencyInjectedNewDefaultLanguage() {
     $default_language = ConfigurableLanguage::load(\Drupal::languageManager()->getDefaultLanguage()->getId());
     // Change the language default object to different values.
-    ConfigurableLanguage::create(array(
-      'id' => 'fr',
-      'label' => 'French',
-      'direction' => Language::DIRECTION_LTR,
-      'weight' => 0,
-      'default' => TRUE,
-    ))->save();
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+    \Drupal::config('system.site')->set('langcode', 'fr')->save();
 
     // The language system creates a Language object which contains the
     // same properties as the new default language object.
@@ -65,8 +60,8 @@ function testDependencyInjectedNewDefaultLanguage() {
     }
 
     // Re-save the previous default language and the delete should work.
-    $default_language->set('default', TRUE);
-    $default_language->save();
+    \Drupal::config('system.site')->set('langcode', $default_language->getId())->save();
+
     entity_delete_multiple('configurable_language', array('fr'));
     $result = \Drupal::languageManager()->getCurrentLanguage();
     $this->assertIdentical($result->id, $default_language->id);
diff --git a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
index 76720e8..4753539 100644
--- a/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
+++ b/core/modules/language/src/Tests/LanguageUILanguageNegotiationTest.php
@@ -89,9 +89,8 @@ function testUILanguageNegotiation() {
     // is for some reason not found when doing translate search. This might
     // be some bug.
     $default_language = \Drupal::languageManager()->getDefaultLanguage();
-    $language = ConfigurableLanguage::createFromLangcode($langcode_browser_fallback);
-    $language->set('default', TRUE);
-    $language->save();
+    ConfigurableLanguage::createFromLangcode($langcode_browser_fallback)->save();
+    \Drupal::config('system.site')->set('langcode', $langcode_browser_fallback)->save();
     ConfigurableLanguage::createFromLangcode($langcode)->save();
 
     // We will look for this string in the admin/config screen to see if the
@@ -104,9 +103,7 @@ function testUILanguageNegotiation() {
     // Now the t()'ed string is in db so switch the language back to default.
     // This will rebuild the container so we need to rebuild the container in
     // the test environment.
-    $default_language = ConfigurableLanguage::load($default_language->getId());
-    $default_language->set('default', TRUE);
-    $default_language->save();
+    \Drupal::config('system.site')->set('langcode', $default_language->getId())->save();
     \Drupal::config('language.negotiation')->set('url.prefixes.en', '')->save();
     $this->rebuildContainer();
 
diff --git a/core/modules/language/src/Tests/LanguageUrlRewritingTest.php b/core/modules/language/src/Tests/LanguageUrlRewritingTest.php
index 4a4658f..deec467 100644
--- a/core/modules/language/src/Tests/LanguageUrlRewritingTest.php
+++ b/core/modules/language/src/Tests/LanguageUrlRewritingTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\language\Tests;
 
-use Drupal\Core\Language\Language;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationUrl;
 use Drupal\simpletest\WebTestBase;
 use Symfony\Component\HttpFoundation\Request;
@@ -52,7 +51,8 @@ protected function setUp() {
    */
   function testUrlRewritingEdgeCases() {
     // Check URL rewriting with a non-installed language.
-    $non_existing = new Language(array('id' => $this->randomMachineName()));
+    $non_existing = \Drupal::languageManager()->getDefaultLanguage();
+    $non_existing->id = $this->randomMachineName();
     $this->checkUrl($non_existing, 'Path language is ignored if language is not installed.', 'URL language negotiation does not work with non-installed languages');
 
     // Check that URL rewriting is not applied to subrequests.
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 11ffc27..3122f59 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -174,6 +174,18 @@ function locale_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function locale_permission() {
+  return array(
+    'translate interface' => array(
+      'title' => t('Translate interface texts'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function locale_theme() {
diff --git a/core/modules/locale/locale.permissions.yml b/core/modules/locale/locale.permissions.yml
deleted file mode 100644
index 8d37e89..0000000
--- a/core/modules/locale/locale.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-translate interface:
-  title: 'Translate interface texts'
-  restrict access: true
diff --git a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
index 07f6f48..96f5a26 100644
--- a/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
+++ b/core/modules/locale/src/Tests/LocaleLocaleLookupTest.php
@@ -31,9 +31,9 @@ public function setUp() {
     parent::setUp();
 
     // Change the language default object to different values.
-    $language = ConfigurableLanguage::createFromLangcode('fr');
-    $language->set('default', TRUE);
-    $language->save();
+    ConfigurableLanguage::createFromLangcode('fr')->save();
+    \Drupal::config('system.site')->set('langcode', 'fr')->save();
+
     $this->drupalLogin($this->root_user);
   }
 
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index 148203a..dcedc00 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -54,6 +54,17 @@ function menu_ui_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function menu_ui_permission() {
+  return array(
+    'administer menu' => array(
+      'title' => t('Administer menus and menu items'),
+    ),
+  );
+}
+
+/**
  * Implements hook_entity_type_build().
  */
 function menu_ui_entity_type_build(array &$entity_types) {
diff --git a/core/modules/menu_ui/menu_ui.permissions.yml b/core/modules/menu_ui/menu_ui.permissions.yml
deleted file mode 100644
index 9bc104f..0000000
--- a/core/modules/menu_ui/menu_ui.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer menu:
-  title: 'Administer menus and menu items'
diff --git a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
index f5d32f8..f74fb09 100644
--- a/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuLanguageTest.php
@@ -150,9 +150,7 @@ function testMenuLanguageRemovedEnglish() {
 
     // Remove English language. To do that another language has to be set as
     // default.
-    $language = ConfigurableLanguage::load('cs');
-    $language->set('default', TRUE);
-    $language->save();
+    \Drupal::config('system.site')->set('langcode', 'cs')->save();
     entity_delete_multiple('configurable_language', array('en'));
 
     // Save the menu again and check if the language is still the same.
diff --git a/core/modules/node/node.permissions.yml b/core/modules/node/node.permissions.yml
index 6c7ea02..31a4992 100644
--- a/core/modules/node/node.permissions.yml
+++ b/core/modules/node/node.permissions.yml
@@ -1,17 +1,14 @@
 bypass node access:
   title: 'Bypass content access control'
-  description: 'View, edit and delete all content regardless of permission restrictions.'
-  restrict access: true
+  description: 'View edit and delete all content regardless of permission restrictions.'
+  'restrict access': TRUE
 administer content types:
   title: 'Administer content types'
-  description: 'Promote, change ownership, edit revisions, and perform other tasks across all content types.'
-  restrict access: true
+  description: 'Promote change ownership edit revisions and perform other tasks across all content types.'
+  'restrict access': TRUE
 administer nodes:
   title: 'Administer content'
-  restrict access: true
-access content overview:
-  title: 'Access the Content overview page'
-  description: 'Get an overview of all content.'
+  'restrict access': TRUE
 access content:
   title: 'View published content'
 view own unpublished content:
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module
index d759087..86fdbf1 100644
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.module
+++ b/core/modules/node/tests/modules/node_access_test/node_access_test.module
@@ -45,7 +45,7 @@
  *
  * @see \Drupal\node\Tests\NodeQueryAlterTest::testNodeQueryAlterOverride()
  * @see \Drupal\node\Tests\NodeAccessPagerTest
- * @see node_access_test.permissions.yml
+ * @see node_access_test_permission()
  * @see node_access_test_node_access_records()
  */
 function node_access_test_node_grants($account, $op) {
@@ -73,7 +73,7 @@ function node_access_test_node_grants($account, $op) {
  *
  * @see \Drupal\node\Tests\NodeAccessBaseTableTest::setUp()
  * @see node_access_test_node_grants()
- * @see node_access_test.permissions.yml
+ * @see node_access_test_permission()
  */
 function node_access_test_node_access_records(NodeInterface $node) {
   $grants = array();
@@ -113,6 +113,22 @@ function node_access_test_node_access_records(NodeInterface $node) {
 }
 
 /**
+ * Implements hook_permission().
+ *
+ * Provides a 'node test view' permission. By default, all content is
+ * restricted, and users without this permission can only view content they
+ * have authored. When the 'node_access_test.private' state variable is
+ * TRUE, only 'private' nodes are restricted, and this permission grants access
+ * to view private nodes.
+ *
+ * @see node_access_test_node_access_records()
+ * @see node_access_test_node_grants()
+ */
+function node_access_test_permission() {
+  return array('node test view' => array('title' => 'View content'));
+}
+
+/**
  * Adds the private field to a node type.
  *
  * @param \Drupal\node\NodeTypeInterface $type
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.permissions.yml b/core/modules/node/tests/modules/node_access_test/node_access_test.permissions.yml
deleted file mode 100644
index 5e52fa0..0000000
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-node test view:
-  title: 'View content'
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index ad99d4a..0bf3781 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -39,6 +39,20 @@ function path_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function path_permission() {
+  return array(
+    'administer url aliases' => array(
+      'title' => t('Administer URL aliases'),
+    ),
+    'create url aliases' => array(
+      'title' => t('Create and edit URL aliases'),
+    ),
+  );
+}
+
+/**
  * Implements hook_form_BASE_FORM_ID_alter() for node_form().
  */
 function path_form_node_form_alter(&$form, FormStateInterface $form_state) {
diff --git a/core/modules/path/path.permissions.yml b/core/modules/path/path.permissions.yml
deleted file mode 100644
index c194de4..0000000
--- a/core/modules/path/path.permissions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-administer url aliases:
-  title: 'Administer URL aliases'
-create url aliases:
-  title: 'Create and edit URL aliases'
diff --git a/core/modules/quickedit/quickedit.module b/core/modules/quickedit/quickedit.module
index 6b5a9cf..f02fe3d 100644
--- a/core/modules/quickedit/quickedit.module
+++ b/core/modules/quickedit/quickedit.module
@@ -35,6 +35,18 @@ function quickedit_help($route_name, RouteMatchInterface $route_match) {
   }
 }
 
+
+/**
+ * Implements hook_permission().
+ */
+function quickedit_permission() {
+  return array(
+    'access in-place editing' => array(
+      'title' => t('Access in-place editing'),
+    ),
+  );
+}
+
 /**
  * Implements hook_page_build().
  *
diff --git a/core/modules/quickedit/quickedit.permissions.yml b/core/modules/quickedit/quickedit.permissions.yml
deleted file mode 100644
index f9ff51c..0000000
--- a/core/modules/quickedit/quickedit.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-access in-place editing:
-  title: 'Access in-place editing'
diff --git a/core/modules/responsive_image/responsive_image.module b/core/modules/responsive_image/responsive_image.module
index 63c732a..d8985c9 100644
--- a/core/modules/responsive_image/responsive_image.module
+++ b/core/modules/responsive_image/responsive_image.module
@@ -41,6 +41,17 @@ function responsive_image_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function responsive_image_permission() {
+  return array(
+    'administer responsive images' => array(
+      'title' => t('Administer responsive images'),
+    ),
+  );
+}
+
+/**
  * Implements hook_menu().
  */
 function responsive_image_menu() {
diff --git a/core/modules/responsive_image/responsive_image.permissions.yml b/core/modules/responsive_image/responsive_image.permissions.yml
deleted file mode 100644
index ad54cc8..0000000
--- a/core/modules/responsive_image/responsive_image.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-administer responsive images:
-  title: 'Administer responsive images'
diff --git a/core/modules/rest/rest.module b/core/modules/rest/rest.module
index 1b24f80..c0c6be3 100644
--- a/core/modules/rest/rest.module
+++ b/core/modules/rest/rest.module
@@ -8,6 +8,22 @@
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
+ * Implements hook_permission().
+ */
+function rest_permission() {
+  $permissions = array();
+  $manager = \Drupal::service('plugin.manager.rest');
+  $resources = \Drupal::config('rest.settings')->get('resources');
+  if ($resources && $enabled = array_intersect_key($manager->getDefinitions(), $resources)) {
+    foreach ($enabled as $key => $resource) {
+      $plugin = $manager->getInstance(array('id' => $key));
+      $permissions = array_merge($permissions, $plugin->permissions());
+    }
+  }
+  return $permissions;
+}
+
+/**
  * Implements hook_help().
  */
 function rest_help($route_name, RouteMatchInterface $route_match) {
diff --git a/core/modules/rest/rest.permissions.yml b/core/modules/rest/rest.permissions.yml
deleted file mode 100644
index 2ab7154..0000000
--- a/core/modules/rest/rest.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-permission_callbacks:
-  - Drupal\rest\RestPermissions::permissions
diff --git a/core/modules/rest/src/Plugin/ResourceInterface.php b/core/modules/rest/src/Plugin/ResourceInterface.php
index 2aef832..11e2cd9 100644
--- a/core/modules/rest/src/Plugin/ResourceInterface.php
+++ b/core/modules/rest/src/Plugin/ResourceInterface.php
@@ -33,7 +33,7 @@
   public function routes();
 
   /**
-   * Provides an array of permissions suitable for .permissions.yml files.
+   * Provides an array of permissions suitable for hook_permission().
    *
    * A resource plugin can define a set of user permissions that are used on the
    * routes for this resource or for other purposes.
diff --git a/core/modules/rest/src/RestPermissions.php b/core/modules/rest/src/RestPermissions.php
deleted file mode 100644
index 652ae1d..0000000
--- a/core/modules/rest/src/RestPermissions.php
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\rest\RestPermissions.
- */
-
-namespace Drupal\rest;
-
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\rest\Plugin\Type\ResourcePluginManager;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides rest module permissions.
- */
-class RestPermissions implements ContainerInjectionInterface {
-
-  /**
-   * The rest resource plugin manager.
-   *
-   * @var \Drupal\rest\Plugin\Type\ResourcePluginManager
-   */
-  protected $restPluginManager;
-
-  /**
-   * The config factory.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
-
-  /**
-   * Constructs a new RestPermissions instance.
-   *
-   * @param \Drupal\rest\Plugin\Type\ResourcePluginManager $rest_plugin_manager
-   *   The rest resource plugin manager.
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory.
-   */
-  public function __construct(ResourcePluginManager $rest_plugin_manager, ConfigFactoryInterface $config_factory) {
-    $this->restPluginManager = $rest_plugin_manager;
-    $this->configFactory = $config_factory;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static($container->get('plugin.manager.rest'), $container->get('config.factory'));
-  }
-
-  /**
-   * Returns an array of REST permissions.
-   *
-   * @return array
-   */
-  public function permissions() {
-    $permissions = [];
-    $resources = $this->configFactory->get('rest.settings')->get('resources');
-    if ($resources && $enabled = array_intersect_key($this->restPluginManager->getDefinitions(), $resources)) {
-      foreach ($enabled as $key => $resource) {
-        $plugin = $this->restPluginManager->getInstance(['id' => $key]);
-        $permissions = array_merge($permissions, $plugin->permissions());
-      }
-    }
-    return $permissions;
-  }
-
-}
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index eef49c5..7cbe706 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -110,6 +110,23 @@ function search_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function search_permission() {
+  return array(
+    'administer search' => array(
+      'title' => t('Administer search'),
+    ),
+    'search content' => array(
+      'title' => t('Use search'),
+    ),
+    'use advanced search' => array(
+      'title' => t('Use advanced search'),
+    ),
+  );
+}
+
+/**
  * Implements hook_preprocess_HOOK() for block templates.
  */
 function search_preprocess_block(&$variables) {
diff --git a/core/modules/search/search.permissions.yml b/core/modules/search/search.permissions.yml
deleted file mode 100644
index 346d848..0000000
--- a/core/modules/search/search.permissions.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-administer search:
-  title: 'Administer search'
-search content:
-  title: 'Use search'
-use advanced search:
-  title: 'Use advanced search'
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 61fc895..4954887 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -46,6 +46,28 @@ function shortcut_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function shortcut_permission() {
+  return array(
+    'administer shortcuts' => array(
+      'title' => t('Administer shortcuts'),
+    ),
+    'customize shortcut links' => array(
+      'title' => t('Edit current shortcut set'),
+      'description' => t('Editing the current shortcut set will affect other users if that set has been assigned to or selected by other users. Granting "Select any shortcut set" permission along with this permission will grant permission to edit any shortcut set.'),
+    ),
+    'switch shortcut sets' => array(
+      'title' => t('Select any shortcut set'),
+      'description' => t('From all shortcut sets, select one to be own active set. Without this permission, an administrator selects shortcut sets for users.'),
+    ),
+    'access shortcuts' => array(
+      'title' => t('Use shortcuts'),
+    ),
+  );
+}
+
+/**
  * Access callback for editing a shortcut set.
  *
  * @param Drupal\shortcut\ShortcutSetInterface $shortcut_set
diff --git a/core/modules/shortcut/shortcut.permissions.yml b/core/modules/shortcut/shortcut.permissions.yml
deleted file mode 100644
index 3ee20cf..0000000
--- a/core/modules/shortcut/shortcut.permissions.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-administer shortcuts:
-  title: 'Administer shortcuts'
-customize shortcut links:
-  title: 'Edit current shortcut set'
-  description: 'Editing the current shortcut set will affect other users if that set has been assigned to or selected by other users. Granting "Select any shortcut set" permission along with this permission will grant permission to edit any shortcut set.'
-switch shortcut sets:
-  title: 'Select any shortcut set'
-  description: 'From all shortcut sets, select one to be own active set. Without this permission, an administrator selects shortcut sets for users.'
-access shortcuts:
-  title: 'Use shortcuts'
diff --git a/core/modules/simpletest/simpletest.module b/core/modules/simpletest/simpletest.module
index d45bd36..24665c7 100644
--- a/core/modules/simpletest/simpletest.module
+++ b/core/modules/simpletest/simpletest.module
@@ -38,6 +38,18 @@ function simpletest_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function simpletest_permission() {
+  return array(
+    'administer unit tests' => array(
+      'title' => t('Administer tests'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function simpletest_theme() {
diff --git a/core/modules/simpletest/simpletest.permissions.yml b/core/modules/simpletest/simpletest.permissions.yml
deleted file mode 100644
index a23e8c8..0000000
--- a/core/modules/simpletest/simpletest.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-administer unit tests:
-  title: 'Administer tests'
-  restrict access: true
diff --git a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
index 73cee71..3a6434b 100644
--- a/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
+++ b/core/modules/simpletest/src/Tests/KernelTestBaseTest.php
@@ -40,11 +40,10 @@ function testSetUp() {
     $table = 'entity_test';
 
     // Verify that specified $modules have been loaded.
-    $this->assertTrue(function_exists('entity_test_entity_bundle_info'), 'entity_test.module was loaded.');
+    $this->assertTrue(function_exists('entity_test_permission'), 'entity_test.module was loaded.');
     // Verify that there is a fixed module list.
     $this->assertIdentical(array_keys(\Drupal::moduleHandler()->getModuleList()), $modules);
-    $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('entity_bundle_info'), ['entity_test']);
-    $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('entity_type_alter'), ['entity_test']);
+    $this->assertIdentical(\Drupal::moduleHandler()->getImplementations('permission'), $modules);
 
     // Verify that no modules have been installed.
     $this->assertFalse(db_table_exists($table), "'$table' database table not found.");
@@ -60,8 +59,8 @@ function testEnableModulesLoad() {
     $this->assertFalse(\Drupal::moduleHandler()->moduleExists($module), "$module module not found.");
     $list = array_keys(\Drupal::moduleHandler()->getModuleList());
     $this->assertFalse(in_array($module, $list), "$module module not found in the extension handler's module list.");
-    $list = \Drupal::moduleHandler()->getImplementations('entity_display_build_alter');
-    $this->assertFalse(in_array($module, $list), "{$module}_entity_display_build_alter() in \Drupal::moduleHandler()->getImplementations() not found.");
+    $list = \Drupal::moduleHandler()->getImplementations('permission');
+    $this->assertFalse(in_array($module, $list), "{$module}_permission() in \Drupal::moduleHandler()->getImplementations() not found.");
 
     // Enable the module.
     $this->enableModules(array($module));
@@ -70,8 +69,8 @@ function testEnableModulesLoad() {
     $this->assertTrue(\Drupal::moduleHandler()->moduleExists($module), "$module module found.");
     $list = array_keys(\Drupal::moduleHandler()->getModuleList());
     $this->assertTrue(in_array($module, $list), "$module module found in the extension handler's module list.");
-    $list = \Drupal::moduleHandler()->getImplementations('query_efq_table_prefixing_test_alter');
-    $this->assertTrue(in_array($module, $list), "{$module}_query_efq_table_prefixing_test_alter() in \Drupal::moduleHandler()->getImplementations() found.");
+    $list = \Drupal::moduleHandler()->getImplementations('permission');
+    $this->assertTrue(in_array($module, $list), "{$module}_permission() in \Drupal::moduleHandler()->getImplementations() found.");
   }
 
   /**
@@ -85,8 +84,8 @@ function testEnableModulesInstall() {
     $this->assertFalse(\Drupal::moduleHandler()->moduleExists($module), "$module module not found.");
     $list = array_keys(\Drupal::moduleHandler()->getModuleList());
     $this->assertFalse(in_array($module, $list), "$module module not found in the extension handler's module list.");
-    $list = \Drupal::moduleHandler()->getImplementations('hook_info');
-    $this->assertFalse(in_array($module, $list), "{$module}_hook_info() in \Drupal::moduleHandler()->getImplementations() not found.");
+    $list = \Drupal::moduleHandler()->getImplementations('permission');
+    $this->assertFalse(in_array($module, $list), "{$module}_permission() in \Drupal::moduleHandler()->getImplementations() not found.");
 
     $this->assertFalse(db_table_exists($table), "'$table' database table not found.");
     $schema = drupal_get_schema($table, TRUE);
@@ -99,8 +98,8 @@ function testEnableModulesInstall() {
     $this->assertTrue(\Drupal::moduleHandler()->moduleExists($module), "$module module found.");
     $list = array_keys(\Drupal::moduleHandler()->getModuleList());
     $this->assertTrue(in_array($module, $list), "$module module found in the extension handler's module list.");
-    $list = \Drupal::moduleHandler()->getImplementations('hook_info');
-    $this->assertTrue(in_array($module, $list), "{$module}_hook_info() in \Drupal::moduleHandler()->getImplementations() found.");
+    $list = \Drupal::moduleHandler()->getImplementations('permission');
+    $this->assertTrue(in_array($module, $list), "{$module}_permission() in \Drupal::moduleHandler()->getImplementations() found.");
 
     $this->assertTrue(db_table_exists($table), "'$table' database table found.");
     $schema = drupal_get_schema($table);
diff --git a/core/modules/statistics/statistics.module b/core/modules/statistics/statistics.module
index 7e4927b..bb52373 100644
--- a/core/modules/statistics/statistics.module
+++ b/core/modules/statistics/statistics.module
@@ -34,6 +34,20 @@ function statistics_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function statistics_permission() {
+  return array(
+    'administer statistics' => array(
+      'title' => t('Administer statistics'),
+    ),
+    'view post access counter' => array(
+      'title' => t('View content hits'),
+    ),
+  );
+}
+
+/**
  * Implements hook_ENTITY_TYPE_view() for node entities.
  */
 function statistics_node_view(array &$build, EntityInterface $node, EntityViewDisplayInterface $display, $view_mode) {
diff --git a/core/modules/statistics/statistics.permissions.yml b/core/modules/statistics/statistics.permissions.yml
deleted file mode 100644
index b414c22..0000000
--- a/core/modules/statistics/statistics.permissions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-administer statistics:
-  title: 'Administer statistics'
-view post access counter:
-  title: 'View content hits'
diff --git a/core/modules/system/core.api.php b/core/modules/system/core.api.php
index 8852c31..d695403 100644
--- a/core/modules/system/core.api.php
+++ b/core/modules/system/core.api.php
@@ -551,11 +551,10 @@
  * appropriately for their particular sites.
  *
  * @section sec_define Defining permissions
- * Modules define permissions via a $module.permissions.yml file or by
- * implementing hook_permission(). The return value defines machine names,
- * human-readable names, and optionally descriptions for each permission type.
- * The machine names are the canonical way to refer to permissions for access
- * checking.
+ * Modules define permissions by implementing hook_permission(). The return
+ * value defines machine names, human-readable names, and optionally
+ * descriptions for each permission type. The machine names are the canonical
+ * way to refer to permissions for access checking.
  *
  * @section sec_access Access permission checking
  * Depending on the situation, there are several methods for ensuring that
diff --git a/core/modules/system/src/Tests/Common/FormatDateTest.php b/core/modules/system/src/Tests/Common/FormatDateTest.php
index 9c75f29..f8ad3b7 100644
--- a/core/modules/system/src/Tests/Common/FormatDateTest.php
+++ b/core/modules/system/src/Tests/Common/FormatDateTest.php
@@ -96,9 +96,7 @@ function testFormatDate() {
     $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'Europe/London', 'en'), 'Monday, 26-Mar-07 01:00:00 BST', 'Test a different time zone.');
 
     // Change the default language and timezone.
-    $language = ConfigurableLanguage::load(static::LANGCODE);
-    $language->set('default', TRUE);
-    $language->save();
+    \Drupal::config('system.site')->set('langcode', static::LANGCODE)->save();
     date_default_timezone_set('America/Los_Angeles');
 
     $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'America/Los_Angeles', 'en'), 'Sunday, 25-Mar-07 17:00:00 PDT', 'Test a different language.');
diff --git a/core/modules/system/src/Tests/Module/ModuleImplementsAlterTest.php b/core/modules/system/src/Tests/Module/ModuleImplementsAlterTest.php
index 8d5d229..319e3be 100644
--- a/core/modules/system/src/Tests/Module/ModuleImplementsAlterTest.php
+++ b/core/modules/system/src/Tests/Module/ModuleImplementsAlterTest.php
@@ -39,14 +39,14 @@ function testModuleImplementsAlter() {
       'The \Drupal::moduleHandler() instance has been replaced during \Drupal::moduleHandler()->install().');
 
     // Assert that module_test.module is now included.
-    $this->assertTrue(function_exists('module_test_modules_installed'),
+    $this->assertTrue(function_exists('module_test_permission'),
       'The file module_test.module was successfully included.');
 
     $this->assertTrue(array_key_exists('module_test', \Drupal::moduleHandler()->getModuleList()),
       'module_test is in the module list.');
 
-    $this->assertTrue(in_array('module_test', \Drupal::moduleHandler()->getImplementations('modules_installed')),
-      'module_test implements hook_modules_installed().');
+    $this->assertTrue(in_array('module_test', \Drupal::moduleHandler()->getImplementations('permission')),
+      'module_test implements hook_permission().');
 
     $this->assertTrue(in_array('module_test', \Drupal::moduleHandler()->getImplementations('module_implements_alter')),
       'module_test implements hook_module_implements_alter().');
diff --git a/core/modules/system/src/Tests/Theme/TwigTransTest.php b/core/modules/system/src/Tests/Theme/TwigTransTest.php
index 98a6e9f..7825259 100644
--- a/core/modules/system/src/Tests/Theme/TwigTransTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigTransTest.php
@@ -70,9 +70,7 @@ protected function setUp() {
     $this->installLanguages();
 
     // Assign Lolspeak (xx) to be the default language.
-    $language = ConfigurableLanguage::load('xx');
-    $language->set('default', TRUE);
-    $language->save();
+    \Drupal::config('system.site')->set('langcode', 'xx')->save();
     $this->rebuildContainer();
 
     // Check that lolspeak is the default language for the site.
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 71297db..c2f590f 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -979,8 +979,6 @@ function hook_system_info_alter(array &$info, \Drupal\Core\Extension\Extension $
  *     is specific to the permission you are defining.
  *
  * @ingroup user_api
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- *   Use $module.permissions.yml files.
  */
 function hook_permission() {
   return array(
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 6ca3699..f3b65a2 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -217,6 +217,47 @@ function system_theme() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function system_permission() {
+  return array(
+    'administer modules' => array(
+      'title' => t('Administer modules'),
+    ),
+    'administer site configuration' => array(
+      'title' => t('Administer site configuration'),
+      'restrict access' => TRUE,
+    ),
+    'administer themes' => array(
+      'title' => t('Administer themes'),
+    ),
+    'administer software updates' => array(
+      'title' => t('Administer software updates'),
+      'restrict access' => TRUE,
+    ),
+    'access administration pages' => array(
+      'title' => t('Use the administration pages and help'),
+    ),
+    'access site in maintenance mode' => array(
+      'title' => t('Use the site in maintenance mode'),
+    ),
+    'view the administration theme' => array(
+      'title' => t('View the administration theme'),
+      'description' => t('This is only used when the site is configured to use a separate administration theme on the <a href="@appearance-url">Appearance</a> page.', array('@appearance-url' => url('admin/appearance'))),
+    ),
+    'access site reports' => array(
+      'title' => t('View site reports'),
+      'restrict access' => TRUE,
+    ),
+    'link to any page' => [
+      'title' => t('Link to any page'),
+      'description' => t('This allows to bypass access checking when linking to internal paths.'),
+      'restrict access' => TRUE,
+    ],
+  );
+}
+
+/**
  * Implements hook_hook_info().
  */
 function system_hook_info() {
@@ -1077,10 +1118,7 @@ function system_get_module_admin_tasks($module, array $info) {
   }
 
   // Append link for permissions.
-  /** @var \Drupal\user\PermissionHandlerInterface $permission_handler */
-  $permission_handler = \Drupal::service('user.permissions');
-
-  if ($permission_handler->moduleProvidesPermissions($module)) {
+  if (\Drupal::moduleHandler()->implementsHook($module, 'permission')) {
     /** @var \Drupal\Core\Access\AccessManagerInterface $access_manager */
     $access_manager = \Drupal::service('access_manager');
     if ($access_manager->checkNamedRoute('user.admin_permissions', array(), \Drupal::currentUser())) {
diff --git a/core/modules/system/system.permissions.yml b/core/modules/system/system.permissions.yml
deleted file mode 100644
index 44bb5ef..0000000
--- a/core/modules/system/system.permissions.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-administer modules:
-  title: 'Administer modules'
-administer site configuration:
-  title: 'Administer site configuration'
-  restrict access: true
-administer themes:
-  title: 'Administer themes'
-administer software updates:
-  title: 'Administer software updates'
-  restrict access: true
-access administration pages:
-  title: 'Use the administration pages and help'
-access site in maintenance mode:
-  title: 'Use the site in maintenance mode'
-view the administration theme:
-  title: 'View the administration theme'
-  description: 'This is only used when the site is configured to use a separate administration theme on the Appearance page.'
-access site reports:
-  title: 'View site reports'
-  restrict access: true
-link to any page:
-  title: 'Link to any page'
-  restrict access: true
-  description: 'This allows to bypass access checking when linking to internal paths.'
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module
index 63e289a..835b9d5 100644
--- a/core/modules/system/tests/modules/entity_test/entity_test.module
+++ b/core/modules/system/tests/modules/entity_test/entity_test.module
@@ -234,6 +234,25 @@ function entity_test_entity_extra_field_info() {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function entity_test_permission() {
+  $permissions = array(
+    'administer entity_test content' => array(
+      'title' => t('Administer entity_test content'),
+      'description' => t('Manage entity_test content'),
+    ),
+    'view test entity' => array(
+      'title' => t('View test entities'),
+    ),
+    'view test entity translations' => array(
+      'title' => t('View translations of test entities'),
+    ),
+  );
+  return $permissions;
+}
+
+/**
  * Implements hook_form_BASE_FORM_ID_alter().
  */
 function entity_test_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
diff --git a/core/modules/system/tests/modules/entity_test/entity_test.permissions.yml b/core/modules/system/tests/modules/entity_test/entity_test.permissions.yml
deleted file mode 100644
index e6b705e..0000000
--- a/core/modules/system/tests/modules/entity_test/entity_test.permissions.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-administer entity_test content:
-  title: 'Administer entity_test content'
-  description: 'Manage entity_test content'
-view test entity:
-  title: 'View test entities'
-view test entity translations:
-  title: 'View translations of test entities'
diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module
index d297945..380241b 100644
--- a/core/modules/system/tests/modules/form_test/form_test.module
+++ b/core/modules/system/tests/modules/form_test/form_test.module
@@ -8,6 +8,21 @@
 use Drupal\Core\Form\FormStateInterface;
 
 /**
+ * Implements hook_permission().
+ */
+function form_test_permission() {
+  $perms = array(
+    'access vertical_tab_test tabs' => array(
+      'title' => t('Access vertical_tab_test tabs'),
+    ),
+    'access autocomplete test' => array(
+      'title' => t('Access autocomplete test'),
+    ),
+  );
+  return $perms;
+}
+
+/**
  * Implements hook_form_FORM_ID_alter() on behalf of block.module.
  */
 function block_form_form_test_alter_form_alter(&$form, FormStateInterface $form_state) {
diff --git a/core/modules/system/tests/modules/form_test/form_test.permissions.yml b/core/modules/system/tests/modules/form_test/form_test.permissions.yml
deleted file mode 100644
index f90e15e..0000000
--- a/core/modules/system/tests/modules/form_test/form_test.permissions.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-access vertical_tab_test tabs:
-  title: 'Access vertical_tab_test tabs'
-access autocomplete test:
-  title: 'Access autocomplete test'
diff --git a/core/modules/system/tests/modules/module_test/module_test.module b/core/modules/system/tests/modules/module_test/module_test.module
index 60d53ef..522bab2 100644
--- a/core/modules/system/tests/modules/module_test/module_test.module
+++ b/core/modules/system/tests/modules/module_test/module_test.module
@@ -3,6 +3,15 @@
 use Drupal\Core\Extension\Extension;
 
 /**
+ * Implements hook_permission().
+ */
+function module_test_permission() {
+  return array(
+    'module_test perm' => t('example perm for module_test module'),
+  );
+}
+
+/**
  * Implements hook_system_info_alter().
  *
  * Manipulate module dependencies to test dependency chains.
diff --git a/core/modules/system/tests/modules/module_test/module_test.permissions.yml b/core/modules/system/tests/modules/module_test/module_test.permissions.yml
deleted file mode 100644
index d5f5869..0000000
--- a/core/modules/system/tests/modules/module_test/module_test.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-module_test perm:
-   title: 'example perm for module_test module'
diff --git a/core/modules/system/tests/modules/router_test_directory/router_test.module b/core/modules/system/tests/modules/router_test_directory/router_test.module
new file mode 100644
index 0000000..ffbe070
--- /dev/null
+++ b/core/modules/system/tests/modules/router_test_directory/router_test.module
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * Implements hook_permission().
+ */
+function router_test_permission() {
+  return array(
+    'access test7' =>  array(
+      'title' => t('Access test7 route'),
+      'description' => t('Test permission only.'),
+    ),
+  );
+}
diff --git a/core/modules/system/tests/modules/router_test_directory/router_test.permissions.yml b/core/modules/system/tests/modules/router_test_directory/router_test.permissions.yml
deleted file mode 100644
index 0c61967..0000000
--- a/core/modules/system/tests/modules/router_test_directory/router_test.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-access test7:
-  title: 'Access test7 route'
-  description: 'Test permission only.'
diff --git a/core/modules/taxonomy/src/TaxonomyPermissions.php b/core/modules/taxonomy/src/TaxonomyPermissions.php
deleted file mode 100644
index 8179919..0000000
--- a/core/modules/taxonomy/src/TaxonomyPermissions.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\taxonomy\TaxonomyPermissions.
- */
-
-namespace Drupal\taxonomy;
-
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-/**
- * Provides dynamic permissions of the taxonomy module.
- */
-class TaxonomyPermissions implements ContainerInjectionInterface {
-
-  use StringTranslationTrait;
-
-  /**
-   * The entity manager.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a TaxonomyPermissions instance.
-   *
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   */
-  public function __construct(EntityManagerInterface $entity_manager) {
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static($container->get('entity.manager'));
-  }
-
-  /**
-   * Returns an array of REST permissions.
-   *
-   * @return array
-   */
-  public function permissions() {
-    $permissions = [];
-    foreach ($this->entityManager->getStorage('taxonomy_vocabulary')->loadMultiple() as $vocabulary) {
-      $permissions += [
-        'edit terms in ' . $vocabulary->id() => [
-          'title' => $this->t('Edit terms in %vocabulary', ['%vocabulary' => $vocabulary->name]),
-        ],
-      ];
-      $permissions += [
-        'delete terms in ' . $vocabulary->id() => [
-          'title' => $this->t('Delete terms from %vocabulary', ['%vocabulary' => $vocabulary->name]),
-        ],
-      ];
-    }
-    return $permissions;
-  }
-
-}
diff --git a/core/modules/taxonomy/src/Tests/TermLanguageTest.php b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
index be67e5d..cb64143 100644
--- a/core/modules/taxonomy/src/Tests/TermLanguageTest.php
+++ b/core/modules/taxonomy/src/Tests/TermLanguageTest.php
@@ -95,9 +95,7 @@ function testDefaultTermLanguage() {
 
     // Change the default language of the site and check if the default terms
     // language is still correctly selected.
-    $new_default = ConfigurableLanguage::load('cc');
-    $new_default->set('default', TRUE);
-    $new_default->save();
+    \Drupal::config('system.site')->set('langcode', 'cc')->save();
     $edit = array(
       'default_language[langcode]' => 'site_default',
       'default_language[language_show]' => TRUE,
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 290bbec..7b26e7b 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -94,6 +94,30 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function taxonomy_permission() {
+  $permissions = array(
+    'administer taxonomy' => array(
+      'title' => t('Administer vocabularies and terms'),
+    ),
+  );
+  foreach (entity_load_multiple('taxonomy_vocabulary') as $vocabulary) {
+    $permissions += array(
+      'edit terms in ' . $vocabulary->id() => array(
+        'title' => t('Edit terms in %vocabulary', array('%vocabulary' => $vocabulary->name)),
+      ),
+    );
+    $permissions += array(
+       'delete terms in ' . $vocabulary->id() => array(
+         'title' => t('Delete terms from %vocabulary', array('%vocabulary' => $vocabulary->name)),
+      ),
+    );
+  }
+  return $permissions;
+}
+
+/**
  * Entity URI callback.
  */
 function taxonomy_term_uri($term) {
diff --git a/core/modules/taxonomy/taxonomy.permissions.yml b/core/modules/taxonomy/taxonomy.permissions.yml
deleted file mode 100644
index d485949..0000000
--- a/core/modules/taxonomy/taxonomy.permissions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-administer taxonomy:
-  title: 'Administer vocabularies and terms'
-
-permission_callbacks:
-  - Drupal\taxonomy\TaxonomyPermissions::permissions
diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module
index 07deb3c..49e2530 100644
--- a/core/modules/toolbar/toolbar.module
+++ b/core/modules/toolbar/toolbar.module
@@ -34,6 +34,17 @@ function toolbar_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function toolbar_permission() {
+  return array(
+    'access toolbar' => array(
+      'title' => t('Use the administration toolbar'),
+    ),
+  );
+}
+
+/**
  * Implements hook_theme().
  */
 function toolbar_theme($existing, $type, $theme, $path) {
diff --git a/core/modules/toolbar/toolbar.permissions.yml b/core/modules/toolbar/toolbar.permissions.yml
deleted file mode 100644
index 54e73fb..0000000
--- a/core/modules/toolbar/toolbar.permissions.yml
+++ /dev/null
@@ -1,2 +0,0 @@
-access toolbar:
-  title: 'Use the administration toolbar'
diff --git a/core/modules/tour/tour.module b/core/modules/tour/tour.module
index dc1e3e9..2738d0c 100644
--- a/core/modules/tour/tour.module
+++ b/core/modules/tour/tour.module
@@ -29,6 +29,18 @@ function tour_help($route_name, RouteMatchInterface $route_match) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function tour_permission() {
+  return array(
+    'access tour' => array(
+      'title' => t('Access tour'),
+      'description' => t('View tour tips.'),
+    ),
+  );
+}
+
+/**
  * Implements hook_toolbar().
  */
 function tour_toolbar() {
diff --git a/core/modules/tour/tour.permissions.yml b/core/modules/tour/tour.permissions.yml
deleted file mode 100644
index fa14b8a..0000000
--- a/core/modules/tour/tour.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-access tour:
-  title: 'Access tour'
-  description: 'View tour tips.'
diff --git a/core/modules/user/src/Access/PermissionAccessCheck.php b/core/modules/user/src/Access/PermissionAccessCheck.php
index 6d10101..15752de 100644
--- a/core/modules/user/src/Access/PermissionAccessCheck.php
+++ b/core/modules/user/src/Access/PermissionAccessCheck.php
@@ -13,7 +13,7 @@
 use Symfony\Component\Routing\Route;
 
 /**
- * Determines access to routes based on permissions defined via permissions.yml.
+ * Determines access to routes based on permissions defined via hook_permission().
  */
 class PermissionAccessCheck implements AccessInterface {
 
diff --git a/core/modules/user/src/PermissionHandler.php b/core/modules/user/src/PermissionHandler.php
index 36a6757..1cbe222 100644
--- a/core/modules/user/src/PermissionHandler.php
+++ b/core/modules/user/src/PermissionHandler.php
@@ -95,22 +95,6 @@ public function getPermissions() {
   }
 
   /**
-   * {@inheritdoc}
-   */
-  public function moduleProvidesPermissions($module_name) {
-    // @TODO Static cache this information, see
-    // https://www.drupal.org/node/2339487
-    $permissions = $this->getPermissions();
-
-    foreach ($permissions as $permission) {
-      if ($permission['provider'] == $module_name) {
-        return TRUE;
-      }
-    }
-    return FALSE;
-  }
-
-  /**
    * Builds all permissions provided by .permissions.yml files.
    *
    * @return array[]
diff --git a/core/modules/user/src/PermissionHandlerInterface.php b/core/modules/user/src/PermissionHandlerInterface.php
index 269af11..5259245 100644
--- a/core/modules/user/src/PermissionHandlerInterface.php
+++ b/core/modules/user/src/PermissionHandlerInterface.php
@@ -43,16 +43,5 @@
    */
   public function getPermissions();
 
-  /**
-   * Determines whether a module provides some permissions.
-   *
-   * @param string $module_name
-   *   The module name.
-   *
-   * @return bool
-   *   Returns TRUE if the module provides some permissions, otherwise FALSE.
-   */
-  public function moduleProvidesPermissions($module_name);
-
 }
 
diff --git a/core/modules/user/src/Plugin/views/access/Permission.php b/core/modules/user/src/Plugin/views/access/Permission.php
index b526e07..490ff26 100644
--- a/core/modules/user/src/Plugin/views/access/Permission.php
+++ b/core/modules/user/src/Plugin/views/access/Permission.php
@@ -7,12 +7,9 @@
 
 namespace Drupal\user\Plugin\views\access;
 
-use Drupal\Component\Utility\String;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Session\AccountInterface;
-use Drupal\user\PermissionHandlerInterface;
 use Drupal\views\Plugin\views\access\AccessPluginBase;
-use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Routing\Route;
 
 /**
@@ -34,41 +31,6 @@ class Permission extends AccessPluginBase {
   protected $usesOptions = TRUE;
 
   /**
-   * The permission handler.
-   *
-   * @var \Drupal\user\PermissionHandlerInterface
-   */
-  protected $permissionHandler;
-
-  /**
-   * Constructs a Permission object.
-   *
-   * @param array $configuration
-   *   A configuration array containing information about the plugin instance.
-   * @param string $plugin_id
-   *   The plugin_id for the plugin instance.
-   * @param mixed $plugin_definition
-   *   The plugin implementation definition.
-   * @param \Drupal\user\PermissionHandlerInterface $permission_handler
-   *   The permission handler.
-   */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, PermissionHandlerInterface $permission_handler) {
-    $this->permissionHandler = $permission_handler;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('user.permissions')
-    );
-  }
-
-  /**
    * {@inheritdoc}
    */
   public function access(AccountInterface $account) {
@@ -83,7 +45,7 @@ public function alterRouteDefinition(Route $route) {
   }
 
   public function summaryTitle() {
-    $permissions = $this->permissionHandler->getPermissions();
+    $permissions = \Drupal::service('user.permissions')->getPermissions();
     if (isset($permissions[$this->options['perm']])) {
       return $permissions[$this->options['perm']]['title'];
     }
@@ -101,17 +63,19 @@ protected function defineOptions() {
 
   public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     parent::buildOptionsForm($form, $form_state);
+    $perms = array();
     $module_info = system_get_info('module');
 
     // Get list of permissions
-    $perms = [];
-    $permissions = $this->permissionHandler->getPermissions();
-    foreach ($permissions as $perm => $perm_item) {
-      $provider = $perm_item['provider'];
-      $display_name = $module_info[$provider]['name'];
-      $perms[$display_name][$perm] = String::checkPlain(strip_tags($perm_item['title']));
+    foreach (\Drupal::moduleHandler()->getImplementations('permission') as $module) {
+      $permissions = \Drupal::moduleHandler()->invoke($module, 'permission');
+      foreach ($permissions as $name => $perm) {
+        $perms[$module_info[$module]['name']][$name] = strip_tags($perm['title']);
+      }
     }
 
+    ksort($perms);
+
     $form['perm'] = array(
       '#type' => 'select',
       '#options' => $perms,
diff --git a/core/modules/user/src/Plugin/views/filter/Permissions.php b/core/modules/user/src/Plugin/views/filter/Permissions.php
index d3e7b50..c0a651d 100644
--- a/core/modules/user/src/Plugin/views/filter/Permissions.php
+++ b/core/modules/user/src/Plugin/views/filter/Permissions.php
@@ -9,7 +9,6 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\user\PermissionHandlerInterface;
 use Drupal\views\Plugin\views\filter\ManyToOne;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -23,11 +22,11 @@
 class Permissions extends ManyToOne {
 
   /**
-   * The permission handler.
+   * The module handler.
    *
-   * @var \Drupal\user\PermissionHandlerInterface
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
    */
-  protected $permissionHandler;
+  protected $moduleHandler;
 
   /**
    * Constructs a Permissions object.
@@ -38,36 +37,41 @@ class Permissions extends ManyToOne {
    *   The plugin_id for the plugin instance.
    * @param mixed $plugin_definition
    *   The plugin implementation definition.
-   * @param \Drupal\user\PermissionHandlerInterface $permission_handler
-   *   The permission handler.
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
+   *   The module handler.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, PermissionHandlerInterface $permission_handler) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, ModuleHandlerInterface $module_handler) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
-    $this->permissionHandler = $permission_handler;
+    $this->moduleHandler = $module_handler;
   }
 
   /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static(
-      $configuration,
-      $plugin_id,
-      $plugin_definition,
-      $container->get('user.permissions')
-    );
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('module_handler'));
   }
 
   public function getValueOptions() {
     if (!isset($this->value_options)) {
       $module_info = system_get_info('module');
 
-      $permissions = $this->permissionHandler->getPermissions();
-      foreach ($permissions as $perm => $perm_item) {
-        $provider = $perm_item['provider'];
-        $display_name = $module_info[$provider]['name'];
-        $this->value_options[$display_name][$perm] = String::checkPlain(strip_tags($perm_item['title']));
+      // Get a list of all the modules implementing a hook_permission() and sort by
+      // display name.
+      $modules = array();
+      foreach ($this->moduleHandler->getImplementations('permission') as $module) {
+        $modules[$module] = $module_info[$module]['name'];
+      }
+      asort($modules);
+
+      $this->value_options = array();
+      foreach ($modules as $module => $display_name) {
+        if ($permissions = $this->moduleHandler->invoke($module, 'permission')) {
+          foreach ($permissions as $perm => $perm_item) {
+            $this->value_options[$display_name][$perm] = String::checkPlain(strip_tags($perm_item['title']));
+          }
+        }
       }
     }
     else {
diff --git a/core/modules/user/src/Tests/Views/HandlerFilterPermissionTest.php b/core/modules/user/src/Tests/Views/HandlerFilterPermissionTest.php
index 49af462..16db903 100644
--- a/core/modules/user/src/Tests/Views/HandlerFilterPermissionTest.php
+++ b/core/modules/user/src/Tests/Views/HandlerFilterPermissionTest.php
@@ -79,16 +79,10 @@ public function testFilterPermission() {
 
     // Test the value options.
     $value_options = $view->filter['permission']->getValueOptions();
-
-    $permisssion_by_module = [];
-    $permissions = \Drupal::service('user.permissions')->getPermissions();
-    foreach ($permissions as $name => $permission) {
-      $permisssion_by_module[$permission['provider']][$name] = $permission;
-    }
     foreach (array('system' => 'System', 'user' => 'User') as $module => $title) {
       $expected = array_map(function ($permission) {
         return String::checkPlain(strip_tags($permission['title']));
-      }, $permisssion_by_module[$module]);
+      }, $this->container->get('module_handler')->invoke($module, 'permission'));
 
       $this->assertEqual($expected, $value_options[$title], 'Ensure the all permissions are available');
     }
diff --git a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
index 013986d..a25bbce 100644
--- a/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
+++ b/core/modules/user/tests/src/Unit/PermissionHandlerTest.php
@@ -140,7 +140,6 @@ public function testBuildPermissionsModules() {
    * @covers ::getPermissions
    * @covers ::buildPermissions
    * @covers ::buildPermissionsYaml
-   * @covers ::moduleProvidesPermissions
    */
   public function testBuildPermissionsYaml() {
     vfsStreamWrapper::register();
@@ -199,11 +198,6 @@ public function testBuildPermissionsYaml() {
 
     $actual_permissions = $this->permissionHandler->getPermissions();
     $this->assertPermissions($actual_permissions);
-
-    $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_a'));
-    $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_b'));
-    $this->assertTrue($this->permissionHandler->moduleProvidesPermissions('module_c'));
-    $this->assertFalse($this->permissionHandler->moduleProvidesPermissions('module_d'));
   }
 
   /**
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 9e52c20..eb3d5ae 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -434,6 +434,41 @@ function user_is_blocked($name) {
 }
 
 /**
+ * Implements hook_permission().
+ */
+function user_permission() {
+  return array(
+    'administer permissions' =>  array(
+      'title' => t('Administer permissions'),
+      'restrict access' => TRUE,
+    ),
+    'administer account settings' => array(
+      'title' => t('Administer account settings'),
+      'description' => t('Configure site-wide settings and behavior for <a href="@url">user accounts and registration</a>.', array('@url' => url('admin/config/people'))),
+      'restrict access' => TRUE,
+    ),
+    'administer users' => array(
+      'title' => t('Administer users'),
+      'restrict access' => TRUE,
+    ),
+    'access user profiles' => array(
+      'title' => t('View user information'),
+    ),
+    'change own username' => array(
+      'title' => t('Change own username'),
+    ),
+    'cancel account' => array(
+      'title' => t('Cancel own user account'),
+      'description' => t('Note: content may be kept, unpublished, deleted or transferred to the %anonymous-name user depending on the configured <a href="@user-settings-url">user settings</a>.', array('%anonymous-name' => \Drupal::config('user.settings')->get('anonymous'), '@user-settings-url' => url('admin/config/people/accounts'))),
+    ),
+    'select account cancellation method' => array(
+      'title' => t('Select method for cancelling own account'),
+      'restrict access' => TRUE,
+    ),
+  );
+}
+
+/**
  * Implements hook_ENTITY_TYPE_view() for user entities.
  */
 function user_user_view(array &$build, UserInterface $account, EntityViewDisplayInterface $display) {
@@ -1168,6 +1203,23 @@ function user_role_load($rid) {
 }
 
 /**
+ * Determine the modules that permissions belong to.
+ *
+ * @return
+ *   An associative array in the format $permission => $module.
+ */
+function user_permission_get_modules() {
+  $permissions = array();
+  foreach (\Drupal::moduleHandler()->getImplementations('permission') as $module) {
+    $perms = \Drupal::moduleHandler()->invoke($module, 'permission');
+    foreach ($perms as $key => $value) {
+      $permissions[$key] = $module;
+    }
+  }
+  return $permissions;
+}
+
+/**
  * Change permissions for a user role.
  *
  * This function may be used to grant and revoke multiple permissions at once.
@@ -1372,11 +1424,14 @@ function user_modules_installed($modules) {
   // Assign all available permissions to the administrator role.
   $rid = \Drupal::config('user.settings')->get('admin_role');
   if ($rid) {
-    /** @var \Drupal\user\PermissionHandlerInterface $permission_handler */
-    $permission_handler = \Drupal::service('user.permissions');
-    $permissions = $permission_handler->getPermissions();
+    $permissions = array();
+    foreach ($modules as $module) {
+      if ($module_permissions = \Drupal::moduleHandler()->invoke($module, 'permission')) {
+        $permissions = array_merge($permissions, array_keys($module_permissions));
+      }
+    }
     if (!empty($permissions)) {
-      user_role_grant_permissions($rid, array_keys($permissions));
+      user_role_grant_permissions($rid, $permissions);
     }
   }
 }
diff --git a/core/modules/user/user.permissions.yml b/core/modules/user/user.permissions.yml
deleted file mode 100644
index 366ca36..0000000
--- a/core/modules/user/user.permissions.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-administer permissions:
-  title: Administer permissions
-  restrict access: true
-administer account settings:
-  title: 'Administer account settings'
-  description: 'Configure site-wide settings and behavior for user accounts and registration.'
-  restrict access: true
-administer users:
-  title: 'Administer users'
-  restrict access: true
-access user profiles:
-  title: 'View user information'
-change own username:
-  title: 'Change own username'
-select account cancellation method:
-  title: 'Select method for cancelling own account'
-  restrict access: true
-cancel account:
-  title: 'Cancel own user account'
-  description: 'Note: content may be kept, unpublished, deleted or transferred to the anonymous user depending on the configured user settings.'
diff --git a/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php b/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
index 97ed8a7..281539b 100644
--- a/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
+++ b/core/modules/views/src/Tests/Wizard/WizardPluginBaseUnitTest.php
@@ -56,9 +56,8 @@ public function testCreateView() {
     $random_description = $this->randomMachineName();
 
     // Add a new language and mark it as default.
-    $language = ConfigurableLanguage::createFromLangcode('it');
-    $language->set('default', TRUE);
-    $language->save();
+    ConfigurableLanguage::createFromLangcode('it')->save();
+    \Drupal::config('system.site')->set('langcode', 'it')->save();
 
     $form_state->setValues([
       'id' => $random_id,
diff --git a/core/modules/views/tests/modules/views_test_data/views_test_data.module b/core/modules/views/tests/modules/views_test_data/views_test_data.module
index 1af309c..61c7fdb 100644
--- a/core/modules/views/tests/modules/views_test_data/views_test_data.module
+++ b/core/modules/views/tests/modules/views_test_data/views_test_data.module
@@ -8,6 +8,18 @@
 use Drupal\views\ViewExecutable;
 
 /**
+ * Implements hook_permission().
+ */
+function views_test_data_permission() {
+  return array(
+    'views_test_data test permission' => array(
+      'title' => t('Test permission'),
+      'description' => t('views_test_data test permission'),
+    ),
+  );
+}
+
+/**
  * Access callback for the generic handler test.
  *
  * @return bool
diff --git a/core/modules/views/tests/modules/views_test_data/views_test_data.permissions.yml b/core/modules/views/tests/modules/views_test_data/views_test_data.permissions.yml
deleted file mode 100644
index ea742c7..0000000
--- a/core/modules/views/tests/modules/views_test_data/views_test_data.permissions.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-views_test_data test permission:
-  title: 'Test permission'
-  description: 'views_test_data test permission'
diff --git a/core/modules/views/views.permissions.yml b/core/modules/views/views.permissions.yml
index 7eb1a08..db47ea5 100644
--- a/core/modules/views/views.permissions.yml
+++ b/core/modules/views/views.permissions.yml
@@ -1,4 +1,4 @@
-access all views:
+'access all views':
   title: 'Bypass views access control'
   description: 'Bypass access control when accessing views.'
-  restrict access: true
+  'restrict access': TRUE
diff --git a/core/modules/views_ui/views_ui.permissions.yml b/core/modules/views_ui/views_ui.permissions.yml
index fd49722..0881aab 100644
--- a/core/modules/views_ui/views_ui.permissions.yml
+++ b/core/modules/views_ui/views_ui.permissions.yml
@@ -1,4 +1,4 @@
-administer views:
+'administer views':
   title: 'Administer views'
   description: 'Access the views administration pages.'
-  restrict access: true
+  'restrict access': TRUE
diff --git a/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php b/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php
index 75e1fd8..e15cbac 100644
--- a/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php
@@ -49,9 +49,26 @@ public function testGetDirection() {
    * @covers ::isDefault()
    */
   public function testIsDefault() {
-    $language_code = $this->randomMachineName(2);
-    $language = new Language(array('id' => $language_code, 'default' => TRUE));
+    $language_default = $this->getMockBuilder('Drupal\Core\Language\LanguageDefault')->disableOriginalConstructor()->getMock();
+    $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface');
+    $container->expects($this->any())
+      ->method('get')
+      ->with('language.default')
+      ->will($this->returnValue($language_default));
+    \Drupal::setContainer($container);
+
+    $language = new Language(array('id' => $this->randomMachineName(2)));
+    // Set up the LanguageDefault to return different default languages on
+    // consecutive calls.
+    $language_default->expects($this->any())
+      ->method('get')
+      ->willReturnOnConsecutiveCalls(
+        $language,
+        new Language(array('id' => $this->randomMachineName(2)))
+      );
+
     $this->assertTrue($language->isDefault());
+    $this->assertFalse($language->isDefault());
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Path/PathValidatorTest.php b/core/tests/Drupal/Tests/Core/Path/PathValidatorTest.php
index 0722680..fe704e2 100644
--- a/core/tests/Drupal/Tests/Core/Path/PathValidatorTest.php
+++ b/core/tests/Drupal/Tests/Core/Path/PathValidatorTest.php
@@ -246,16 +246,16 @@ public function testIsValidWithNotExistingPath() {
    * Tests the getUrlIfValid() method when there is access.
    */
   public function testGetUrlIfValidWithAccess() {
-    $this->account->expects($this->exactly(2))
+    $this->account->expects($this->once())
       ->method('hasPermission')
       ->with('link to any page')
       ->willReturn(FALSE);
 
-    $this->accessAwareRouter->expects($this->exactly(2))
+    $this->accessAwareRouter->expects($this->once())
       ->method('match')
       ->with('/test-path')
       ->willReturn([RouteObjectInterface::ROUTE_NAME => 'test_route', '_raw_variables' => new ParameterBag(['key' => 'value'])]);
-    $this->pathProcessor->expects($this->exactly(2))
+    $this->pathProcessor->expects($this->once())
       ->method('processInbound')
       ->willReturnArgument(0);
 
@@ -264,13 +264,6 @@ public function testGetUrlIfValidWithAccess() {
 
     $this->assertEquals('test_route', $url->getRouteName());
     $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
-
-    // Test with leading /.
-    $url = $this->pathValidator->getUrlIfValid('/test-path');
-    $this->assertInstanceOf('Drupal\Core\Url', $url);
-
-    $this->assertEquals('test_route', $url->getRouteName());
-    $this->assertEquals(['key' => 'value'], $url->getRouteParameters());
   }
 
   /**
