diff --git a/core/modules/forum/src/Form/Overview.php b/core/modules/forum/src/Form/Overview.php
index 720ee85..034cab1 100644
--- a/core/modules/forum/src/Form/Overview.php
+++ b/core/modules/forum/src/Form/Overview.php
@@ -65,19 +65,24 @@ public function buildForm(array $form, FormStateInterface $form_state) {
       if (isset($form['terms'][$key]['#term'])) {
         $term = $form['terms'][$key]['#term'];
         $form['terms'][$key]['term']['#url'] = Url::fromRoute('forum.page', ['taxonomy_term' => $term->id()]);
-        unset($form['terms'][$key]['operations']['#links']['delete']);
-        $route_parameters = $form['terms'][$key]['operations']['#links']['edit']['url']->getRouteParameters();
-        if (!empty($term->forum_container->value)) {
-          $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit container');
-          $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', $route_parameters);
+        if ($form['terms'][$key]['#term']->access('delete')) {
+          unset($form['terms'][$key]['operations']['#links']['delete']);
         }
-        else {
-          $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit forum');
-          $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_form', $route_parameters);
+
+        if($form['terms'][$key]['#term']->access('update')) {
+          $route_parameters = $form['terms'][$key]['operations']['#links']['edit']['url']->getRouteParameters();
+          if (!empty($term->forum_container->value)) {
+            $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit container');
+            $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', $route_parameters);
+          }
+          else {
+            $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit forum');
+            $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_form', $route_parameters);
+          }
+          // We don't want the redirect from the link so we can redirect the
+          // delete action.
+          unset($form['terms'][$key]['operations']['#links']['edit']['query']['destination']);
         }
-        // We don't want the redirect from the link so we can redirect the
-        // delete action.
-        unset($form['terms'][$key]['operations']['#links']['edit']['query']['destination']);
       }
     }
 
diff --git a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
index 91547c4..31403a8 100644
--- a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
+++ b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php
@@ -99,7 +99,7 @@ function testNodeAccessBasic() {
     // Array of nids marked private.
     $private_nodes = [];
     for ($i = 0; $i < $num_simple_users; $i++) {
-      $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content'));
+      $simple_users[$i] = $this->drupalCreateUser(['access content', 'create article content', 'create terms in tags']);
     }
     foreach ($simple_users as $this->webUser) {
       $this->drupalLogin($this->webUser);
diff --git a/core/modules/taxonomy/src/Access/TaxonomyOverviewAccessCheck.php b/core/modules/taxonomy/src/Access/TaxonomyOverviewAccessCheck.php
new file mode 100644
index 0000000..46833ca
--- /dev/null
+++ b/core/modules/taxonomy/src/Access/TaxonomyOverviewAccessCheck.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck.
+ */
+
+namespace Drupal\taxonomy\Access;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Routing\Access\AccessInterface;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Provides an access check for the taxonomy overview page.
+ */
+class TaxonomyOverviewAccessCheck implements AccessInterface {
+
+  /**
+   * {@inheritdoc}
+   *
+   * @param AccountInterface $account
+   * @return AccessResult
+   */
+  public function access(AccountInterface $account) {
+    $access = $account->hasPermission('administer taxonomy') || $account->hasPermission('access taxonomy overview');
+    return AccessResult::allowedIf($access);
+  }
+
+}
diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php
index dffbe34..2450cd9 100644
--- a/core/modules/taxonomy/src/Form/OverviewTerms.php
+++ b/core/modules/taxonomy/src/Form/OverviewTerms.php
@@ -27,6 +27,13 @@ class OverviewTerms extends FormBase {
   protected $moduleHandler;
 
   /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
    * The term storage controller.
    *
    * @var \Drupal\taxonomy\TermStorageInterface
@@ -43,6 +50,7 @@ class OverviewTerms extends FormBase {
    */
   public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) {
     $this->moduleHandler = $module_handler;
+    $this->entityManager = $entity_manager;
     $this->storageController = $entity_manager->getStorage('taxonomy_term');
   }
 
@@ -204,14 +212,23 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
     $destination = $this->getDestinationArray();
     $row_position = 0;
     // Build the actual form.
+    $access_control_handler = $this->entityManager->getAccessControlHandler('taxonomy_term');
+    if ($access_control_handler->createAccess($taxonomy_vocabulary->id())) {
+      $empty = $this->t('No terms available. <a href="@link">Add term</a>.', ['@link' => $this->url('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])]);
+    }
+    else {
+      $empty = $this->t('No terms available.');
+    }
     $form['terms'] = array(
       '#type' => 'table',
       '#header' => array($this->t('Name'), $this->t('Weight'), $this->t('Operations')),
-      '#empty' => $this->t('No terms available. <a href=":link">Add term</a>.', array(':link' => $this->url('entity.taxonomy_term.add_form', array('taxonomy_vocabulary' => $taxonomy_vocabulary->id())))),
+      '#empty' => $empty,
       '#attributes' => array(
         'id' => 'taxonomy',
       ),
     );
+    $change_weight_access = TRUE;
+    $operations_access = TRUE;
     foreach ($current_page as $key => $term) {
       /** @var $term \Drupal\Core\Entity\EntityInterface */
       $form['terms'][$key]['#term'] = $term;
@@ -256,28 +273,36 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
           ),
         );
       }
-      $form['terms'][$key]['weight'] = array(
-        '#type' => 'weight',
-        '#delta' => $delta,
-        '#title' => $this->t('Weight for added term'),
-        '#title_display' => 'invisible',
-        '#default_value' => $term->getWeight(),
-        '#attributes' => array(
-          'class' => array('term-weight'),
-        ),
-      );
-      $operations = array(
-        'edit' => array(
+      $edit_access = $term->access('update');
+      $change_weight_access &= $edit_access;
+
+      if ($edit_access) {
+        $form['terms'][$key]['weight'] = [
+          '#type' => 'weight',
+          '#delta' => $delta,
+          '#title' => $this->t('Weight for added term'),
+          '#title_display' => 'invisible',
+          '#default_value' => $term->getWeight(),
+          '#attributes' => ['class' => ['term-weight']],
+          '#access' => $edit_access,
+        ];
+      }
+      $operations = [];
+
+      if ($edit_access) {
+        $operations['edit'] = [
           'title' => $this->t('Edit'),
           'query' => $destination,
           'url' => $term->urlInfo('edit-form'),
-        ),
-        'delete' => array(
+        ];
+      }
+      if ($term->access('delete')) {
+        $operations['delete'] = [
           'title' => $this->t('Delete'),
           'query' => $destination,
           'url' => $term->urlInfo('delete-form'),
-        ),
-      );
+        ];
+      }
       if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) {
         $operations['translate'] = array(
           'title' => $this->t('Translate'),
@@ -285,10 +310,14 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
           'url' => $term->urlInfo('drupal:content-translation-overview'),
         );
       }
-      $form['terms'][$key]['operations'] = array(
-        '#type' => 'operations',
-        '#links' => $operations,
-      );
+
+      $operations_access &= count($operations) > 0;
+      if (count($operations)) {
+        $form['terms'][$key]['operations'] = [
+          '#type' => 'operations',
+          '#links' => $operations,
+        ];
+      }
 
       $form['terms'][$key]['#attributes']['class'] = array();
       if ($parent_fields) {
@@ -318,32 +347,40 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
       $row_position++;
     }
 
-    if ($parent_fields) {
-      $form['terms']['#tabledrag'][] = array(
-        'action' => 'match',
-        'relationship' => 'parent',
-        'group' => 'term-parent',
-        'subgroup' => 'term-parent',
-        'source' => 'term-id',
-        'hidden' => FALSE,
-      );
-      $form['terms']['#tabledrag'][] = array(
-        'action' => 'depth',
-        'relationship' => 'group',
-        'group' => 'term-depth',
-        'hidden' => FALSE,
-      );
-      $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy';
-      $form['terms']['#attached']['drupalSettings']['taxonomy'] = [
-        'backStep' => $back_step,
-        'forwardStep' => $forward_step,
+    $form['terms']['#header'] = array($this->t('Name'));
+    if ($change_weight_access) {
+      $form['terms']['#header'][] = $this->t('Weight');
+      if ($parent_fields) {
+        $form['terms']['#tabledrag'][] = [
+          'action' => 'match',
+          'relationship' => 'parent',
+          'group' => 'term-parent',
+          'subgroup' => 'term-parent',
+          'source' => 'term-id',
+          'hidden' => FALSE,
+        ];
+        $form['terms']['#tabledrag'][] = [
+          'action' => 'depth',
+          'relationship' => 'group',
+          'group' => 'term-depth',
+          'hidden' => FALSE,
+        ];
+        $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy';
+        $form['terms']['#attached']['drupalSettings']['taxonomy'] = [
+          'backStep' => $back_step,
+          'forwardStep' => $forward_step,
+        ];
+      }
+      $form['terms']['#tabledrag'][] = [
+        'action' => 'order',
+        'relationship' => 'sibling',
+        'group' => 'term-weight',
       ];
     }
-    $form['terms']['#tabledrag'][] = array(
-      'action' => 'order',
-      'relationship' => 'sibling',
-      'group' => 'term-weight',
-    );
+
+    if ($operations_access) {
+      $form['terms']['#header'][] = $this->t('Operations');
+    }
 
     if ($taxonomy_vocabulary->getHierarchy() != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
       $form['actions'] = array('#type' => 'actions', '#tree' => FALSE);
@@ -351,11 +388,13 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
         '#type' => 'submit',
         '#value' => $this->t('Save'),
         '#button_type' => 'primary',
+        '#access' => $change_weight_access,
       );
       $form['actions']['reset_alphabetical'] = array(
         '#type' => 'submit',
         '#submit' => array('::submitReset'),
         '#value' => $this->t('Reset to alphabetical'),
+        '#access' => $change_weight_access,
       );
     }
 
diff --git a/core/modules/taxonomy/src/TaxonomyPermissions.php b/core/modules/taxonomy/src/TaxonomyPermissions.php
index 6b7b841..24dc3dc 100644
--- a/core/modules/taxonomy/src/TaxonomyPermissions.php
+++ b/core/modules/taxonomy/src/TaxonomyPermissions.php
@@ -10,6 +10,7 @@
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\taxonomy\Entity\Vocabulary;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -53,19 +54,30 @@ public static function create(ContainerInterface $container) {
    */
   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->label()]),
-        ],
-      ];
-      $permissions += [
-        'delete terms in ' . $vocabulary->id() => [
-          'title' => $this->t('Delete terms from %vocabulary', ['%vocabulary' => $vocabulary->label()]),
-        ],
-      ];
+    foreach (Vocabulary::loadMultiple() as $vocabulary) {
+      $permissions += $this->buildPermissions($vocabulary);
     }
     return $permissions;
   }
 
+  /**
+   * Builds a standard list of taxonomy term permissions for a given vocabulary.
+   *
+   * @param \Drupal\taxonomy\Entity\Vocabulary
+   *   The vocabulary.
+   *
+   * @return array
+   *   An array of permission names and descriptions.
+   */
+  protected function buildPermissions(Vocabulary $vocabulary) {
+    $id = $vocabulary->id();
+    $args = ['%vocabulary' => $vocabulary->label()];
+
+    return [
+      "create terms in $id" => ['title' => $this->t('%vocabulary: Create terms', $args)],
+      "delete terms in $id" => ['title' => $this->t('%vocabulary: Delete terms', $args)],
+      "edit terms in $id" => ['title' => $this->t('%vocabulary: Edit terms', $args)],
+    ];
+  }
+
 }
diff --git a/core/modules/taxonomy/src/TermAccessControlHandler.php b/core/modules/taxonomy/src/TermAccessControlHandler.php
index 7f12e02..61ea699 100644
--- a/core/modules/taxonomy/src/TermAccessControlHandler.php
+++ b/core/modules/taxonomy/src/TermAccessControlHandler.php
@@ -46,7 +46,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter
    * {@inheritdoc}
    */
   protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {
-    return AccessResult::allowedIfHasPermission($account, 'administer taxonomy');
+    return AccessResult::allowedIfHasPermissions($account, ["create terms in $entity_bundle", 'administer taxonomy'], 'OR');
   }
 
 }
