diff --git c/core/modules/book/book.module w/core/modules/book/book.module
index 1039b59..282aa92 100644
--- c/core/modules/book/book.module
+++ w/core/modules/book/book.module
@@ -195,11 +195,7 @@ function book_menu() {
   );
   $items['node/%node/outline/remove'] = array(
     'title' => 'Remove from outline',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('book_remove_form', 1),
-    'access callback' => '_book_outline_remove_access',
-    'access arguments' => array(1),
-    'file' => 'book.pages.inc',
+    'route_name' => 'book.remove',
   );
 
   return $items;
diff --git c/core/modules/book/book.routing.yml w/core/modules/book/book.routing.yml
index 39aff5c..923157d 100644
--- c/core/modules/book/book.routing.yml
+++ w/core/modules/book/book.routing.yml
@@ -50,3 +50,15 @@ book.admin_edit:
     _permission: 'administer book outlines'
     _entity_access: 'node.view'
     node: \d+
+
+book.remove:
+  path: '/node/{node}/outline/remove'
+  defaults:
+    _content: '\Drupal\book\Form\BookForm::remove'
+    _title: 'Remove from outline'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer book outlines'
+    _entity_access: 'node.view'
+    _book_node_is_removable: 'TRUE'
diff --git c/core/modules/book/book.services.yml w/core/modules/book/book.services.yml
index 510573a..2f1097a 100644
--- c/core/modules/book/book.services.yml
+++ w/core/modules/book/book.services.yml
@@ -5,3 +5,9 @@ services:
   book.export:
     class: Drupal\book\BookExport
     arguments: ['@entity.manager']
+
+  access_check.book.removable:
+    class: Drupal\book\Access\BookNodeIsRemovableAccessCheck
+    arguments: ['@book.manager']
+    tags:
+      - { name: access_check }
diff --git c/core/modules/book/lib/Drupal/book/Access/BookNodeIsRemovableAccessCheck.php w/core/modules/book/lib/Drupal/book/Access/BookNodeIsRemovableAccessCheck.php
new file mode 100644
index 0000000..eeeeca7
--- /dev/null
+++ w/core/modules/book/lib/Drupal/book/Access/BookNodeIsRemovableAccessCheck.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\book\Access\BookNodeIsRemovableAccessCheck.
+ */
+
+namespace Drupal\book\Access;
+
+use Drupal\book\BookManager;
+use Drupal\Core\Access\StaticAccessCheckInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Determines whether the requested node can be removed from its book.
+ */
+class BookNodeIsRemovableAccessCheck implements StaticAccessCheckInterface {
+
+  /**
+   * Book Manager Service.
+   *
+   * @var \Drupal\book\BookManager
+   */
+  protected $bookManager;
+
+  /**
+   * Constructs a BookNodeIsRemovableAccessCheck object.
+   *
+   * @param \Drupal\book\BookManager $book_manager
+   *   Book Manager Service.
+   */
+  public function __construct(BookManager $book_manager) {
+    $this->bookManager = $book_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appliesTo() {
+    return array('_book_node_is_removable');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    $node = $request->attributes->get('node');
+    if (!empty($node)) {
+      return $this->bookManager->checkNodeIsRemovable($node) ? static::ALLOW : static::DENY;
+    }
+    return static::DENY;
+  }
+
+}
diff --git c/core/modules/book/lib/Drupal/book/Form/BookForm.php w/core/modules/book/lib/Drupal/book/Form/BookForm.php
new file mode 100644
index 0000000..9ed431a
--- /dev/null
+++ w/core/modules/book/lib/Drupal/book/Form/BookForm.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\book\Form\BookForm.
+ */
+
+namespace Drupal\book\Form;
+
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Temporary form controller for book module.
+ */
+class BookForm {
+  /**
+   * Wraps book_remove_form().
+   *
+   * @see book_remove_form()
+   */
+  public function remove(EntityInterface $node) {
+    module_load_include('pages.inc', 'book');
+    return drupal_get_form('book_remove_form', $node);
+  }
+
+}
diff --git c/core/modules/content_translation/content_translation.module w/core/modules/content_translation/content_translation.module
index f26ff20..f2ae71d 100644
--- c/core/modules/content_translation/content_translation.module
+++ w/core/modules/content_translation/content_translation.module
@@ -192,10 +192,7 @@ function content_translation_menu() {
       // Delete translation callback.
       $items["$path/translations/delete/%language"] = array(
         'title' => 'Delete',
-        'page callback' => 'drupal_get_form',
-        'page arguments' => array('content_translation_delete_confirm', $entity_position, $language_position),
-        'access callback' => 'content_translation_delete_access',
-        'access arguments' => $args,
+        'route_name' => "content_translation.delete_$entity_type",
       ) + $item;
     }
   }
