diff --git a/core/core.services.yml b/core/core.services.yml
index c56c778..738a5fa 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1532,3 +1532,8 @@ services:
     arguments: ['@current_user', '@path.current', '@path.matcher', '@language_manager']
     tags:
       - { name: event_subscriber }
+  pager.factory:
+    class: Drupal\Core\Pager\PagerFactory
+    arguments: ['@request_stack']
+    calls:
+      - [initPagers]
diff --git a/core/globals.api.php b/core/globals.api.php
index 1487b19..8934c4a 100644
--- a/core/globals.api.php
+++ b/core/globals.api.php
@@ -78,6 +78,9 @@
  *
  * The array index is the pager element index (0 by default).
  *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
+ *
  * @see pager_default_initialize()
  */
 global $pager_limits;
@@ -87,6 +90,9 @@
  *
  * The array index is the pager element index (0 by default).
  *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
+ *
  * @see pager_default_initialize()
  */
 global $pager_page_array;
@@ -96,6 +102,9 @@
  *
  * The array index is the pager element index (0 by default).
  *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
+ *
  * @see pager_default_initialize()
  */
 global $pager_total;
@@ -105,6 +114,9 @@
  *
  * The array index is the pager element index (0 by default).
  *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
+ *
  * @see pager_default_initialize()
  */
 global $pager_total_items;
diff --git a/core/includes/pager.inc b/core/includes/pager.inc
index 7b106ea..f0e0637 100644
--- a/core/includes/pager.inc
+++ b/core/includes/pager.inc
@@ -6,7 +6,6 @@
  */
 
 use Drupal\Core\Template\Attribute;