diff --git a/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php b/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php
index 6294e60..1a94988 100644
--- a/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php
+++ b/core/modules/taxonomy/src/Tests/VocabularyPermissionsTest.php
@@ -21,6 +21,34 @@ protected function setUp() {
   }
 
   /**
+   * Create, edit and delete a vocabulary via the user interface.
+   */
+  function testVocabularyPermissionsVocabulary() {
+    // VocabularyTest.php already tests for user with "administer taxonomy"
+    // permission.
+
+    // Test as user without proper permissions.
+    $authenticated_user = $this->drupalCreateUser([]);
+    $this->drupalLogin($authenticated_user);
+
+    // Visit the main taxonomy administration page.
+    $this->drupalGet('admin/structure/taxonomy');
+    $this->assertResponse(403, 'Vocabulary overview open failed.');
+
+    // Test as user with "access taxonomy overview" permissions.
+    $proper_user = $this->drupalCreateUser(['access taxonomy overview']);
+    $this->drupalLogin($proper_user);
+
+    // Visit the main taxonomy administration page.
+    $this->drupalGet('admin/structure/taxonomy');
+    $this->assertResponse(200);
+    $this->assertText(t('Vocabulary name'), 'Vocabulary overview opened successfully.');
+
+    // Create a new vocabulary.
+    $this->assertNoLink(t('Add vocabulary'));
+  }
+
+  /**
    * Create, edit and delete a taxonomy term via the user interface.
    */
   function testVocabularyPermissionsTaxonomyTerm() {
@@ -63,8 +91,35 @@ function testVocabularyPermissionsTaxonomyTerm() {
     $this->drupalPostForm(NULL, NULL, t('Delete'));
     $this->assertRaw(t('Deleted term %name.', array('%name' => $edit['name[0][value]'])), 'Term deleted.');
 
+    // Test as user with "create" permissions.
+    $user = $this->drupalCreateUser(["access taxonomy overview", "create terms in {$vocabulary->id()}"]);
+    $this->drupalLogin($user);
+
+    // Visit the main taxonomy administration page.
+    $this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add');
+    $this->assertResponse(200);
+    $this->assertFieldByName('name[0][value]', NULL, 'Add taxonomy term form opened successfully.');
+
+    // Submit the term.
+    $edit = array();
+    $edit['name[0][value]'] = $this->randomMachineName();
+
+    $this->drupalPostForm(NULL, $edit, t('Save'));
+    $this->assertRaw(t('Created new term %name.', ['%name' => $edit['name[0][value]']]), 'Term created successfully.');
+
+    $terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']);
+    $term = reset($terms);
+
+    // Edit the term.
+    $this->drupalGet('taxonomy/term/' . $term->id() . '/edit');
+    $this->assertResponse(403, 'Edit taxonomy term form open failed.');
+
+    // Delete the vocabulary.
+    $this->drupalGet('taxonomy/term/' . $term->id() . '/delete');
+    $this->assertResponse(403, 'Delete taxonomy term form open failed.');
+
     // Test as user with "edit" permissions.
-    $user = $this->drupalCreateUser(array("edit terms in {$vocabulary->id()}"));
+    $user = $this->drupalCreateUser(["access taxonomy overview", "edit terms in {$vocabulary->id()}"]);
     $this->drupalLogin($user);
 
     // Visit the main taxonomy administration page.
@@ -88,7 +143,7 @@ function testVocabularyPermissionsTaxonomyTerm() {
     $this->assertResponse(403, 'Delete taxonomy term form open failed.');
 
     // Test as user with "delete" permissions.
-    $user = $this->drupalCreateUser(array("delete terms in {$vocabulary->id()}"));
+    $user = $this->drupalCreateUser(["access taxonomy overview", "delete terms in {$vocabulary->id()}"]);
     $this->drupalLogin($user);
 
     // Visit the main taxonomy administration page.
diff --git a/core/modules/taxonomy/src/VocabularyListBuilder.php b/core/modules/taxonomy/src/VocabularyListBuilder.php
index be8b318..b73445b 100644
--- a/core/modules/taxonomy/src/VocabularyListBuilder.php
+++ b/core/modules/taxonomy/src/VocabularyListBuilder.php
@@ -9,8 +9,14 @@
 
 use Drupal\Core\Config\Entity\DraggableListBuilder;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
+use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Url;
+use Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a class to build a listing of taxonomy vocabulary entities.
@@ -25,6 +31,55 @@ class VocabularyListBuilder extends DraggableListBuilder {
   protected $entitiesKey = 'vocabularies';
 
   /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $currentUser;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * Constructs a new VocabularyListBuilder object.
+   *
+   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
+   *   The entity type definition.
+   * @param \Drupal\Core\Entity\EntityStorageInterface $storage
+   *   The entity storage class.
+   * @param \Drupal\Core\Session\AccountInterface $current_user
+   *   The current user.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager service.
+   * @param \Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck $access_view
+   *   The access check service.
+   */
+  public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, AccountInterface $current_user, EntityManagerInterface $entity_manager, TaxonomyOverviewAccessCheck $access_view) {
+    parent::__construct($entity_type, $storage);
+
+    $this->current_user = $current_user;
+    $this->entityManager = $entity_manager;
+    $this->access_view = $access_view;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
+    return new static(
+      $entity_type,
+      $container->get('entity.manager')->getStorage($entity_type->id()),
+      $container->get('current_user'),
+      $container->get('entity.manager'),
+      $container->get('access_check.taxonomy.taxonomy_overview')
+    );
+  }
+
+  /**
    * {@inheritdoc}
    */
   public function getFormId() {
@@ -41,16 +96,22 @@ public function getDefaultOperations(EntityInterface $entity) {
       $operations['edit']['title'] = t('Edit vocabulary');
     }
 
-    $operations['list'] = array(
-      'title' => t('List terms'),
-      'weight' => 0,
-      'url' => $entity->urlInfo('overview-form'),
-    );
-    $operations['add'] = array(
-      'title' => t('Add terms'),
-      'weight' => 10,
-      'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]),
-    );
+    if($this->access_view->access($this->current_user)) {
+      $operations['list'] = array(
+        'title' => t('List terms'),
+        'weight' => 0,
+        'url' => $entity->urlInfo('overview-form'),
+      );
+    }
+
+    $taxonomy_term_access_control_handler = $this->entityManager->getAccessControlHandler('taxonomy_term');
+    if ($taxonomy_term_access_control_handler->createAccess($entity->id())) {
+      $operations['add'] = [
+        'title' => t('Add terms'),
+        'weight' => 10,
+        'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]),
+      ];
+    }
     unset($operations['delete']);
 
     return $operations;
@@ -61,6 +122,11 @@ public function getDefaultOperations(EntityInterface $entity) {
    */
   public function buildHeader() {
     $header['label'] = t('Vocabulary name');
+
+    if ($this->current_user->hasPermission('administer vocabularies')) {
+      $header['weight'] = t('Weight');
+    }
+
     return $header + parent::buildHeader();
   }
 
@@ -68,9 +134,9 @@ public function buildHeader() {
    * {@inheritdoc}
    */
   public function buildRow(EntityInterface $entity) {
-    $row['label'] = $entity->label();
-    return $row + parent::buildRow($entity);
-  }
+      $row['label'] = $entity->label();
+      return $row + parent::buildRow($entity);
+    }
 
   /**
    * {@inheritdoc}
@@ -83,7 +149,12 @@ public function render() {
       unset($this->weightKey);
     }
     $build = parent::render();
-    $build['table']['#empty'] = t('No vocabularies available. <a href=":link">Add vocabulary</a>.', array(':link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')));
+    if ($this->current_user->hasPermission('administer vocabularies')) {
+      $build['table']['#empty'] = t('No vocabularies available. <a href="@link">Add vocabulary</a>.', ['@link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')]);
+    }
+    else {
+      $build['table']['#empty'] = t('No vocabularies available.');
+    }
     return $build;
   }
 
diff --git a/core/modules/taxonomy/taxonomy.permissions.yml b/core/modules/taxonomy/taxonomy.permissions.yml
index d485949..bb71e93 100644
--- a/core/modules/taxonomy/taxonomy.permissions.yml
+++ b/core/modules/taxonomy/taxonomy.permissions.yml
@@ -1,5 +1,9 @@
 administer taxonomy:
   title: 'Administer vocabularies and terms'
 
+access taxonomy overview:
+  title: 'Access the taxonomy vocabulary overview page'
+  description: 'Get an overview of all taxonomy vocabularies.'
+
 permission_callbacks:
   - Drupal\taxonomy\TaxonomyPermissions::permissions
diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml
index a7a75f3..0ee60f6 100644
--- a/core/modules/taxonomy/taxonomy.routing.yml
+++ b/core/modules/taxonomy/taxonomy.routing.yml
@@ -4,7 +4,7 @@ entity.taxonomy_vocabulary.collection:
     _entity_list: 'taxonomy_vocabulary'
     _title: 'Taxonomy'
   requirements:
-    _permission: 'administer taxonomy'
+    _access_taxonomy_overview: 'TRUE'
 
 entity.taxonomy_term.add_form:
   path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add'
@@ -72,7 +72,7 @@ entity.taxonomy_vocabulary.overview_form:
     _form: 'Drupal\taxonomy\Form\OverviewTerms'
     _title_callback: 'Drupal\taxonomy\Controller\TaxonomyController::vocabularyTitle'
   requirements:
-    _entity_access: 'taxonomy_vocabulary.view'
+    _access_taxonomy_overview: 'TRUE'
 
 entity.taxonomy_term.canonical:
   path: '/taxonomy/term/{taxonomy_term}'
diff --git a/core/modules/taxonomy/taxonomy.services.yml b/core/modules/taxonomy/taxonomy.services.yml
index a8153ed..b521c7f 100644
--- a/core/modules/taxonomy/taxonomy.services.yml
+++ b/core/modules/taxonomy/taxonomy.services.yml
@@ -4,3 +4,7 @@ services:
     arguments: ['@entity.manager']
     tags:
       - { name: breadcrumb_builder, priority: 1002 }
+  access_check.taxonomy.taxonomy_overview:
+    class: Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck
+    tags:
+      - { name: access_check, applies_to: _access_taxonomy_overview }
diff --git a/core/modules/views/src/Tests/Wizard/WizardTestBase.php b/core/modules/views/src/Tests/Wizard/WizardTestBase.php
index 7d8d9c0..0e35233 100644
--- a/core/modules/views/src/Tests/Wizard/WizardTestBase.php
+++ b/core/modules/views/src/Tests/Wizard/WizardTestBase.php
@@ -15,6 +15,13 @@
 abstract class WizardTestBase extends ViewTestBase {
 
   /**
+   * Permissions for this user to test with.
+   *
+   * @var array
+   */
+  protected $permissions = [];
+
+  /**
    * Modules to enable.
    *
    * @var array
@@ -24,8 +31,10 @@
   protected function setUp() {
     parent::setUp();
 
+    $this->permissions = array_merge($this->permissions, ['administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view all revisions']);
+
     // Create and log in a user with administer views permission.
-    $views_admin = $this->drupalCreateUser(array('administer views', 'administer blocks', 'bypass node access', 'access user profiles', 'view all revisions'));
+    $views_admin = $this->drupalCreateUser($this->permissions);
     $this->drupalLogin($views_admin);
     $this->drupalPlaceBlock('local_actions_block');
   }