diff --git c/core/modules/content_translation/content_translation.services.yml w/core/modules/content_translation/content_translation.services.yml
index 678724d..c6514bc 100644
--- c/core/modules/content_translation/content_translation.services.yml
+++ w/core/modules/content_translation/content_translation.services.yml
@@ -2,3 +2,15 @@ services:
   content_translation.synchronizer:
     class: Drupal\content_translation\FieldTranslationSynchronizer
     arguments: ['@entity.manager']
+
+  content_translation.subscriber:
+    class: Drupal\content_translation\Routing\ContentTranslationRouteSubscriber
+    arguments: ['@plugin.manager.entity']
+    tags:
+      - { name: event_subscriber }
+
+  content_translation.manage_access:
+    class: Drupal\content_translation\Access\ContentTranslationManageAccessCheck
+    arguments: ['@plugin.manager.entity']
+    tags:
+      - { name: access_check }
diff --git c/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php w/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php
new file mode 100644
index 0000000..6a0f360
--- /dev/null
+++ w/core/modules/content_translation/lib/Drupal/content_translation/Access/ContentTranslationManageAccessCheck.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\content_translation\Access\ContentTranslationManageAccessCheck.
+ */
+
+namespace Drupal\content_translation\Access;
+
+use Drupal\Core\Entity\EntityManager;
+use Drupal\Core\Access\StaticAccessCheckInterface;
+use Drupal\Core\Language\Language;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Access check for entity translation CRUD operation.
+ */
+class ContentTranslationManageAccessCheck implements StaticAccessCheckInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
+
+  /**
+   * Constructs a ContentTranslationManageAccessCheck object.
+   *
+   * @param \Drupal\Core\Entity\EntityManager $manager
+   *   The entity type manager.
+   */
+  public function __construct(EntityManager $manager) {
+    $this->entityManager = $manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appliesTo() {
+    return array('_access_content_translation_manage');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    if ($entity = $request->attributes->get('entity')) {
+      $operation = $route->getRequirement('_access_content_translation_manage');
+      $entity_type = $entity->entityType();
+      $controller_class = $this->entityManager->getControllerClass($entity_type, 'translation');
+      $controller = new $controller_class($entity_type, $entity->entityInfo());
+
+      // Load translation.
+      $translations = $entity->getTranslationLanguages();
+      $languages = language_list();
+
+      if ($operation == 'delete') {
+        $language = language_load($request->attributes->get('language'));
+        $language = !empty($language) ? $language : language(Language::TYPE_CONTENT);
+        return isset($languages[$language->id])
+          && $language->id != $entity->getUntranslated()->language()->id
+          && isset($translations[$language->id])
+          && $controller->getTranslationAccess($entity, $operation)
+          ? static::ALLOW : static::DENY;
+      }
+    }
+    return static::DENY;
+  }
+}
diff --git c/core/modules/content_translation/lib/Drupal/content_translation/Form/ContentTranslationForm.php w/core/modules/content_translation/lib/Drupal/content_translation/Form/ContentTranslationForm.php
new file mode 100644
index 0000000..9873043
--- /dev/null
+++ w/core/modules/content_translation/lib/Drupal/content_translation/Form/ContentTranslationForm.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\content_translation\Form\ContentTranslationForm.
+ */
+
+namespace Drupal\content_translation\Form;
+
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Language\Language;
+
+/**
+ * Temporary form controller for content_translation module.
+ */
+class ContentTranslationForm {
+  /**
+   * Wraps content_translation_delete_confirm().
+   *
+   * @see content_translation_delete_confirm()
+   */
+  public function deleteTranslation(EntityInterface $entity, $language) {
+    module_load_include('pages.inc', 'content_translation');
+    $language = language_load($language);
+    return drupal_get_form('content_translation_delete_confirm', $entity, $language);
+  }
+
+}
diff --git c/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php w/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php
new file mode 100644
index 0000000..91ff885
--- /dev/null
+++ w/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php
@@ -0,0 +1,79 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\content_translation\Routing\ContentTranslationRouteSubscriber.
+ */
+
+namespace Drupal\content_translation\Routing;
+
+use Drupal\Core\Routing\RouteBuildEvent;
+use Drupal\Core\Routing\RoutingEvents;
+use Drupal\Core\Entity\EntityManager;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Subscriber for entity translation routes.
+ */
+class ContentTranslationRouteSubscriber implements EventSubscriberInterface {
+
+  /**
+   * The entity type manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManager
+   */
+  protected $entityManager;
+
+  /**
+   * Constructs a ContentTranslationRouteSubscriber object.
+   *
+   * @param \Drupal\Core\Entity\EntityManager $entityManager
+   *   The entity type manager.
+   */
+  public function __construct(EntityManager $entityManager) {
+    $this->entityManager = $entityManager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[RoutingEvents::DYNAMIC] = 'routes';
+    return $events;
+  }
+
+  /**
+   * Adds routes for entity translations.
+   */
+  public function routes(RouteBuildEvent $event) {
+    $collection = $event->getRouteCollection();
+    foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) {
+      if ($entity_info['translatable'] && isset($entity_info['translation'])) {
+        $route = new Route(
+          '/' . str_replace($entity_info['menu_path_wildcard'], '{entity}', $entity_info['menu_base_path']) . "/translations/delete/{language}",
+          array(
+            '_content' => '\Drupal\content_translation\Form\ContentTranslationForm::deleteTranslation',
+            'language' => NULL,
+            '_title' => 'Delete',
+          ),
+          array(
+            '_permission' => 'translate any entity',
+            '_access_content_translation_manage' => 'delete',
+          ),
+          array(
+            'parameters' => array(
+              'entity' => array(
+                'type' => 'entity:' . $entity_type,
+              ),
+              'language' => array(
+                'type' => 'language',
+              ),
+            ),
+          )
+        );
+        $collection->add("content_translation.delete_$entity_type", $route);
+      }
+    }
+  }
+}
diff --git c/core/modules/language/language.module w/core/modules/language/language.module
index 6031e33..52c14c9 100644
--- c/core/modules/language/language.module
+++ w/core/modules/language/language.module
@@ -92,11 +92,8 @@ function language_menu() {
   // Language negotiation.
   $items['admin/config/regional/language/detection'] = array(
     'title' => 'Detection and selection',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('language_negotiation_configure_form'),
-    'access arguments' => array('administer languages'),
+    'route_name' => 'language.negotiation',
     'weight' => 10,
-    'file' => 'language.admin.inc',
     'type' => MENU_LOCAL_TASK,
   );
   $items['admin/config/regional/language/detection/url'] = array(
diff --git c/core/modules/language/language.routing.yml w/core/modules/language/language.routing.yml
index ae980ec..a2628e6 100644
--- c/core/modules/language/language.routing.yml
+++ w/core/modules/language/language.routing.yml
@@ -61,3 +61,11 @@ language.negotiation_browser_delete:
     _form: '\Drupal\language\Form\NegotiationBrowserDeleteForm'
   requirements:
     _permission: 'administer languages'
+
+language.negotiation:
+  path: '/admin/config/regional/language/detection'
+  defaults:
+    _content: '\Drupal\language\Form\LanguageForm::negotiation'
+    _title: 'Detection and selection'
+  requirements:
+    _permission: 'administer languages'
diff --git c/core/modules/language/lib/Drupal/language/Form/LanguageForm.php w/core/modules/language/lib/Drupal/language/Form/LanguageForm.php
new file mode 100644
index 0000000..17773ff
--- /dev/null
+++ w/core/modules/language/lib/Drupal/language/Form/LanguageForm.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\language\Form\LanguageForm.
+ */
+
+namespace Drupal\language\Form;
+
+/**
+ * Temporary form controller for language module.
+ */
+class LanguageForm {
+  /**
+   * Wraps language_negotiation_configure_form().
+   *
+   * @see language_negotiation_configure_form()
+   */
+  public function negotiation() {
+    module_load_include('admin.inc', 'language');
+    return drupal_get_form('language_negotiation_configure_form');
+  }
+
+}
diff --git c/core/modules/locale/lib/Drupal/locale/Form/LocaleForm.php w/core/modules/locale/lib/Drupal/locale/Form/LocaleForm.php
new file mode 100644
index 0000000..733dca7
--- /dev/null
+++ w/core/modules/locale/lib/Drupal/locale/Form/LocaleForm.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\locale\Form\LocaleForm.
+ */
+
+namespace Drupal\locale\Form;
+
+/**
+ * Temporary form controller for locale module.
+ */
+class LocaleForm {
+  /**
+   * Wraps locale_translate_import_form().
+   *
+   * @see locale_translate_import_form()
+   */
+  public function import() {
+    module_load_include('bulk.inc', 'locale');
+    return drupal_get_form('locale_translate_import_form');
+  }
+
+  /**
+   * Wraps locale_translate_export_form().
+   *
+   * @see locale_translate_export_form()
+   */
+  public function export() {
+    module_load_include('bulk.inc', 'locale');
+    return drupal_get_form('locale_translate_export_form');
+  }
+
+  /**
+   * Wraps locale_translation_status_form().
+   *
+   * @see locale_translation_status_form()
+   */
+  public function status() {
+    module_load_include('pages.inc', 'locale');
+    return drupal_get_form('locale_translation_status_form');
+  }
+
+}
diff --git c/core/modules/locale/locale.module w/core/modules/locale/locale.module
index f426670..6ba156d 100644
--- c/core/modules/locale/locale.module
+++ w/core/modules/locale/locale.module
@@ -182,21 +182,15 @@ function locale_menu() {
   );
   $items['admin/config/regional/translate/import'] = array(
     'title' => 'Import',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('locale_translate_import_form'),
-    'access arguments' => array('translate interface'),
+    'route_name' => 'locale.translate_import',
     'weight' => 20,
     'type' => MENU_LOCAL_TASK,
-    'file' => 'locale.bulk.inc',
   );
   $items['admin/config/regional/translate/export'] = array(
     'title' => 'Export',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('locale_translate_export_form'),
-    'access arguments' => array('translate interface'),
+    'route_name' => 'locale.translate_export',
     'weight' => 30,
     'type' => MENU_LOCAL_TASK,
-    'file' => 'locale.bulk.inc',
   );
   $items['admin/config/regional/translate/settings'] = array(
     'title' => 'Settings',
@@ -206,11 +200,8 @@ function locale_menu() {
   );
   $items['admin/reports/translations'] = array(
     'title' => 'Available translation updates',
+    'route_name' => 'locale.translate_status',
     'description' => 'Get a status report about available interface translations for your installed modules and themes.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('locale_translation_status_form'),
-    'access arguments' => array('translate interface'),
-    'file' => 'locale.pages.inc',
   );
 
   return $items;
diff --git c/core/modules/locale/locale.routing.yml w/core/modules/locale/locale.routing.yml
index 7b08569..cc60aec 100644
--- c/core/modules/locale/locale.routing.yml
+++ w/core/modules/locale/locale.routing.yml
@@ -18,3 +18,27 @@ locale.translate_page:
     _content: 'Drupal\locale\Controller\LocaleController::translatePage'
   requirements:
     _permission: 'translate interface'
+
+locale.translate_import:
+  path: '/admin/config/regional/translate/import'
+  defaults:
+    _content: '\Drupal\locale\Form\LocaleForm::import'
+    _title: 'Import'
+  requirements:
+    _permission: 'translate interface'
+
+locale.translate_export:
+  path: '/admin/config/regional/translate/export'
+  defaults:
+    _content: '\Drupal\locale\Form\LocaleForm::export'
+    _title: 'Export'
+  requirements:
+    _permission: 'translate interface'
+
+locale.translate_status:
+  path: '/admin/reports/translations'
+  defaults:
+    _content: '\Drupal\locale\Form\LocaleForm::status'
+    _title: 'Available translation updates'
+  requirements:
+    _permission: 'translate interface'
diff --git c/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutForm.php w/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutForm.php
new file mode 100644
index 0000000..030fa0a
--- /dev/null
+++ w/core/modules/shortcut/lib/Drupal/shortcut/Form/ShortcutForm.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\shortcut\Form\ShortcutForm.
+ */
+
+namespace Drupal\shortcut\Form;
+
+use Drupal\menu_link\Entity\MenuLinkInterface;
+use Drupal\shortcut\ShortcutSetInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Temporary form controller for shortcut module.
+ */
+class ShortcutForm {
+  /**
+   * Wraps shortcut_link_edit().
+   *
+   * @see shortcut_link_edit()
+   */
+  public function edit(MenuLinkInterface $menu_link) {
+    module_load_include('admin.inc', 'shortcut');
+    return drupal_get_form('shortcut_link_edit', $menu_link);
+  }
+
+  /**
+   * Wraps shortcut_link_add().
+   *
+   * @see shortcut_link_add()
+   */
+  public function add(ShortcutSetInterface $shortcut_set) {
+    module_load_include('admin.inc', 'shortcut');
+    return drupal_get_form('shortcut_link_add', $shortcut_set);
+  }
+
+  /**
+   * Wraps shortcut_set_switch().
+   *
+   * @see shortcut_set_switch()
+   */
+  public function overview(UserInterface $user) {
+    module_load_include('admin.inc', 'shortcut');
+    return drupal_get_form('shortcut_set_switch', $user);
+  }
+
+}
diff --git c/core/modules/shortcut/shortcut.module w/core/modules/shortcut/shortcut.module
index e47b5ed..1368558 100644
--- c/core/modules/shortcut/shortcut.module
+++ w/core/modules/shortcut/shortcut.module
@@ -117,20 +117,12 @@ function shortcut_menu() {
   );
   $items['admin/config/user-interface/shortcut/manage/%shortcut_set/add-link'] = array(
     'title' => 'Add shortcut',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('shortcut_link_add', 5),
-    'access callback' => 'shortcut_set_edit_access',
-    'access arguments' => array(5),
+    'route_name' => 'shortcut.link_edit',
     'type' => MENU_LOCAL_ACTION,
-    'file' => 'shortcut.admin.inc',
   );
   $items['admin/config/user-interface/shortcut/link/%menu_link'] = array(
     'title' => 'Edit shortcut',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('shortcut_link_edit', 5),
-    'access callback' => 'shortcut_link_access',
-    'access arguments' => array(5),
-    'file' => 'shortcut.admin.inc',
+    'route_name' => 'shortcut.link_edit',
   );
   $items['admin/config/user-interface/shortcut/link/%menu_link/delete'] = array(
     'title' => 'Delete shortcut',
@@ -138,12 +130,8 @@ function shortcut_menu() {
   );
   $items['user/%user/shortcuts'] = array(
     'title' => 'Shortcuts',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('shortcut_set_switch', 1),
-    'access callback' => 'shortcut_set_switch_access',
-    'access arguments' => array(1),
+    'route_name' => 'shortcut.overview',
     'type' => MENU_LOCAL_TASK,
-    'file' => 'shortcut.admin.inc',
   );
 
   return $items;
diff --git c/core/modules/shortcut/shortcut.routing.yml w/core/modules/shortcut/shortcut.routing.yml
index 204ce81..9071330 100644
--- c/core/modules/shortcut/shortcut.routing.yml
+++ w/core/modules/shortcut/shortcut.routing.yml
@@ -46,3 +46,32 @@ shortcut.set_customize:
     _entity_form: 'shortcut_set.customize'
   requirements:
     _entity_access: 'shortcut_set.update'
+
+shortcut.link_add:
+  path: '/admin/config/user-interface/shortcut/manage/{shortcut_set}/add-link'
+  defaults:
+    _content: '\Drupal\shortcut\Form\ShortcutForm::add'
+    _title: 'Add Shortcut'
+  requirements:
+    _access: 'TRUE'
+
+shortcut.link_edit:
+  path: '/admin/config/user-interface/shortcut/link/{menu_link}'
+  defaults:
+    _content: '\Drupal\shortcut\Form\ShortcutForm::edit'
+    _title: 'Add Shortcut'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _access: 'TRUE'
+
+shortcut.overview:
+  path: 'user/{user}/shortcuts'
+  defaults:
+    _content: '\Drupal\shortcut\Form\ShortcutForm::overview'
+    _title: 'Add Shortcut'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _access: 'TRUE'
+
diff --git c/core/modules/system/lib/Drupal/system/Form/SystemForm.php w/core/modules/system/lib/Drupal/system/Form/SystemForm.php
new file mode 100644
index 0000000..e3b4021
--- /dev/null
+++ w/core/modules/system/lib/Drupal/system/Form/SystemForm.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\system\Form\SystemForm.
+ */
+
+namespace Drupal\system\Form;
+
+/**
+ * Temporary form controller for system module.
+ */
+class SystemForm {
+  /**
+   * Wraps system_date_format_localize_form().
+   *
+   * @see system_date_format_localize_form()
+   */
+  public function localizeDateFormat($langcode) {
+    module_load_include('admin.inc', 'system');
+    return drupal_get_form('system_date_format_localize_form', $langcode);
+  }
+
+}
diff --git c/core/modules/system/system.module w/core/modules/system/system.module
index f62f640..a7db847 100644
--- c/core/modules/system/system.module
+++ w/core/modules/system/system.module
@@ -909,11 +909,8 @@ function system_menu() {
     );
     $items['admin/config/regional/date-time/locale/%/edit'] = array(
       'title' => 'Localize date formats',
+      'route_name' => 'system.localize_date_format',
       'description' => 'Configure date formats for each locale',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('system_date_format_localize_form', 5),
-      'access arguments' => array('administer site configuration'),
-      'file' => 'system.admin.inc',
     );
     $items['admin/config/regional/date-time/locale/%/reset'] = array(
       'title' => 'Reset date formats',
diff --git c/core/modules/system/system.routing.yml w/core/modules/system/system.routing.yml
index 4ad6509..f63dfa5 100644
--- c/core/modules/system/system.routing.yml
+++ w/core/modules/system/system.routing.yml
@@ -326,3 +326,11 @@ system.batch_page:
     _controller: '\Drupal\system\Controller\BatchController::batchPage'
   requirements:
     _access: 'TRUE'
+
+system.localize_date_format:
+  path: '/admin/config/regional/date-time/locale/{langcode}/edit'
+  defaults:
+    _content: '\Drupal\system\Form\SystemForm::localizeDateFormat'
+    _title: 'Localize date formats'
+  requirements:
+    _permission: 'administer site configuration'
diff --git c/core/modules/update/lib/Drupal/update/Access/UpdateManagerAccessCheck.php w/core/modules/update/lib/Drupal/update/Access/UpdateManagerAccessCheck.php
new file mode 100644
index 0000000..adc04c8
--- /dev/null
+++ w/core/modules/update/lib/Drupal/update/Access/UpdateManagerAccessCheck.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\update\Access\UpdateManagerAccessCheck.
+ */
+
+namespace Drupal\update\Access;
+
+use Drupal\Component\Utility\Settings;
+use Drupal\Core\Access\StaticAccessCheckInterface;
+use Symfony\Component\Routing\Route;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Determines whether allow authorized operations is set.
+ */
+class UpdateManagerAccessCheck implements StaticAccessCheckInterface {
+
+  /**
+   * Settings Service.
+   *
+   * @var \Drupal\Component\Utility\Settings
+   */
+  protected $settings;
+
+  /**
+   * Constructs a UpdateManagerAccessCheck object.
+   *
+   * @param \Drupal\update\updateManager $update_manager
+   *   update Manager Service.
+   */
+  public function __construct(Settings $settings) {
+    $this->settings = $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function appliesTo() {
+    return array('_access_update_manager');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(Route $route, Request $request) {
+    return $this->settings->get('allow_authorize_operations', TRUE) ? static::ALLOW : static::DENY;
+  }
+
+}
diff --git c/core/modules/update/lib/Drupal/update/Form/UpdateForm.php w/core/modules/update/lib/Drupal/update/Form/UpdateForm.php
new file mode 100644
index 0000000..9832c17
--- /dev/null
+++ w/core/modules/update/lib/Drupal/update/Form/UpdateForm.php
@@ -0,0 +1,83 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\update\Form\UpdateForm.
+ */
+
+namespace Drupal\update\Form;
+
+/**
+ * Temporary form controller for update module.
+ */
+class UpdateForm {
+  /**
+   * Wraps update_manager_install_form().
+   *
+   * @see update_manager_install_form()
+   */
+  public function reportInstall() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_install_form', 'report');
+  }
+
+  /**
+   * Wraps update_manager_update_form().
+   *
+   * @see update_manager_update_form()
+   */
+  public function reportUpdate() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_update_form', 'report');
+  }
+
+  /**
+   * Wraps update_manager_install_form().
+   *
+   * @see update_manager_install_form()
+   */
+  public function moduleInstall() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_install_form', 'module');
+  }
+
+  /**
+   * Wraps update_manager_update_form().
+   *
+   * @see update_manager_update_form()
+   */
+  public function moduleUpdate() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_update_form', 'module');
+  }
+
+  /**
+   * Wraps update_manager_install_form().
+   *
+   * @see update_manager_install_form()
+   */
+  public function themeInstall() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_install_form', 'theme');
+  }
+
+  /**
+   * Wraps update_manager_update_form().
+   *
+   * @see update_manager_update_form()
+   */
+  public function themeUpdate() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_update_form', 'theme');
+  }
+
+  /**
+   * Wraps update_manager_update_ready_form().
+   *
+   * @see update_manager_update_ready_form()
+   */
+  public function confirmUpdates() {
+    module_load_include('manager.inc', 'update');
+    return drupal_get_form('update_manager_update_ready_form');
+  }
+
+}
diff --git c/core/modules/update/update.module w/core/modules/update/update.module
index 0210c01..3960f05 100644
--- c/core/modules/update/update.module
+++ w/core/modules/update/update.module
@@ -194,23 +194,15 @@ function update_menu() {
   );
   foreach ($paths as $context => $path) {
     $items[$path . '/install'] = array(
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('update_manager_install_form', $context),
-      'access callback' => 'update_manager_access',
-      'access arguments' => array(),
+      'route_name' => "update.{$context}_install",
       'weight' => 25,
       'type' => MENU_LOCAL_ACTION,
-      'file' => 'update.manager.inc',
     );
     $items[$path . '/update'] = array(
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('update_manager_update_form', $context),
-      'access callback' => 'update_manager_access',
-      'access arguments' => array(),
+      'route_name' => "update.{$context}_update",
       'weight' => 10,
       'title' => 'Update',
       'type' => MENU_LOCAL_TASK,
-      'file' => 'update.manager.inc',
     );
   }
   // Customize the titles of the action links depending on where they appear.
@@ -219,18 +211,6 @@ function update_menu() {
   $items['admin/modules/install'] += array('title' => 'Install new module');
   $items['admin/appearance/install'] += array('title' => 'Install new theme');
 
-  // Menu callback used for the confirmation page after all the releases
-  // have been downloaded, asking you to backup before installing updates.
-  $items['admin/update/ready'] = array(
-    'title' => 'Ready to update',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('update_manager_update_ready_form'),
-    'access callback' => 'update_manager_access',
-    'access arguments' => array(),
-    'type' => MENU_CALLBACK,
-    'file' => 'update.manager.inc',
-  );
-
   return $items;
 }
 
diff --git c/core/modules/update/update.routing.yml w/core/modules/update/update.routing.yml
index f6bd120..0727bfb 100644
--- c/core/modules/update/update.routing.yml
+++ w/core/modules/update/update.routing.yml
@@ -11,3 +11,77 @@ update.status:
     _content: '\Drupal\update\Controller\UpdateController::updateStatus'
   requirements:
     _permission: 'administer site configuration'
+
+update.report_install:
+  path: '/admin/reports/updates/install'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::reportInstall'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.report_update:
+  path: '/admin/reports/updates/update'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::reportUpdate'
+    _title: 'Update'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.module_install:
+  path: '/admin/modules/install'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::moduleInstall'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.module_update:
+  path: '/admin/modules/update'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::moduleUpdate'
+    _title: 'Update'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.theme_install:
+  path: '/admin/theme/install'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::themeInstall'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.theme_update:
+  path: '/admin/theme/update'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::themeUpdate'
+    _title: 'Update'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
+
+update.confirmation_page:
+  path: '/admin/update/ready'
+  defaults:
+    _content: '\Drupal\update\Form\UpdateForm::confirmUpdates'
+    _title: 'Ready to update'
+  options:
+    _access_checks: 'ALL'
+  requirements:
+    _permission: 'administer software updates'
+    _access_update_manager: 'TRUE'
diff --git c/core/modules/update/update.services.yml w/core/modules/update/update.services.yml
new file mode 100644
index 0000000..0ffafc2
--- /dev/null
+++ w/core/modules/update/update.services.yml
@@ -0,0 +1,6 @@
+services:
+  access_check.update.manager_access:
+    class: Drupal\update\Access\UpdateManagerAccessCheck
+    arguments: ['@settings']
+    tags:
+      - { name: access_check }
diff --git c/core/modules/user/lib/Drupal/user/Form/UserForm.php w/core/modules/user/lib/Drupal/user/Form/UserForm.php
new file mode 100644
index 0000000..18744cc
--- /dev/null
+++ w/core/modules/user/lib/Drupal/user/Form/UserForm.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\user\Form\UserForm.
+ */
+
+namespace Drupal\user\Form;
+
+/**
+ * Temporary form controller for user module.
+ */
+class UserForm {
+  /**
+   * Wraps user_pass_reset().
+   *
+   * @see user_pass_reset()
+   */
+  public function resetPass($uid, $timestamp, $hash, $operation) {
+    module_load_include('pages.inc', 'user');
+    return drupal_get_form('user_pass_reset', $uid, $timestamp, $hash, $operation);
+  }
+
+}
diff --git c/core/modules/user/user.module w/core/modules/user/user.module
index 3bc4534..9ca5d09 100644
--- c/core/modules/user/user.module
+++ w/core/modules/user/user.module
@@ -759,14 +759,6 @@ function user_menu() {
     'route_name' => 'user.pass',
     'type' => MENU_LOCAL_TASK,
   );
-  $items['user/reset/%/%/%'] = array(
-    'title' => 'Reset password',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('user_pass_reset', 2, 3, 4),
-    'access callback' => TRUE,
-    'type' => MENU_CALLBACK,
-    'file' => 'user.pages.inc',
-  );
 
   $items['user/logout'] = array(
     'title' => 'Log out',
diff --git c/core/modules/user/user.routing.yml w/core/modules/user/user.routing.yml
index 22b6c5e..9b60814 100644
--- c/core/modules/user/user.routing.yml
+++ w/core/modules/user/user.routing.yml
@@ -132,3 +132,12 @@ user.cancel_confirm:
     _entity_form: 'user.cancel'
   requirements:
     _entity_access: 'user.delete'
+
+user.reset:
+  path: '/user/reset/{uid}/{timestamp}/{hash}/{operation}'
+  defaults:
+    _content: '\Drupal\user\Form\UserForm::resetPass'
+    _title: 'Reset password'
+    operation: NULL
+  requirements:
+    _access: 'TRUE'