-use Drupal\Component\Utility\UrlHelper;
 
 /**
  * Returns the current page being requested for display within a pager.
@@ -24,15 +23,13 @@
  *  though the default pager implementation adjusts for this and still displays
  * the third page of search results at that URL.
  *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
+ *
  * @see pager_default_initialize()
  */
 function pager_find_page($element = 0) {
-  $page = \Drupal::request()->query->get('page', '');
-  $page_array = explode(',', $page);
-  if (!isset($page_array[$element])) {
-    $page_array[$element] = 0;
-  }
-  return (int) $page_array[$element];
+  return \Drupal::service('pager.factory')->get($element)->findCurrentPage();
 }
 
 /**
@@ -124,18 +121,12 @@ function pager_find_page($element = 0) {
  *   that does not correspond to the actual range of the result set was
  *   requested, this function will return the closest page actually within the
  *   result set.
+ *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
  */
 function pager_default_initialize($total, $limit, $element = 0) {
-  global $pager_page_array, $pager_total, $pager_total_items, $pager_limits;
-
-  $page = pager_find_page($element);
-
-  // We calculate the total of pages as ceil(items / limit).
-  $pager_total_items[$element] = $total;
-  $pager_total[$element] = ceil($pager_total_items[$element] / $limit);
-  $pager_page_array[$element] = max(0, min($page, ((int) $pager_total[$element]) - 1));
-  $pager_limits[$element] = $limit;
-  return $pager_page_array[$element];
+  return \Drupal::service('pager.factory')->get($element)->init($total, $limit)->getCurrentPage();
 }
 
 /**
@@ -144,13 +135,12 @@ function pager_default_initialize($total, $limit, $element = 0) {
  * @return
  *   A URL query parameter array that consists of all components of the current
  *   page request except for those pertaining to paging.
+ *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
  */
 function pager_get_query_parameters() {
-  $query = &drupal_static(__FUNCTION__);
-  if (!isset($query)) {
-    $query = UrlHelper::filterQueryParameters(\Drupal::request()->query->all(), array('page'));
-  }
-  return $query;
+  return \Drupal::service('pager.factory')->getCurrentRequestQueryParameters();
 }
 
 /**
@@ -173,14 +163,16 @@ function pager_get_query_parameters() {
  *     - #quantity: The number of pages in the list.
  */
 function template_preprocess_pager(&$variables) {
-  $element = $variables['pager']['#element'];
-  $parameters = $variables['pager']['#parameters'];
   $quantity = $variables['pager']['#quantity'];
-  $route_name = $variables['pager']['#route_name'];
-  global $pager_page_array, $pager_total;
+
+  // Prepare the pager object.
+  $pager = \Drupal::service('pager.factory')
+    ->get($variables['pager']['#element'])
+    ->setRouteName($variables['pager']['#route_name'])
+    ->setInputQueryParameters($variables['pager']['#parameters']);
 
   // Nothing to do if there is only one page.
-  if ($pager_total[$element] <= 1) {
+  if ($pager->getTotalPages() <= 1) {
     return;
   }
 
@@ -190,13 +182,13 @@ function template_preprocess_pager(&$variables) {
   // Middle is used to "center" pages around the current page.
   $pager_middle = ceil($quantity / 2);
   // current is the page we are currently paged to.
-  $pager_current = $pager_page_array[$element] + 1;
+  $pager_current = $pager->getCurrentPage() + 1;
   // first is the first page listed by this pager piece (re quantity).
   $pager_first = $pager_current - $pager_middle + 1;
   // last is the last page listed by this pager piece (re quantity).
   $pager_last = $pager_current + $quantity - $pager_middle;
   // max is the maximum page number.
-  $pager_max = $pager_total[$element];
+  $pager_max = $pager->getTotalPages();
   // End of marker calculations.
 
   // Prepare for generation loop.
@@ -214,21 +206,17 @@ function template_preprocess_pager(&$variables) {
   // End of generation loop preparation.
 
   // Create the "first" and "previous" links if we are not on the first page.
-  if ($pager_page_array[$element] > 0) {
-    $items['first'] = array();
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, 0),
-    );
-    $items['first']['href'] = \Drupal::url($route_name, [], $options);
+  if ($pager->getCurrentPage() > 0) {
+    $items['first'] = [
+      'href' => $pager->getLink(0),
+    ];
     if (isset($tags[0])) {
       $items['first']['text'] = $tags[0];
     }
 
-    $items['previous'] = array();
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, $pager_page_array[$element] - 1),
-    );
-    $items['previous']['href'] = \Drupal::url($route_name, [], $options);
+    $items['previous'] = [
+      'href' => $pager->getLink($pager->getCurrentPage() - 1),
+    ];
     if (isset($tags[1])) {
       $items['previous']['text'] = $tags[1];
     }
@@ -241,10 +229,7 @@ function template_preprocess_pager(&$variables) {
     }
     // Now generate the actual pager piece.
     for (; $i <= $pager_last && $i <= $pager_max; $i++) {
-      $options = array(
-        'query' => pager_query_add_page($parameters, $element, $i - 1),
-      );
-      $items['pages'][$i]['href'] = \Drupal::url($route_name, [], $options);
+      $items['pages'][$i]['href'] = $pager->getLink($i - 1);
       if ($i == $pager_current) {
         $variables['current'] = $i;
       }
@@ -256,21 +241,17 @@ function template_preprocess_pager(&$variables) {
   }
 
   // Create the "next" and "last" links if we are not on the last page.
-  if ($pager_page_array[$element] < ($pager_max - 1)) {
-    $items['next'] = array();
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, $pager_page_array[$element] + 1),
-    );
-    $items['next']['href'] = \Drupal::url($route_name, [], $options);
+  if ($pager->getCurrentPage() < ($pager_max - 1)) {
+    $items['next'] = [
+      'href' => $pager->getLink($pager->getCurrentPage() + 1),
+    ];
     if (isset($tags[3])) {
       $items['next']['text'] = $tags[3];
     }
 
-    $items['last'] = array();
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, $pager_max - 1),
-    );
-    $items['last']['href'] = \Drupal::url($route_name, [], $options);
+    $items['last'] = [
+      'href' => $pager->getLink($pager_max - 1),
+    ];
     if (isset($tags[4])) {
       $items['last']['text'] = $tags[4];
     }
@@ -301,25 +282,10 @@ function template_preprocess_pager(&$variables) {
  *
  * @return array
  *   The altered $query parameter array.
+ *
+ * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+ *   Instead, @todo
  */
 function pager_query_add_page(array $query, $element, $index) {
-  global $pager_page_array;
-
-  // Build the 'page' query parameter. This is built based on the current
-  // page of each pager element (or NULL if the pager is not set), with the
-  // exception of the requested page index for the current element.
-  $max_element = max(array_keys($pager_page_array));
-  $element_pages = [];
-  for ($i = 0; $i <= $max_element; $i++) {
-    $element_pages[] = ($i == $element) ? $index : (isset($pager_page_array[$i]) ? $pager_page_array[$i] : NULL);
-  }
-  $query['page'] = implode(',', $element_pages);
-
-  // Merge the query parameters passed to this function with the parameters
-  // from the current request. In case of collision, the parameters passed into
-  // this function take precedence.
-  if ($current_request_query = pager_get_query_parameters()) {
-    $query = array_merge($current_request_query, $query);
-  }
-  return $query;
+  return \Drupal::service('pager.factory')->get($element)->setInputQueryParameters($query)->getLinkQueryParameters($index);
 }
diff --git a/core/lib/Drupal/Core/Pager/Pager.php b/core/lib/Drupal/Core/Pager/Pager.php
new file mode 100644
index 0000000..cca6598
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/Pager.php
@@ -0,0 +1,317 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Pager\Pager.
+ */
+
+namespace Drupal\Core\Pager;
+
+use Drupal\Core\Routing\UrlGeneratorInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Pager class.
+ */
+class Pager implements PagerInterface {
+
+  /**
+   * The pager element.
+   *
+   * This is the index used by query extenders to identify the query
+   * to be paged, and reflected in the 'page=x,y,z' query parameter
+   * of the HTTP request.
+   *
+   * @var int
+   */
+  protected $element;
+
+  /**
+   * Number of items per page.
+   *
+   * @var int
+   */
+  protected $limit = 0;
+
+  /**
+   * Current page number, 0-indexed.
+   *
+   * @var int
+   */
+  protected $currentPage = 0;
+
+  /**
+   * Total number of pages.
+   *
+   * @var int
+   */
+  protected $totalPages = 0;
+
+  /**
+   * Total number of items.
+   *
+   * @var int
+   */
+  protected $totalItems = 0;
+
+  /**
+   * The route name.
+   *
+   * @var string
+   */
+  protected $routeName;
+
+  /**
+   * The input query parameters for this pager's links.
+   *
+   * @var string[]
+   */
+  protected $inputQueryParameters;
+
+  /**
+   * The pager factory.
+   *
+   * @var \Drupal\Core\Pager\PagerFactoryInterface
+   */
+  protected $factory;
+
+  /**
+   * The URL generator.
+   *
+   * @var \Drupal\Core\Routing\UrlGeneratorInterface
+   */
+  protected $urlGenerator;
+
+  /**
+   * Constructs a new Pager object.
+   *
+   * @param \Drupal\Core\Pager\PagerFactoryInterface $pager_factory
+   *   The pager factory.
+   * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
+   *   The URL generator.
+   */
+  public function __construct(PagerFactoryInterface $pager_factory, UrlGeneratorInterface $url_generator) {
+    $this->factory = $pager_factory;
+    $this->urlGenerator = $url_generator;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, $element = NULL) {
+    $instance = new static(
+      $container->get('pager.factory'),
+      $container->get('url_generator')
+    );
+
+    // Set the pager element.
+    $instance->element = $element;
+
+    return $instance;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRouteName() {
+    return $this->routeName;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setRouteName($route_name) {
+    $this->routeName = $route_name;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getInputQueryParameters() {
+    return $this->inputQueryParameters;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setInputQueryParameters(array $query_parameters) {
+    $this->inputQueryParameters = $query_parameters;
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getElement() {
+    return $this->element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function init($total, $limit) {
+    // Gets the element's current page from the current request.
+    $page = $this->findCurrentPage();
+
+    // We calculate the total of pages as ceil(items / limit).
+    $this
+      ->setTotalItems($total)
+      ->setTotalPages(ceil($this->getTotalItems() / $limit))
+      ->setCurrentPage(max(0, min($page, ((int) $this->getTotalPages() - 1))))
+      ->setLimit($limit);
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function findCurrentPage() {
+    $page_query = $this->factory->getCurrentRequestPageQuery();
+    $page_array = explode(',', $page_query);
+    if (!isset($page_array[$this->element])) {
+      $page_array[$this->element] = 0;
+    }
+    return (int) $page_array[$this->element];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCurrentPage() {
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_page_array;
+    $this->currentPage = isset($pager_page_array[$this->element]) ? $pager_page_array[$this->element] : NULL;
+
+    return $this->currentPage;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCurrentPage($page) {
+    $this->currentPage = $page;
+
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_page_array;
+    $pager_page_array[$this->element] = $page;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTotalPages() {
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_total;
+    $this->totalPages = isset($pager_total[$this->element]) ? $pager_total[$this->element] : NULL;
+
+    return $this->totalPages;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setTotalPages($total_pages) {
+    $this->totalPages = $total_pages;
+
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_total;
+    $pager_total[$this->element] = $total_pages;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLastPage() {
+    return max(0, $this->getTotalPages() - 1);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTotalItems() {
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_total_items;
+    $this->totalItems = isset($pager_total_items[$this->element]) ? $pager_total_items[$this->element] : NULL;
+
+    return $this->totalItems;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setTotalItems($total_items) {
+    $this->totalItems = $total_items;
+
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_total_items;
+    $pager_total_items[$this->element] = $total_items;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLimit() {
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_limits;
+    $this->limit = isset($pager_limits[$this->element]) ? $pager_limits[$this->element] : NULL;
+
+    return $this->limit;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setLimit($limit) {
+    $this->limit = $limit;
+
+    // @todo: BC layer. When removing the globals, remove the following.
+    global $pager_limits;
+    $pager_limits[$this->element] = $limit;
+
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLinkQueryParameters($page) {
+    // Get all defined pagers.
+    $pagers = $this->factory->all();
+
+    // Build the 'page' query parameter. This is built based on the current
+    // page of each pager element (or NULL if the pager is not set), with the
+    // exception of the requested page index for the current element.
+    $query = $this->getInputQueryParameters();
+    $max_element = max(array_keys($pagers));
+    $element_pages = [];
+    for ($i = 0; $i <= $max_element; $i++) {
+      $element_pages[] = ($i == $this->getElement()) ? $page : (isset($pagers[$i]) ? $pagers[$i]->getCurrentPage() : NULL);
+    }
+    $query['page'] = implode(',', $element_pages);
+
+    // Merge the query parameters passed to this function with the parameters
+    // from the current request. In case of collision, the parameters passed into
+    // this function take precedence.
+    if ($current_request_query = $this->factory->getCurrentRequestQueryParameters()) {
+      $query = array_merge($current_request_query, $query);
+    }
+
+    return $query;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getLink($page) {
+    $options = ['query' => $this->getLinkQueryParameters($page)];
+    return $this->urlGenerator->generateFromRoute($this->getRouteName(), [], $options);
+  }
+}
diff --git a/core/lib/Drupal/Core/Pager/PagerFactory.php b/core/lib/Drupal/Core/Pager/PagerFactory.php
new file mode 100644
index 0000000..79e3435
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/PagerFactory.php
@@ -0,0 +1,101 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Pager\PagerFactory.
+ */
+
+namespace Drupal\Core\Pager;
+
+use Drupal\Component\Utility\UrlHelper;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Provides a factory for pagers.
+ */
+class PagerFactory implements PagerFactoryInterface {
+
+  /**
+   * The array of pager objects.
+   *
+   * @var \Drupal\Core\Pager\Pager[]
+   */
+  protected $pagers = [];
+
+  /**
+   * The request stack object.
+   *
+   * @var \Symfony\Component\HttpFoundation\RequestStack
+   */
+  protected $requestStack;
+
+  /**
+   * Constructs a new PagerFactory object.
+   *
+   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
+   *   The request stack.
+   */
+  public function __construct(RequestStack $request_stack) {
+    $this->requestStack = $request_stack;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function initPagers() {
+    // @todo: BC layer. When removing the global, this method as well its
+    // call in core.services.yml can be dropped.
+    global $pager_total;
+    if (!empty($pager_total)) {
+      foreach ($pager_total as $element => $total) {
+        $this->get($element);
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function get($element) {
+    if (!isset($this->pagers[$element])) {
+      $this->pagers[$element] = Pager::create(\Drupal::getContainer(), $element);
+    }
+    return $this->pagers[$element];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function all() {
+    return $this->pagers;
+  }
+
+  /**
+   * Returns the current request object.
+   *
+   * @return \Symfony\Component\HttpFoundation\Request
+   *   The request object.
+   */
+  protected function getCurrentRequest() {
+    return $this->requestStack->getCurrentRequest();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCurrentRequestPageQuery() {
+    return $this->getCurrentRequest()->query->get('page', '');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCurrentRequestQueryParameters() {
+    static $query;
+    if (!isset($query)) {
+      $query = UrlHelper::filterQueryParameters($this->getCurrentRequest()->query->all(), ['page']);
+    }
+    return $query;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Pager/PagerFactoryInterface.php b/core/lib/Drupal/Core/Pager/PagerFactoryInterface.php
new file mode 100644
index 0000000..9b4611b
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/PagerFactoryInterface.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Pager\PagerFactory.
+ */
+
+namespace Drupal\Core\Pager;
+
+/**
+ * Provides an interface for pager factory objects.
+ */
+interface PagerFactoryInterface {
+
+  /**
+   * Initialises the pagers.
+   *
+   * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+   *   BC layer, @todo
+   */
+  public function initPagers();
+
+  /**
+   * Returns the pager object for the specified pager element.
+   *
+   * The pager gets created if not already existing.
+   *
+   * @param int $element
+   *   The pager element.
+   *
+   * @return \Drupal\Core\Pager\Pager
+   *   The pager object.
+   */
+  public function get($element);
+
+  /**
+   * Returns the current array of pager objects.
+   *
+   * @return \Drupal\Core\Pager\Pager[]
+   *   The array of pager objects.
+   */
+  public function all();
+
+  /**
+   * Returns the current request 'page' query fragment.
+   *
+   * @return string[]
+   *   The 'page' query fragment.
+   *
+   * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+   *   BC layer, @todo protected
+   */
+  public function getCurrentRequestPageQuery();
+
+  /**
+   * Compose a URL query parameter array for pager links.
+   *
+   * @return
+   *   A URL query parameter array that consists of all components of the current
+   *   page request except for those pertaining to paging.
+   *
+   * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+   *   BC layer, @todo protected
+   */
+  public function getCurrentRequestQueryParameters();
+
+}
diff --git a/core/lib/Drupal/Core/Pager/PagerInterface.php b/core/lib/Drupal/Core/Pager/PagerInterface.php
new file mode 100644
index 0000000..90892e9
--- /dev/null
+++ b/core/lib/Drupal/Core/Pager/PagerInterface.php
@@ -0,0 +1,195 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Pager\PagerInterface.
+ */
+
+namespace Drupal\Core\Pager;
+
+use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+
+/**
+ * Provides an interface for pager objects.
+ */
+interface PagerInterface extends ContainerInjectionInterface {
+
+  /**
+   * Gets the route name for this pager.
+   *
+   * @return string
+   *   The route name.
+   */
+  public function getRouteName();
+
+  /**
+   * Sets the route name for this pager.
+   *
+   * @param string $route_name
+   *   The route name.
+   *
+   * @return \Drupal\Core\Pager\PagerInterface
+   *   The Pager object.
+   */
+  public function setRouteName($route_name);
+
+  /**
+   * Gets the query parameters for this pager.
+   *
+   * @return string[]
+   *   The query parameters array.
+   */
+  public function getInputQueryParameters();
+
+  /**
+   * Sets the query parameters for this pager.
+   *
+   * @var string[] $query_parameters
+   *   The query parameters array.
+   *
+   * @return \Drupal\Core\Pager\PagerInterface
+   *   The Pager object.
+   */
+  public function setInputQueryParameters(array $query_parameters);
+
+  /**
+   * Gets the pager element.
+   *
+   * @return int
+   *   The pager element.
+   */
+  public function getElement();
+
+  /**
+   * Initializes the pager.
+   *
+   * @param int $total
+   *   The total number of items to be paged.
+   * @param int $limit
+   *   The number of items the calling code will display per page.
+   *
+   * @return \Drupal\Core\Pager\PagerInterface
+   *   The Pager object.
+   */
+  public function init($total, $limit);
+
+  /**
+   * Gets the current page (0-index), from the request query parameters.
+   *
+   * @return int
+   *   The page to which the pager is currently positioned to.
+   *
+   * @deprecated as of Drupal @todo, will be removed in Drupal 9.0.0.
+   *   BC layer, @todo protected
+   */
+  public function findCurrentPage();
+
+  /**
+   * Gets the current page (0-index).
+   *
+   * @return int
+   *   The page to which the pager is currently positioned to.
+   */
+  public function getCurrentPage();
+
+  /**
+   * Sets the current page for this pager (0-index).
+   *
+   * @param int $page
+   *   The page to which the pager is currently positioned to.
+   *
+   * @return \Drupal\Core\Pager\Pager
+   *   The Pager object.
+   */
+  public function setCurrentPage($page);
+
+  /**
+   * Gets total pages in the pager.
+   *
+   * @return int
+   *   The total number of pages managed by the pager.
+   */
+  public function getTotalPages();
+
+  /**
+   * Sets total pages in the pager.
+   *
+   * @var $total_pages int
+   *   The total number of pages managed by the pager.
+   *
+   * @return \Drupal\Core\Pager\Pager
+   *   The Pager object.
+   */
+  public function setTotalPages($total_pages);
+
+  /**
+   * Gets last page in the pager (0-index).
+   *
+   * @return int
+   *   The index of the last page in the pager.
+   */
+  public function getLastPage();
+
+  /**
+   * Gets total items in the pager.
+   *
+   * @return int
+   *   The total number of items (records) managed by the pager.
+   */
+  public function getTotalItems();
+
+  /**
+   * Sets total items in the pager.
+   *
+   * @var $total_items int
+   *   The total number of items (records) managed by the pager.
+   *
+   * @return \Drupal\Core\Pager\Pager
+   *   The Pager object.
+   */
+  public function setTotalItems($total_items);
+
+  /**
+   * Gets the items per page.
+   *
+   * @return int
+   *   The number of items (records) in each page.
+   */
+  public function getLimit();
+
+  /**
+   * Sets the items per page.
+   *
+   * @var $limit int
+   *   The number of items (records) in each page.
+   *
+   * @return \Drupal\Core\Pager\Pager
+   *   The Pager object.
+   */
+  public function setLimit($limit);
+
+  /**
+   * Gets a pager link query parameters.
+   *
+   * @param int $page
+   *   The target page.
+   *
+   * @return string[]
+   *   The query parameters array.
+   *
+   * @todo change to protected when pager_query_add_page() is removed maybe?
+   */
+  public function getLinkQueryParameters($page);
+
+  /**
+   * Gets a pager link.
+   *
+   * @param int $page
+   *   The target page.
+   *
+   * @return string
+   *   The URL of the pager link.
+   */
+  public function getLink($page);
+
+}
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index f34d076..1b0ec57 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -1021,31 +1021,27 @@ function template_preprocess_views_exposed_form(&$variables) {
  *     exposed input.
  */
 function template_preprocess_views_mini_pager(&$variables) {
-  global $pager_page_array, $pager_total;
-
   $tags = &$variables['tags'];
-  $element = $variables['element'];
-  $parameters = $variables['parameters'];
+
+  // Prepare the pager object.
+  $pager = \Drupal::service('pager.factory')
+    ->get($variables['element'])
+    ->setRouteName('<current>')
+    ->setInputQueryParameters($variables['parameters']);
 
   // Current is the page we are currently paged to.
-  $variables['items']['current'] = $pager_page_array[$element] + 1;
+  $variables['items']['current'] = $pager->getCurrentPage() + 1;
 
-  if ($pager_total[$element] > 1 && $pager_page_array[$element] > 0) {
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, $pager_page_array[$element] - 1),
-    );
-    $variables['items']['previous']['href'] = \Drupal::url('<current>', [], $options);
+  if ($pager->getTotalPages() > 1 && $pager->getCurrentPage() > 0) {
+    $variables['items']['previous']['href'] = $pager->getLink($pager->getCurrentPage() - 1);
     if (isset($tags[1])) {
       $variables['items']['previous']['text'] = $tags[1];
     }
     $variables['items']['previous']['attributes'] = new Attribute();
   }
 
-  if ($pager_page_array[$element] < ($pager_total[$element] - 1)) {
-    $options = array(
-      'query' => pager_query_add_page($parameters, $element, $pager_page_array[$element] + 1),
-    );
-    $variables['items']['next']['href'] = \Drupal::url('<current>', [], $options);
+  if ($pager->getCurrentPage() < ($pager->getTotalPages() - 1)) {
+    $variables['items']['next']['href'] = $pager->getLink($pager->getCurrentPage() + 1);
     if (isset($tags[3])) {
       $variables['items']['next']['text'] = $tags[3];
     }
