diff --git a/core/lib/Drupal/Core/Entity/ContentEntityConfirmFormBase.php b/core/lib/Drupal/Core/Entity/ContentEntityConfirmFormBase.php
index a174e31..dfd44ad 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityConfirmFormBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityConfirmFormBase.php
@@ -91,4 +91,12 @@ protected function actions(array $form, array &$form_state) {
     return $actions;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function validate(array $form, array &$form_state) {
+    // Overwrite the default validation implementation as it is not necessary
+    // nor possible to validate an entity in a confirmation form.
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php
index 93b329a..c9959a5 100644
--- a/core/lib/Drupal/Core/Url.php
+++ b/core/lib/Drupal/Core/Url.php
@@ -122,13 +122,17 @@ public static function createFromPath($path) {
     else {
       // Look up the route name and parameters used for the given path.
       try {
+        // Path aliases are added on the request level (instead of the routing
+        // level), so we need to convert the path manually.
+        // @see \Drupal\Core\EventSubscriber\PathSubscriber
+        $path = \Drupal::service('path.alias_manager.cached')->getPathByAlias($path);
         $result = \Drupal::service('router')->match('/' . $path);
       }
       catch (ResourceNotFoundException $e) {
         throw new MatchingRouteNotFoundException(sprintf('No matching route could be found for the path "%s"', $path), 0, $e);
       }
       $route_name = $result[RouteObjectInterface::ROUTE_NAME];
-      $route_parameters = $result['_raw_variables']->all();
+      $route_parameters = isset($result['_raw_variables']) ? $result['_raw_variables']->all() : array();
     }
     return new static($route_name, $route_parameters);
   }
diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
index 850c19e..b4f1449 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\link\Plugin\Field\FieldType;
 
+use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\Core\TypedData\DataDefinition;
@@ -135,9 +136,36 @@ public function instanceSettingsForm(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
+  public function preSave() {
+    // Trim any spaces around the link text.
+    $this->title = trim($this->title);
+
+    $parsed_url = UrlHelper::parse(trim($this->url));
+    $this->url = $parsed_url['path'];
+    $this->options = ($this->options) ?: array();
+
+    // The link 'query' and 'fragment' parts need to be split and updated only
+    // if they exist (e.g. when the 'url' property is new or updated).
+    $options = array();
+    if (!empty($parsed_url['query'])) {
+      $options['query'] = $parsed_url['query'];
+    }
+    if (!empty($parsed_url['fragment'])) {
+      $options['fragment'] = $parsed_url['fragment'];
+    }
+    $this->options = $options + $this->options;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function isEmpty() {
-    $value = $this->get('url')->getValue();
-    return $value === NULL || $value === '';
+    if ($this->isExternal()) {
+      return $this->url === NULL || $this->url === '';
+    }
+    else {
+      return $this->route_name === NULL || $this->route_name === '';
+    }
   }
 
   /**
@@ -147,4 +175,19 @@ public function isExternal() {
     // External links don't have a route_name value.
     return empty($this->route_name);
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setValue($values, $notify = TRUE) {
+    // Unserialize the values.
+    // @todo The storage controller should take care of this.
+    foreach (array('route_parameters', 'options') as $property) {
+      if (isset($values[$property]) && is_string($values[$property])) {
+        $values[$property] = unserialize($values[$property]);
+      }
+    }
+    parent::setValue($values, $notify);
+  }
+
 }
diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldWidget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldWidget/LinkWidget.php
index 6550a0e..995241b 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldWidget/LinkWidget.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldWidget/LinkWidget.php
@@ -219,8 +219,6 @@ public function massageFormValues(array $values, array $form, array &$form_state
           $url->setOption('attributes', $value['attributes']);
 
           $value += $url->toArray();
-          // Reset the URL value to contain only the path.
-          $value['url'] = $parsed_url['path'];
         }
         catch (NotFoundHttpException $e) {
           // Nothing to do here, LinkTypeConstraintValidator emits errors.
diff --git a/core/modules/shortcut/shortcut.info.yml b/core/modules/shortcut/shortcut.info.yml
index dde0e9c..8293685 100644
--- a/core/modules/shortcut/shortcut.info.yml
+++ b/core/modules/shortcut/shortcut.info.yml
@@ -5,3 +5,5 @@ package: Core
 version: VERSION
 core: 8.x
 configure: shortcut.set_admin
+dependencies:
+  - link
diff --git a/core/modules/shortcut/shortcut.install b/core/modules/shortcut/shortcut.install
index b7ed49c..6c6917f 100644
--- a/core/modules/shortcut/shortcut.install
+++ b/core/modules/shortcut/shortcut.install
@@ -5,9 +5,6 @@
  * Install, update and uninstall functions for the shortcut module.
  */
 
-use Drupal\Core\Database\Database;
-use Drupal\Core\Language\Language;
-
 /**
  * Implements hook_schema().
  */
@@ -46,13 +43,21 @@ function shortcut_schema() {
         'not null' => TRUE,
         'default' => 0,
       ),
-      'route_name' => array(
-        'description' => 'The machine name of a defined Symfony Route this menu item represents.',
+      'link__route_name' => array(
+        'description' => 'The machine name of a defined Route this link represents.',
         'type' => 'varchar',
         'length' => 255,
+        'not null' => FALSE,
+      ),
+      'link__route_parameters' => array(
+        'description' => 'Serialized array of route parameters of the link.',
+        'type' => 'blob',
+        'size' => 'big',
+        'not null' => FALSE,
+        'serialize' => TRUE,
       ),
-      'route_parameters' => array(
-        'description' => 'Serialized array of route parameters of this shortcut.',
+      'link__options' => array(
+        'description' => 'Serialized array of options for the link.',
         'type' => 'blob',
         'size' => 'big',
         'not null' => FALSE,
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index 09ead75..2b074db 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -289,10 +289,10 @@ function shortcut_renderable_links($shortcut_set = NULL) {
   $shortcuts = \Drupal::entityManager()->getStorage('shortcut')->loadByProperties(array('shortcut_set' => $shortcut_set->id()));
   $all_cache_tags = array();
   foreach ($shortcuts as $shortcut) {
-    $links[] = array(
-      'title' => $shortcut->label(),
-      'href' => $shortcut->path->value,
-    );
+    $links[$shortcut->id()] = array(
+      'type' => 'link',
+      'title' => $shortcut->getTitle(),
+    ) + $shortcut->getUrl()->toArray();
     $all_cache_tags[] = $shortcut->getCacheTag();
   }
 
diff --git a/core/modules/shortcut/src/Controller/ShortcutSetController.php b/core/modules/shortcut/src/Controller/ShortcutSetController.php
index e63e027..3a1db6a 100644
--- a/core/modules/shortcut/src/Controller/ShortcutSetController.php
+++ b/core/modules/shortcut/src/Controller/ShortcutSetController.php
@@ -8,6 +8,7 @@
 namespace Drupal\shortcut\Controller;
 
 use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Url;
 use Drupal\shortcut\ShortcutSetInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -39,7 +40,9 @@ public function addShortcutLinkInline(ShortcutSetInterface $shortcut_set, Reques
       $shortcut = $this->entityManager()->getStorage('shortcut')->create(array(
         'title' => $name,
         'shortcut_set' => $shortcut_set->id(),
-        'path' => $link,
+        'link' => array(
+          'url' => $link,
+        ) + Url::createFromPath($link)->toArray(),
       ));
 
       try {
diff --git a/core/modules/shortcut/src/Entity/Shortcut.php b/core/modules/shortcut/src/Entity/Shortcut.php
index 03be8c8..34541e3 100644
--- a/core/modules/shortcut/src/Entity/Shortcut.php
+++ b/core/modules/shortcut/src/Entity/Shortcut.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Url;
+use Drupal\link\LinkItemInterface;
 use Drupal\shortcut\ShortcutInterface;
 
 /**
@@ -63,7 +64,7 @@ public function getTitle() {
    */
   public function setTitle($link_title) {
     $this->set('title', $link_title);
-   return $this;
+    return $this;
   }
 
   /**
@@ -85,14 +86,14 @@ public function setWeight($weight) {
    * {@inheritdoc}
    */
   public function getRouteName() {
-    return $this->get('route_name')->value;
+    return $this->get('link')->route_name;
   }
 
   /**
    * {@inheritdoc}
    */
   public function setRouteName($route_name) {
-    $this->set('route_name', $route_name);
+    $this->get('link')->route_name = $route_name;
     return $this;
   }
 
@@ -100,37 +101,33 @@ public function setRouteName($route_name) {
    * {@inheritdoc}
    */
   public function getRouteParams() {
-    return $this->get('route_parameters')->first()->getValue();
+    return $this->get('link')->route_parameters;
   }
 
   /**
    * {@inheritdoc}
    */
   public function setRouteParams($route_parameters) {
-    $this->set('route_parameters', array($route_parameters));
+    $this->get('link')->route_parameters = $route_parameters;
     return $this;
   }
 
   /**
    * {@inheritdoc}
    */
-  public static function preCreate(EntityStorageInterface $storage, array &$values) {
-    parent::preCreate($storage, $values);
-
-    if (!isset($values['shortcut_set'])) {
-      $values['shortcut_set'] = 'default';
-    }
+  public function getUrl() {
+    return new Url($this->link->route_name, (array) $this->link->route_parameters, (array) $this->link->options);
   }
 
   /**
    * {@inheritdoc}
    */
-  public function preSave(EntityStorageInterface $storage) {
-    parent::preSave($storage);
+  public static function preCreate(EntityStorageInterface $storage, array &$values) {
+    parent::preCreate($storage, $values);
 
-    $url = Url::createFromPath($this->path->value);
-    $this->setRouteName($url->getRouteName());
-    $this->setRouteParams($url->getRouteParameters());
+    if (!isset($values['shortcut_set'])) {
+      $values['shortcut_set'] = 'default';
+    }
   }
 
   /**
@@ -190,13 +187,22 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setLabel(t('Weight'))
       ->setDescription(t('Weight among shortcuts in the same shortcut set.'));
 
-    $fields['route_name'] = FieldDefinition::create('string')
-      ->setLabel(t('Route name'))
-      ->setDescription(t('The machine name of a defined Route this shortcut represents.'));
-
-    $fields['route_parameters'] = FieldDefinition::create('map')
-      ->setLabel(t('Route parameters'))
-      ->setDescription(t('A serialized array of route parameters of this shortcut.'));
+    $fields['link'] = FieldDefinition::create('link')
+      ->setLabel(t('Path'))
+      ->setDescription(t('The location this shortcut points to.'))
+      ->setRequired(TRUE)
+      ->setTranslatable(FALSE)
+      ->setSettings(array(
+        'default_value' => '',
+        'max_length' => 560,
+        'link_type' => LinkItemInterface::LINK_INTERNAL,
+        'title' => DRUPAL_DISABLED,
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'link',
+        'weight' => 0,
+      ))
+      ->setDisplayConfigurable('form', TRUE);
 
     $fields['langcode'] = FieldDefinition::create('language')
       ->setLabel(t('Language code'))
@@ -206,15 +212,6 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
       ->setLabel(t('Default language'))
       ->setDescription(t('Flag to indicate whether this is the default language.'));
 
-    $fields['path'] = FieldDefinition::create('string')
-      ->setLabel(t('Path'))
-      ->setDescription(t('The computed shortcut path.'))
-      ->setComputed(TRUE);
-
-    $item_definition = $fields['path']->getItemDefinition();
-    $item_definition->setClass('\Drupal\shortcut\ShortcutPathItem');
-    $fields['path']->setItemDefinition($item_definition);
-
     return $fields;
   }
 
diff --git a/core/modules/shortcut/src/Form/SetCustomize.php b/core/modules/shortcut/src/Form/SetCustomize.php
index 716f7ea..59e4148 100644
--- a/core/modules/shortcut/src/Form/SetCustomize.php
+++ b/core/modules/shortcut/src/Form/SetCustomize.php
@@ -51,7 +51,10 @@ public function form(array $form, array &$form_state) {
     foreach ($this->entity->getShortcuts() as $shortcut) {
       $id = $shortcut->id();
       $form['shortcuts']['links'][$id]['#attributes']['class'][] = 'draggable';
-      $form['shortcuts']['links'][$id]['name']['#markup'] = l($shortcut->getTitle(), $shortcut->path->value);
+      $form['shortcuts']['links'][$id]['name'] = array(
+        '#type' => 'link',
+        '#title' => $shortcut->getTitle(),
+      ) + $shortcut->getUrl()->toRenderArray();
       $form['shortcuts']['links'][$id]['#weight'] = $shortcut->getWeight();
       $form['shortcuts']['links'][$id]['weight'] = array(
         '#type' => 'weight',
diff --git a/core/modules/shortcut/src/Form/ShortcutDeleteForm.php b/core/modules/shortcut/src/Form/ShortcutDeleteForm.php
index 8802da7..13166ef 100644
--- a/core/modules/shortcut/src/Form/ShortcutDeleteForm.php
+++ b/core/modules/shortcut/src/Form/ShortcutDeleteForm.php
@@ -26,7 +26,7 @@ public function getFormId() {
    * {@inheritdoc}
    */
   public function getQuestion() {
-    return $this->t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->entity->title->value));
+    return $this->t('Are you sure you want to delete the shortcut %title?', array('%title' => $this->entity->getTitle()));
   }
 
   /**
diff --git a/core/modules/shortcut/src/ShortcutForm.php b/core/modules/shortcut/src/ShortcutForm.php
index 0e101ff..d69f816 100644
--- a/core/modules/shortcut/src/ShortcutForm.php
+++ b/core/modules/shortcut/src/ShortcutForm.php
@@ -28,15 +28,6 @@ class ShortcutForm extends ContentEntityForm {
   public function form(array $form, array &$form_state) {
     $form = parent::form($form, $form_state);
 
-    $form['path'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Path'),
-      '#size' => 40,
-      '#maxlength' => 255,
-      '#field_prefix' => $this->url('<front>', array(), array('absolute' => TRUE)),
-      '#default_value' => $this->entity->path->value,
-    );
-
     $form['langcode'] = array(
       '#title' => t('Language'),
       '#type' => 'language_select',
@@ -50,30 +41,6 @@ public function form(array $form, array &$form_state) {
   /**
    * {@inheritdoc}
    */
-  public function buildEntity(array $form, array &$form_state) {
-    $entity = parent::buildEntity($form, $form_state);
-
-    // Set the computed 'path' value so it can used in the preSave() method to
-    // derive the route name and parameters.
-    $entity->path->value = $form_state['values']['path'];
-
-    return $entity;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function validate(array $form, array &$form_state) {
-    if (!shortcut_valid_link($form_state['values']['path'])) {
-      $this->setFormError('path', $form_state, $this->t('The shortcut must correspond to a valid path on the site.'));
-    }
-
-    parent::validate($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
   public function save(array $form, array &$form_state) {
     $entity = $this->entity;
     $entity->save();
diff --git a/core/modules/shortcut/src/ShortcutInterface.php b/core/modules/shortcut/src/ShortcutInterface.php
index 6dc0be2..38fd28d 100644
--- a/core/modules/shortcut/src/ShortcutInterface.php
+++ b/core/modules/shortcut/src/ShortcutInterface.php
@@ -90,4 +90,12 @@ public function getRouteParams();
    */
   public function setRouteParams($route_parameters);
 
+  /**
+   * Returns the Url object for the link this shortcut points to.
+   *
+   * @return \Drupal\Core\Url
+   *   The Url object.
+   */
+  public function getUrl();
+
 }
diff --git a/core/modules/shortcut/src/ShortcutPathValue.php b/core/modules/shortcut/src/ShortcutPathValue.php
deleted file mode 100644
index 3d88d9b..0000000
--- a/core/modules/shortcut/src/ShortcutPathValue.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\shortcut\ShortcutPathValue.
- */
-
-namespace Drupal\shortcut;
-
-use Drupal\Core\TypedData\TypedData;
-
-/**
- * A computed property for the string value of the path field.
- */
-class ShortcutPathValue extends TypedData {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getValue() {
-    if (!isset($this->value)) {
-      if (!isset($this->parent)) {
-        throw new \InvalidArgumentException('Computed properties require context for computation.');
-      }
-
-      $entity = $this->parent->getEntity();
-      if ($route_name = $entity->getRouteName()) {
-        $path = \Drupal::urlGenerator()->getPathFromRoute($route_name, $entity->getRouteParams());
-        $this->value = trim($path, '/');
-      }
-      else {
-        $this->value = NULL;
-      }
-    }
-    return $this->value;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function setValue($value, $notify = TRUE) {
-    // Normalize the path in case it is an alias.
-    $value = \Drupal::service('path.alias_manager')->getPathByAlias($value);
-    if (empty($value)) {
-      $value = '<front>';
-    }
-
-    parent::setValue($value, $notify);
-  }
-
-}
diff --git a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
index cf2d732..d0187ea 100644
--- a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
@@ -44,7 +44,7 @@ public function testShortcutLinkAdd() {
 
     // Create some paths to test.
     $test_cases = array(
-      array('path' => ''),
+      array('path' => '<front>'),
       array('path' => 'admin'),
       array('path' => 'admin/config/system/site-information'),
       array('path' => 'node/' . $this->node->id() . '/edit'),
@@ -58,13 +58,16 @@ public function testShortcutLinkAdd() {
       $title = $this->randomName();
       $form_data = array(
         'title[0][value]' => $title,
-        'path' => $test['path'],
+        'link[0][url]' => $test['path'],
       );
       $this->drupalPostForm('admin/config/user-interface/shortcut/manage/' . $set->id() . '/add-link', $form_data, t('Save'));
       $this->assertResponse(200);
       $saved_set = ShortcutSet::load($set->id());
-      $paths = $this->getShortcutInformation($saved_set, 'path');
-      $this->assertTrue(in_array($this->container->get('path.alias_manager')->getPathByAlias($test['path']), $paths), 'Shortcut created: ' . $test['path']);
+      $paths = $this->getShortcutInformation($saved_set, 'link');
+      $test['path'] = $test['path'] != '<front>' ? $test['path'] : '';
+      debug($test['path']);
+      debug($paths);
+      $this->assertTrue(in_array($test['path'], $paths), 'Shortcut created: ' . $test['path']);
       $this->assertLink($title, 0, 'Shortcut link found on the page.');
     }
     $saved_set = ShortcutSet::load($set->id());
@@ -72,11 +75,11 @@ public function testShortcutLinkAdd() {
     $shortcuts = $saved_set->getShortcuts();
     foreach ($shortcuts as $entity) {
       // Test the node routes with parameters.
-      if (strpos($entity->route_name->value, 'node.') === 0) {
+      if (strpos($entity->link->route_name, 'node.') === 0) {
         $entity->save();
         $loaded = Shortcut::load($entity->id());
-        $this->assertEqual($entity->route_name->value, $loaded->route_name->value);
-        $this->assertEqual($entity->get('route_parameters')->first()->getValue(), $loaded->get('route_parameters')->first()->getValue());
+        $this->assertEqual($entity->link->route_name, $loaded->link->route_name);
+        $this->assertEqual($entity->link->route_parameters, $loaded->link->route_parameters);
       }
     }
   }
@@ -123,7 +126,7 @@ public function testShortcutLinkRename() {
 
     $shortcuts = $set->getShortcuts();
     $shortcut = reset($shortcuts);
-    $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title[0][value]' => $new_link_name, 'path' => $shortcut->path->value), t('Save'));
+    $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title[0][value]' => $new_link_name, 'link[0][url]' => ltrim($shortcut->getUrl()->toString(), '/')), t('Save'));
     $saved_set = ShortcutSet::load($set->id());
     $titles = $this->getShortcutInformation($saved_set, 'title');
     $this->assertTrue(in_array($new_link_name, $titles), 'Shortcut renamed: ' . $new_link_name);
@@ -141,9 +144,9 @@ public function testShortcutLinkChangePath() {
 
     $shortcuts = $set->getShortcuts();
     $shortcut = reset($shortcuts);
-    $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title[0][value]' => $shortcut->getTitle(), 'path' => $new_link_path), t('Save'));
+    $this->drupalPostForm('admin/config/user-interface/shortcut/link/' . $shortcut->id(), array('title[0][value]' => $shortcut->getTitle(), 'link[0][url]' => $new_link_path), t('Save'));
     $saved_set = ShortcutSet::load($set->id());
-    $paths = $this->getShortcutInformation($saved_set, 'path');
+    $paths = $this->getShortcutInformation($saved_set, 'link');
     $this->assertTrue(in_array($new_link_path, $paths), 'Shortcut path changed: ' . $new_link_path);
     $this->assertLinkByHref($new_link_path, 0, 'Shortcut with new path appears on the page.');
   }
diff --git a/core/modules/shortcut/src/Tests/ShortcutTestBase.php b/core/modules/shortcut/src/Tests/ShortcutTestBase.php
index 6d9e240..87403c3 100644
--- a/core/modules/shortcut/src/Tests/ShortcutTestBase.php
+++ b/core/modules/shortcut/src/Tests/ShortcutTestBase.php
@@ -59,7 +59,10 @@ function setUp() {
         'set' => 'default',
         'title' => t('Add content'),
         'weight' => -20,
-        'path' => 'node/add',
+        'link' => array(
+          'url' => 'node/add',
+          'route_name' => 'node.add_page',
+        ),
       ));
       $shortcut->save();
 
@@ -67,7 +70,10 @@ function setUp() {
         'set' => 'default',
         'title' => t('All content'),
         'weight' => -19,
-        'path' => 'admin/content',
+        'link' => array(
+          'url' => 'admin/content',
+          'route_name' => 'node.content_overview',
+        ),
       ));
       $shortcut->save();
     }
@@ -105,7 +111,7 @@ function generateShortcutSet($label = '', $id = NULL) {
    * @param string $key
    *   The array key indicating what information to extract from each link:
    *    - 'title': Extract shortcut titles.
-   *    - 'path': Extract shortcut paths.
+   *    - 'link': Extract shortcut paths.
    *    - 'id': Extract the shortcut ID.
    *
    * @return array
@@ -115,7 +121,12 @@ function getShortcutInformation(ShortcutSetInterface $set, $key) {
     $info = array();
     \Drupal::entityManager()->getStorage('shortcut')->resetCache();
     foreach ($set->getShortcuts() as $shortcut) {
-      $info[] = $shortcut->{$key}->value;
+      if ($key == 'link') {
+        $info[] = ltrim($shortcut->getUrl()->toString(), '/');
+      }
+      else {
+        $info[] = $shortcut->{$key}->value;
+      }
     }
     return $info;
   }
diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install
index 73ea074..18c9a29 100644
--- a/core/profiles/standard/standard.install
+++ b/core/profiles/standard/standard.install
@@ -56,7 +56,9 @@ function standard_install() {
     'shortcut_set' => 'default',
     'title' => t('Add content'),
     'weight' => -20,
-    'path' => 'node/add',
+    'link' => array(
+      'route_name' => 'node.add_page',
+    ),
   ));
   $shortcut->save();
 
@@ -64,7 +66,9 @@ function standard_install() {
     'shortcut_set' => 'default',
     'title' => t('All content'),
     'weight' => -19,
-    'path' => 'admin/content',
+    'link' => array(
+      'route_name' => 'node.content_overview',
+    ),
   ));
   $shortcut->save();
 
diff --git a/core/scripts/run-tests.sh b/core/scripts/run-tests.sh
index 643bcb7..552a512 100755
--- a/core/scripts/run-tests.sh
+++ b/core/scripts/run-tests.sh
@@ -878,6 +878,7 @@ function simpletest_script_get_test_list() {
     simpletest_script_print_error('No valid tests were specified.');
     exit;
   }
+  $test_list = array('\Drupal\shortcut\Tests\ShortcutLinksTest');
   return $test_list;
 }
 
diff --git a/core/tests/Drupal/Tests/Core/UrlTest.php b/core/tests/Drupal/Tests/Core/UrlTest.php
index 83e4c74..aaee399 100644
--- a/core/tests/Drupal/Tests/Core/UrlTest.php
+++ b/core/tests/Drupal/Tests/Core/UrlTest.php
@@ -33,6 +33,13 @@ class UrlTest extends UnitTestCase {
   protected $urlGenerator;
 
   /**
+   * The path alias manager.
+   *
+   * @var \Drupal\Core\Path\AliasManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $pathAliasManager;
+
+  /**
    * The router.
    *
    * @var \Drupal\Tests\Core\Routing\TestRouterInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -69,15 +76,31 @@ protected function setUp() {
     $map[] = array('node_edit', array('node' => '2'), array(), '/node/2/edit');
     $this->map = $map;
 
+    $alias_map = array(
+      // Set up one proper alias that can be resolved to a system path.
+      array('node-alias-test', NULL, 'node'),
+      // Passing in anything else should return the same string.
+      array('node', NULL, 'node'),
+      array('node/1', NULL, 'node/1'),
+      array('node/2/edit', NULL, 'node/2/edit'),
+      array('non-existent', NULL, 'non-existent'),
+    );
+
     $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
     $this->urlGenerator->expects($this->any())
       ->method('generateFromRoute')
       ->will($this->returnValueMap($this->map));
 
+    $this->pathAliasManager = $this->getMock('Drupal\Core\Path\AliasManagerInterface');
+    $this->pathAliasManager->expects($this->any())
+      ->method('getPathByAlias')
+      ->will($this->returnValueMap($alias_map));
+
     $this->router = $this->getMock('Drupal\Tests\Core\Routing\TestRouterInterface');
     $container = new ContainerBuilder();
     $container->set('router', $this->router);
     $container->set('url_generator', $this->urlGenerator);
+    $container->set('path.alias_manager.cached', $this->pathAliasManager);
     \Drupal::setContainer($container);
   }
 
@@ -125,6 +148,27 @@ public function testCreateFromPathFront() {
   }
 
   /**
+   * Tests the createFromPath method with a path alias.
+   *
+   * @covers ::createFromPath()
+   */
+  public function testCreateFromPathAlias() {
+    $this->router->expects($this->any())
+      ->method('match')
+      ->will($this->returnValueMap(array(
+        array('/node', array(
+          RouteObjectInterface::ROUTE_NAME => 'view.frontpage.page_1',
+          '_raw_variables' => new ParameterBag(),
+        )),
+      )));
+
+    $values = $this->map[0];
+    array_pop($values);
+    $url = Url::createFromPath('node-alias-test');
+    $this->assertSame($values, array_values($url->toArray()));
+  }
+
+  /**
    * Tests that an invalid path will thrown an exception.
    *
    * @covers ::createFromPath()
