diff --git a/core/modules/menu_link/config/schema/menu_link.schema.yml b/core/modules/menu_link/config/schema/menu_link.schema.yml
new file mode 100644
index 0000000..54b7a45
--- /dev/null
+++ b/core/modules/menu_link/config/schema/menu_link.schema.yml
@@ -0,0 +1,26 @@
+field.field_settings.menu_link:
+  type: mapping
+  label: 'Menu link settings'
+  mapping:
+    available_menus:
+      type: sequence
+      label: 'Available menus'
+      sequence:
+        - type: string
+    default_menu_parent:
+      type: string
+      label: 'Default menu parent'
+
+field.value.menu_link:
+  type: mapping
+  label: 'Default value'
+  mapping:
+    menu_name:
+      type: string
+      label: 'Value'
+    parent:
+      type: string
+      label: 'Text format'
+    weight:
+      type: integer
+      label: 'Weight'
diff --git a/core/modules/menu_link/menu_link.info.yml b/core/modules/menu_link/menu_link.info.yml
new file mode 100644
index 0000000..2c90e90
--- /dev/null
+++ b/core/modules/menu_link/menu_link.info.yml
@@ -0,0 +1,8 @@
+name: Menu link
+type: module
+description: 'Defines a menu link field type'
+package: Field types
+version: VERSION
+core: 8.x
+dependencies:
+  - field
diff --git a/core/modules/menu_link/menu_link.libraries.yml b/core/modules/menu_link/menu_link.libraries.yml
new file mode 100644
index 0000000..6610a24
--- /dev/null
+++ b/core/modules/menu_link/menu_link.libraries.yml
@@ -0,0 +1,8 @@
+menu_link.form:
+  version: VERSION
+  js:
+    js/menu_link.js: {}
+  dependencies:
+    - core/jquery
+    - core/drupal
+    - core/drupal.form
diff --git a/core/modules/menu_link/menu_link.module b/core/modules/menu_link/menu_link.module
new file mode 100644
index 0000000..5706fdd
--- /dev/null
+++ b/core/modules/menu_link/menu_link.module
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * @file
+ * Provides a menu link field.
+ */
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Implements hook_form_FORM_ID_alter().
+ */
+function menu_link_form_field_ui_field_storage_edit_form_alter(&$form, FormStateInterface $form_state) {
+  if ($form['#field']->getType() == 'menu_link') {
+    // We only support posting one menu link at a time.
+    // @todo - this is a hack and should be managed by the field definition.
+    // https://www.drupal.org/node/2403703
+    $form['field_storage']['cardinality_container']['cardinality']['#default_value'] = 1;
+    $form['field_storage']['cardinality_container']['#access'] = FALSE;
+  }
+}
\ No newline at end of file
diff --git a/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php b/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php
new file mode 100644
index 0000000..50ec814
--- /dev/null
+++ b/core/modules/menu_link/src/Plugin/Field/FieldType/MenuLinkItem.php
@@ -0,0 +1,288 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_link\Plugin\Field\FieldType\MenuLinkItem.
+ */
+
+namespace Drupal\menu_link\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\DataDefinitionInterface;
+use Drupal\Core\TypedData\TypedDataInterface;
+use Drupal\system\Entity\Menu;
+
+/**
+ * Defines a menu link field type which stores the link, parent and menu.
+ *
+ * @FieldType(
+ *   id = "menu_link",
+ *   label = @Translation("Menu link"),
+ *   description = @Translation("Stores a title, menu and parent to insert a link to the current entity."),
+ *   default_widget = "menu_link_default",
+ *   list_class = "\Drupal\menu_link\Plugin\Field\MenuLinkItemList",
+ * )
+ */
+class MenuLinkItem extends FieldItemBase {
+
+  /**
+   * The menu plugin manager.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkManagerInterface
+   */
+  protected $menuPluginManager;
+
+  /**
+   * The menu parent form selector.
+   *
+   * @var \Drupal\Core\Menu\MenuParentFormSelectorInterface
+   */
+  protected $menuParentFormSelector;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
+    parent::__construct($definition, $name, $parent);
+
+    $this->menuPluginManager = \Drupal::service('plugin.manager.menu.link');
+    $this->menuParentFormSelector = \Drupal::service('menu.parent_form_selector');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultFieldSettings() {
+    $settings = parent::defaultFieldSettings();
+
+    $settings['available_menus'] = ['main'];
+    $settings['default_menu_parent'] = 'main:';
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::fieldSettingsForm($form, $form_state);
+
+    $menu_options = $this->getMenuNames();
+
+    $form['available_menus'] = [
+      '#type' => 'checkboxes',
+      '#title' => $this->t('Available menus'),
+      '#default_value' => $this->getSetting('available_menus'),
+      '#options' => $menu_options,
+      '#description' => $this->t('The menus available to place links in for this kind of entity.'),
+      '#required' => TRUE,
+    ];
+
+    $parent_options = [];
+    // Make sure the setting is normalized to an associative array.
+    $available_menus = array_filter($this->getSetting('available_menus'));
+    $available_menus = array_combine($available_menus, $available_menus);
+    foreach ($available_menus as $name) {
+      if (isset($menu_options[$name])) {
+        $parent_options["$name:"] = $menu_options[$name];
+      }
+    }
+    $form['default_menu_parent'] = [
+      '#type' => 'select',
+      '#title' => $this->t('Default menu for new links'),
+      '#default_value' => $this->getSetting('default_menu_parent'),
+      '#options' => $parent_options,
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+    $definitions = [];
+
+    $definitions['menu_name'] = DataDefinition::create('string')
+      ->setLabel(t('Menu'));
+    $definitions['title'] = DataDefinition::create('string')
+      ->setLabel(t('Menu link title'));
+    $definitions['description'] = DataDefinition::create('string')
+      ->setLabel(t('Menu link description'));
+    $definitions['parent'] = DataDefinition::create('string')
+      ->setLabel(t('Menu link parent'));
+    $definitions['weight'] = DataDefinition::create('integer')
+      ->setLabel(t('Menu link weight'));
+
+    return $definitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    $schema = [];
+
+    $schema['columns']['menu_name'] = [
+      'description' => 'The menu of the link',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => FALSE,
+    ];
+
+    $schema['columns']['title'] = [
+      'description' => 'The menu link text.',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => FALSE,
+    ];
+
+    $schema['columns']['description'] = [
+      'description' => 'The description of the menu link.',
+      'type' => 'blob',
+      'size' => 'big',
+      'not null' => FALSE,
+    ];
+
+    $schema['columns']['parent'] = [
+      'description' => 'The parent of the menu link',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => FALSE,
+    ];
+
+    $schema['columns']['weight'] = [
+      'description' => 'The weight of the menu link',
+      'type' => 'int',
+    ];
+
+    return $schema;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function insert() {
+    parent::insert();
+
+    $this->doSave();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function update() {
+    parent::update();
+
+    $this->doSave();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function delete() {
+    parent::delete();
+
+    $plugin_id = $this->getMenuPluginId();
+    if ($this->menuPluginManager->hasDefinition($plugin_id)) {
+      $this->menuPluginManager->removeDefinition($plugin_id, FALSE);
+    }
+  }
+
+  /**
+   * Saves the plugin definition.
+   */
+  protected function doSave() {
+    // We only update the menu link definition when working with the original
+    // language value of the field, otherwise, we can never properly update or
+    // remove the menu link.
+    // @todo - use the FieldTranslationSynchronizer
+    // https://www.drupal.org/node/2403455
+    if ($this->getLangcode() != $this->getEntity()->getUntranslated()->language()->getId()) {
+      return;
+    }
+    $plugin_id = $this->getMenuPluginId();
+
+    // When the entity is saved via a plugin instance, we should not call the
+    // menu tree manager to update the definition a second time.
+    if ($menu_plugin_definition = $this->getMenuPluginDefinition()) {
+      if (!$this->menuPluginManager->hasDefinition($plugin_id)) {
+        $this->menuPluginManager->addDefinition($plugin_id, $this->getMenuPluginDefinition());
+      }
+      else {
+        $this->menuPluginManager->updateDefinition($plugin_id, $this->getMenuPluginDefinition(), FALSE);
+      }
+    }
+    else {
+      $this->menuPluginManager->removeDefinition($plugin_id, FALSE);
+    }
+  }
+
+  /**
+   * Generates the plugin ID for the associated menu link.
+   *
+   * @return string
+   *   The Plugin ID.
+   */
+  public function getMenuPluginId() {
+    $field_name = $this->definition->getFieldDefinition()->getName();
+    $entity_type_id = $this->getEntity()->getEntityTypeId();
+    return 'menu_link_field:' . "{$entity_type_id}_{$field_name}_{$this->getEntity()->uuid()}";
+  }
+
+  /**
+   * Generates the plugin definition of the associated menu link.
+   *
+   * @return array|FALSE
+   *   The menu plugin definition, otherwise FALSE.
+   */
+  protected function getMenuPluginDefinition() {
+    $menu_definition = [];
+
+    // If there is no menu name selected, you don't have a valid menu plugin.
+    if (!$this->values['menu_name']) {
+      return FALSE;
+    }
+
+    $entity = $this->getEntity();
+    $menu_definition['id'] = $this->getPluginId();
+    $menu_definition['title'] = $this->values['title'] ?: $entity->label();
+    $menu_definition['title_max_length'] = $this->getFieldDefinition()->getSetting('max_length');
+    $menu_definition['description'] = isset($this->values['description']) ? $this->values['description'] : '';
+    $menu_definition['menu_name'] = $this->values['menu_name'];
+    $menu_definition['parent'] = $this->values['parent'];
+    $menu_definition['weight'] = isset($this->values['weight']) ? $this->values['weight'] : 0;
+    $menu_definition['class'] = '\Drupal\menu_link\Plugin\Menu\MenuLinkField';
+    $menu_definition['form_class'] = '\Drupal\menu_link\Plugin\Menu\Form\MenuLinkFieldForm';
+    $menu_definition['metadata']['entity_id'] = $entity->id();
+    $menu_definition['metadata']['entity_type_id'] = $entity->getEntityTypeId();
+    $menu_definition['metadata']['field_name'] = $this->definition->getFieldDefinition()->getName();
+    $menu_definition['metadata']['translatable'] = $entity->getEntityType()->isTranslatable();
+
+    $url = $entity->urlInfo();
+    $menu_definition['route_name'] = $url->getRouteName();
+    $menu_definition['route_parameters'] = $url->getRouteParameters();
+
+    return $menu_definition;
+  }
+
+  /**
+   * Returns available menu names.
+   *
+   * @return string[]
+   *   Returns menu labels, keyed by menu ID.
+   */
+  protected function getMenuNames() {
+    if ($custom_menus = Menu::loadMultiple()) {
+      foreach ($custom_menus as $menu_name => $menu) {
+        $custom_menus[$menu_name] = $menu->label();
+      }
+      asort($custom_menus);
+    }
+
+    return $custom_menus;
+  }
+
+}
diff --git a/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php b/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php
new file mode 100644
index 0000000..31007cf
--- /dev/null
+++ b/core/modules/menu_link/src/Plugin/Field/FieldWidget/MenuLinkWidget.php
@@ -0,0 +1,224 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_link\Plugin\Field\FieldWidget\MenuLinkWidget.
+ */
+
+namespace Drupal\menu_link\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Menu\MenuLinkManagerInterface;
+use Drupal\Core\Menu\MenuParentFormSelectorInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Session\AccountInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a widget for the menu_link field type.
+ *
+ * @FieldWidget(
+ *   id = "menu_link_default",
+ *   label = @Translation("Menu link"),
+ *   field_types = {
+ *     "menu_link"
+ *   }
+ * )
+ */
+class MenuLinkWidget extends WidgetBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The parent menu link selector.
+   *
+   * @var \Drupal\Core\Menu\MenuParentFormSelectorInterface
+   */
+  protected $menuParentSelector;
+
+  /**
+   * The current user.
+   *
+   * @var \Drupal\Core\Session\AccountInterface
+   */
+  protected $account;
+
+  /**
+   * The menu link manager.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkManagerInterface
+   */
+  protected $menuLinkManager;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, MenuParentFormSelectorInterface $menu_parent_selector, AccountInterface $account, MenuLinkManagerInterface $menu_link_manager) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
+
+    $this->menuParentSelector = $menu_parent_selector;
+    $this->account = $account;
+    $this->menuLinkManager = $menu_link_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $plugin_id,
+      $plugin_definition,
+      $configuration['field_definition'],
+      $configuration['settings'],
+      $configuration['third_party_settings'],
+      $container->get('menu.parent_form_selector'),
+      $container->get('current_user'),
+      $container->get('plugin.manager.menu.link')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
+    $default_weight = isset($items[$delta]->weight) ? $items[$delta]->weight : 0;
+
+    $available_menus = array_filter($items->getSetting('available_menus'));
+    $available_menus = array_combine($available_menus, $available_menus);
+    $menu_names = array_keys($available_menus);
+
+    if (empty($items[$delta]->menu_name)) {
+      $default_menu_parent = $items->getSetting('default_menu_parent');
+      if (empty($available_menus[rtrim($default_menu_parent, ':')])) {
+        $default_menu_parent = reset($menu_names) . ':';
+      }
+    }
+    else {
+      $menu = $items[$delta]->menu_name;
+      $parent = !empty($items[$delta]->parent) ? $items[$delta]->parent : '';
+      $default_menu_parent = "$menu:$parent";
+    }
+    $default_title = isset($items[$delta]->title) ? $items[$delta]->title : NULL;
+    $default_description = isset($items[$delta]->description) ? $items[$delta]->description : NULL;
+    // The widget form may be used to define default values, so make sure the
+    // form object is an entity form, rather than a configuration form.
+    $form_object = $form_state->getFormObject();
+    $in_translation_form = is_subclass_of($form_object, '\Drupal\Core\Entity\ContentEntityFormInterface') && !$form_object->isDefaultFormLangcode($form_state);
+
+    /** @var \Drupal\Core\Entity\EntityInterface $entity */
+    $entity = $items->getParent()->getValue();
+    $element['#pre_render'][] = [get_class($this), 'preRenderMenuDetails'];
+
+    $element['#attached']['library'][] = 'menu_link/menu_link.form';
+
+    $element['title'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Menu link title'),
+      '#default_value' => $default_title,
+      '#attributes' => ['class' => ['menu-link-title']],
+    ];
+
+    $element['description'] = [
+      '#type' => 'textarea',
+      '#title' => $this->t('Description'),
+      '#default_value' => $default_description,
+      '#rows' => 1,
+      '#description' => $this->t('Shown when hovering over the menu link.'),
+    ];
+
+    $plugin_id = $items[$delta]->getMenuPluginId();
+    $has_plugin = $plugin_id && $this->menuLinkManager->hasDefinition($plugin_id);
+    $element['enabled'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Provide a menu link'),
+      '#default_value' => (int) (bool) $has_plugin,
+      '#attributes' => ['class' => ['menu-link-enabled']],
+      '#multilingual' => FALSE,
+      '#disabled' => $in_translation_form,
+    ];
+    $element['menu'] = [
+      '#type' => 'details',
+      '#title' => $this->t('Menu settings'),
+      '#open' => (bool) $has_plugin,
+      '#tree' => FALSE,
+      '#weight' => $entity->getEntityTypeId() == 'node' ? -2 : 0,
+      '#group' => $entity->getEntityTypeId() == 'node' ? 'advanced' : NULL,
+      '#attributes' => ['class' => ['menu-link-form']],
+      '#attached' => [
+        'library' => ['menu_ui/drupal.menu_ui'],
+      ],
+    ];
+
+    $plugin_id = $items[$delta]->getMenuPluginId();
+    $parent_element = $this->menuParentSelector->parentSelectElement($default_menu_parent, $plugin_id, $available_menus);
+
+    $element['menu_parent'] = $parent_element;
+    $element['menu_parent']['#title'] = $this->t('Parent item');
+    $element['menu_parent']['#attributes']['class'][] = 'menu-parent-select';
+    $element['menu_parent']['#multilingual'] = FALSE;
+    $element['menu_parent']['#disabled'] = $in_translation_form;
+
+    $element['weight'] = [
+      '#type' => 'number',
+      '#title' => $this->t('Weight'),
+      '#default_value' => $default_weight,
+      '#description' => $this->t('Menu links with lower weights are displayed before links with higher weights.'),
+    ];
+
+    return $element;
+  }
+
+  /**
+   * Pre-render callback: Builds a renderable array for the menu link widget.
+   *
+   * @param array $element
+   *   A renderable array.
+   *
+   * @return array
+   *   A renderable array.
+   */
+  public static function preRenderMenuDetails($element) {
+    $element['menu']['enabled'] = $element['enabled'];
+    $element['menu']['title'] = $element['title'];
+    $element['menu']['description'] = $element['description'];
+    $element['menu']['menu_parent'] = $element['menu_parent'];
+    $element['menu']['weight'] = $element['weight'];
+
+    // Hide the elements when enabled is disabled.
+    foreach (['title', 'description', 'menu_parent', 'weight'] as $form_element) {
+      $element['menu'][$form_element]['#states'] = [
+        'invisible' => [
+          'input[name="' . $element['menu']['enabled']['#name'] . '"]' => ['checked' => FALSE],
+        ],
+      ];
+    }
+
+    unset($element['enabled'], $element['title'], $element['description'], $element['menu_parent'], $element['weight']);
+
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
+    parent::extractFormValues($items, $form, $form_state);
+
+    // Extract menu and parent menu link from single select element.
+    foreach ($items as $delta => $item) {
+      if (!empty($item->enabled) && !empty($item->menu_parent) && $item->menu_parent != ':') {
+        list($item->menu_name, $item->parent) = explode(':', $item->menu_parent, 2);
+      }
+      else {
+        $item->title = '';
+        $item->description = '';
+        $item->menu_name = '';
+        $item->parent = '';
+      }
+      unset($item->enabled);
+      unset($item->menu_parent);
+    }
+  }
+
+}
diff --git a/core/modules/menu_link/src/Plugin/Field/MenuLinkItemList.php b/core/modules/menu_link/src/Plugin/Field/MenuLinkItemList.php
new file mode 100644
index 0000000..01b3dd9
--- /dev/null
+++ b/core/modules/menu_link/src/Plugin/Field/MenuLinkItemList.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_link\Plugin\Field\MenuLinkItemList.
+ */
+
+namespace Drupal\menu_link\Plugin\Field;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Field\FieldItemList;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Defines a custom menu link item list for better access checking.
+ */
+class MenuLinkItemList extends FieldItemList {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultValuesForm(array &$form, FormStateInterface $form_state) {
+    // We don't want to use any default values form.
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function defaultAccess($operation = 'view', AccountInterface $account = NULL) {
+    if ($operation == 'edit') {
+      return AccessResult::allowedIfHasPermission($account, 'administer menu');
+    }
+    return parent::defaultAccess($operation, $account);
+  }
+
+}
diff --git a/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php b/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php
new file mode 100644
index 0000000..284d636
--- /dev/null
+++ b/core/modules/menu_link/src/Plugin/Menu/Form/MenuLinkFieldForm.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_link\Plugin\Menu\Form\MenuLinkFieldForm.
+ */
+
+namespace Drupal\menu_link\Plugin\Menu\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Menu\Form\MenuLinkDefaultForm;
+
+/**
+ * Provides the menu link edit form for the field-based menu link.
+ */
+class MenuLinkFieldForm extends MenuLinkDefaultForm {
+
+  /**
+   * The Menu link.
+   *
+   * @var \Drupal\menu_link\Plugin\Menu\MenuLinkField
+   */
+  protected $menuLink;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
+    $entity = $this->menuLink->getEntity();
+
+    $form['info'] = [
+      '#type' => 'item',
+      '#title' => $this->t('This link is provided by the %type: <a href="@url">@label</a>. The path cannot be edited.', [
+        '%type' => $entity->getEntityType()->getLabel(),
+        '@url' => $entity->url(),
+        '@label' => $entity->label(),
+      ]),
+    ];
+
+    return $form;
+  }
+
+}
diff --git a/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php
new file mode 100644
index 0000000..61612e2
--- /dev/null
+++ b/core/modules/menu_link/src/Plugin/Menu/MenuLinkField.php
@@ -0,0 +1,207 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_link\Plugin\Menu\MenuLinkField.
+ */
+
+namespace Drupal\menu_link\Plugin\Menu;
+
+use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Entity\EntityRepositoryInterface;
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\Menu\MenuLinkBase;
+use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a menu link plugin for field-based menu links.
+ */
+class MenuLinkField extends MenuLinkBase implements ContainerFactoryPluginInterface {
+
+  /**
+   * The entity connected to this plugin instance.
+   *
+   * @var \Drupal\Core\Entity\EntityInterface
+   */
+  protected $entity;
+
+  /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
+   */
+  protected $entityTypeManager;
+
+  /**
+   * The entity repsoitory.
+   *
+   * @var Drupal\Core\Entity\EntityRepositoryInterface
+   */
+  protected $entityRepository;
+
+  /**
+   * The language manager.
+   *
+   * @var \Drupal\Core\Language\LanguageManagerInterface
+   */
+  protected $languageManager;
+
+  /**
+   * Constructs a new MenuLinkField object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param mixed $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Core\Entity\EntityRepository $entity_repository
+   *   The entity repository.
+   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+   *   The language manager.
+   */
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_manager, EntityRepositoryInterface $entity_repository, LanguageManagerInterface $language_manager) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+
+    $this->entityTypeManager = $entity_manager;
+    $this->entityRepository = $entity_repository;
+    $this->languageManager = $language_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('entity_type.manager'),
+      $container->get('entity.repository'),
+      $container->get('language_manager')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getTitle() {
+    return $this->getProperty('title');
+  }
+
+  /**
+   * Gets a specific property.
+   *
+   * In case the underlying entity is translatable, we watch the translated
+   * value.
+   *
+   * @param string $property
+   *   Gets a specific property from the field, like title or weight.
+   *
+   * @return mixed
+   *   The Property.
+   */
+  protected function getProperty($property) {
+    // We only need to get the property from the actual entity if it may be a
+    // translation based on the current language context. This can only happen
+    // if the site is configured to be multilingual.
+    if (!empty($this->pluginDefinition['metadata']['translatable']) && $this->languageManager->isMultilingual()) {
+      /** @var \Drupal\Core\TypedData\TranslatableInterface|\Drupal\Core\Entity\EntityInterface $entity */
+      $entity = $this->entityRepository->getTranslationFromContext($this->getEntity());
+      $field_name = $this->getFieldName();
+      if ($property_value = $entity->$field_name->$property) {
+        return $property_value;
+      }
+      return $entity->label();
+    }
+    return $this->pluginDefinition[$property];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->getProperty('description');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getWeight() {
+    return $this->getProperty('weight');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function updateLink(array $new_definition_values, $persist) {
+    $field_name = $this->getFieldName();
+
+    $this->pluginDefinition = $new_definition_values + $this->getPluginDefinition();
+    if ($persist) {
+      $updated = [];
+      foreach ($new_definition_values as $key => $value) {
+        $field = $this->getEntity()->{$field_name};
+        if (isset($field->{$key})) {
+          $field->{$key} = $value;
+          $updated[] = $key;
+        }
+      }
+      if ($updated) {
+        $this->getEntity()->save();
+      }
+    }
+
+    return $this->pluginDefinition;
+  }
+
+  /**
+   * Loads the entity the field was attached to.
+   *
+   * @return \Drupal\Core\Entity\EntityInterface
+   *   Returns the entity, if exists.
+   */
+  public function getEntity() {
+    if (empty($this->entity)) {
+      $entity_type_id = $this->pluginDefinition['metadata']['entity_type_id'];
+      $entity_id = $this->pluginDefinition['metadata']['entity_id'];
+      $this->entity = $this->entityTypeManager->getStorage($entity_type_id)->load($entity_id);
+    }
+    return $this->entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isDeletable() {
+    return TRUE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function deleteLink() {
+    $entity = $this->getEntity();
+    $field_name = $this->getFieldName();
+
+    $entity->$field_name->title = '';
+    $entity->$field_name->description = '';
+    $entity->$field_name->menu_name = '';
+    $entity->$field_name->parent = '';
+    $this->entity->save();
+  }
+
+  /**
+   * Returns the field name.
+   *
+   * @return string
+   *   The Field name.
+   */
+  protected function getFieldName() {
+    return $this->getPluginDefinition()['metadata']['field_name'];
+  }
+
+}
diff --git a/core/modules/menu_link/src/Tests/MenuLinkFieldStandardTest.php b/core/modules/menu_link/src/Tests/MenuLinkFieldStandardTest.php
new file mode 100644
index 0000000..1c78104
--- /dev/null
+++ b/core/modules/menu_link/src/Tests/MenuLinkFieldStandardTest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\menu_link\Tests\MenuLinkFieldStandardTest.
+ */
+
+namespace Drupal\menu_link\Tests;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Tests menu link field functionality.
+ *
+ * @group Menu
+ */
+class MenuLinkFieldStandardTest extends WebTestBase {
+
+  /**
+   * Test paths in the Standard profile.
+   */
+  protected $profile = 'standard';
+
+  /**
+   * An admin user with all permissions.
+   *
+   * @var \Drupal\user\Entity\User
+   */
+  protected $adminUser;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $perms = array_keys(\Drupal::service('user.permissions')->getPermissions());
+    $this->adminUser = $this->drupalCreateUser($perms);
+    $this->drupalLogin($this->adminUser);
+  }
+
+  /**
+   * Tests field CRUD on the node form and field configurations.
+   */
+  public function testLinkEdit() {
+    // Ensure that the field_menu link got created.
+    $node = $this->drupalCreateNode(array(
+      'type' => 'article',
+      'title' => 'Foobar',
+      'promote' => 1,
+      'status' => 1,
+    ));
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertNoFieldChecked('edit-field-menu-0-enabled');
+    $title = $this->randomString();
+    $edit = $this->translatePostValues([
+      'field_menu' => [
+        0 => [
+          'enabled' => TRUE,
+          'title' => $title,
+        ],
+      ],
+    ]);
+    $this->drupalPostForm("node/{$node->id()}/edit", $edit, 'Save and keep published');
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertFieldChecked('edit-field-menu-0-enabled');
+    $this->assertOptionSelected('edit-field-menu-0-menu-parent', 'main:');
+    // Enable another menu.
+    $edit = $this->translatePostValues([
+      'field' => [
+        'settings' => [
+          'available_menus' => [
+            'footer' => TRUE,
+            'main' => TRUE,
+          ],
+        ],
+      ],
+    ]);
+    $this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_menu', $edit, 'Save settings');
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertOptionSelected('edit-field-menu-0-menu-parent', 'main:');
+    $edit = $this->translatePostValues([
+      'field_menu' => [
+        0 => [
+          'menu_parent' => 'footer:',
+        ],
+      ],
+    ]);
+    $this->drupalPostForm("node/{$node->id()}/edit", $edit, 'Save and keep published');
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertOptionSelected('edit-field-menu-0-menu-parent', 'footer:');
+  }
+
+}
diff --git a/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php b/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php
new file mode 100644
index 0000000..707f857
--- /dev/null
+++ b/core/modules/menu_link/src/Tests/MenuLinkFieldTranslateUITest.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\menu_link\Tests\MenuLinkFieldTranslateUITest.
+ */
+
+namespace Drupal\menu_link\Tests;
+
+use Drupal\node\Tests\NodeTranslationUITest;
+
+/**
+ * Tests the translation support for menu field based menu links.
+ *
+ * @group menu_link
+ */
+class MenuLinkFieldTranslateUITest extends NodeTranslationUITest {
+
+  /**
+   * The profile to install as a basis for testing.
+   *
+   * @var string
+   */
+  protected $profile = 'standard';
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'language',
+    'content_translation',
+    'node',
+    'menu_link',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditorPermissions() {
+    return ['administer menu', 'administer nodes', "create $this->bundle content"];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getTranslatorPermissions() {
+    return array_merge(parent::getTranslatorPermissions(), ['administer menu', 'administer nodes', "edit any $this->bundle content"]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getAdministratorPermissions() {
+    return array_merge(parent::getAdministratorPermissions(), ['administer menu', 'access administration pages', 'administer content types', 'administer node fields', 'access content overview', 'bypass node access', 'administer languages', 'administer themes', 'view the administration theme']);
+  }
+
+}
diff --git a/core/modules/menu_ui/config/schema/menu_ui.schema.yml b/core/modules/menu_ui/config/schema/menu_ui.schema.yml
index 69af435..8bbc714 100644
--- a/core/modules/menu_ui/config/schema/menu_ui.schema.yml
+++ b/core/modules/menu_ui/config/schema/menu_ui.schema.yml
@@ -7,17 +7,3 @@ menu_ui.settings:
     override_parent_selector:
       type: boolean
       label: 'Override parent selector'
-
-node.type.*.third_party.menu_ui:
-  type: mapping
-  label: 'Per-content type menu settings'
-  mapping:
-    available_menus:
-      type: sequence
-      label: 'Available menus'
-      sequence:
-       type: string
-       label: 'Menu machine name'
-    parent:
-      type: string
-      label: 'Parent'
diff --git a/core/modules/menu_ui/menu_ui.libraries.yml b/core/modules/menu_ui/menu_ui.libraries.yml
index c5f9594..31f34d2 100644
--- a/core/modules/menu_ui/menu_ui.libraries.yml
+++ b/core/modules/menu_ui/menu_ui.libraries.yml
@@ -1,12 +1,3 @@
-drupal.menu_ui:
-  version: VERSION
-  js:
-    menu_ui.js: {}
-  dependencies:
-    - core/jquery
-    - core/drupal
-    - core/drupal.form
-
 drupal.menu_ui.admin:
   version: VERSION
   js:
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index d3ad899..48d815d 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -128,344 +128,6 @@ function menu_ui_block_view_system_menu_block_alter(array &$build, BlockPluginIn
 }
 
 /**
- * Helper function to create or update a menu link for a node.
- *
- * @param \Drupal\node\NodeInterface $node
- *   Node entity.
- * @param array $values
- *   Values for the menu link.
- */
-function _menu_ui_node_save(NodeInterface $node, array $values) {
-  /** @var \Drupal\menu_link_content\MenuLinkContentInterface $entity */
-  if (!empty($values['entity_id'])) {
-    $entity = MenuLinkContent::load($values['entity_id']);
-    if ($entity->isTranslatable()) {
-      if (!$entity->hasTranslation($node->language()->getId())) {
-        $entity = $entity->addTranslation($node->language()->getId(), $entity->toArray());
-      }
-      else {
-        $entity = $entity->getTranslation($node->language()->getId());
-      }
-    }
-  }
-  else {
-    // Create a new menu_link_content entity.
-    $entity = MenuLinkContent::create(array(
-      'link' => ['uri' => 'entity:node/' . $node->id()],
-      'langcode' => $node->language()->getId(),
-    ));
-    $entity->enabled->value = 1;
-  }
-  $entity->title->value = trim($values['title']);
-  $entity->description->value = trim($values['description']);
-  $entity->menu_name->value = $values['menu_name'];
-  $entity->parent->value = $values['parent'];
-  $entity->weight->value = isset($values['weight']) ? $values['weight'] : 0;
-  $entity->save();
-}
-
-/**
- * Implements hook_ENTITY_TYPE_predelete() for node entities.
- */
-function menu_ui_node_predelete(EntityInterface $node) {
-  // Delete all MenuLinkContent links that point to this node.
-  /** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
-  $menu_link_manager = \Drupal::service('plugin.manager.menu.link');
-  $result = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $node->id()));
-
-  if (!empty($result)) {
-    foreach ($result as $id => $instance) {
-      if ($instance->isDeletable() && strpos($id, 'menu_link_content:') === 0) {
-        $instance->deleteLink();
-      }
-    }
-  }
-}
-
-/**
- * Returns the definition for a menu link for the given node.
- *
- * @param \Drupal\node\NodeInterface $node
- *   The node entity.
- *
- * @return array
- *   An array that contains default values for the menu link form.
- */
-function menu_ui_get_menu_link_defaults(NodeInterface $node) {
-  // Prepare the definition for the edit form.
-  /** @var \Drupal\node\NodeTypeInterface $node_type */
-  $node_type = $node->type->entity;
-  $menu_name = strtok($node_type->getThirdPartySetting('menu_ui', 'parent', 'main:'), ':');
-  $defaults = FALSE;
-  if ($node->id()) {
-    $id = FALSE;
-    // Give priority to the default menu
-    $type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', array('main'));
-    if (in_array($menu_name, $type_menus)) {
-      $query = \Drupal::entityQuery('menu_link_content')
-        ->condition('link.uri', 'node/' . $node->id())
-        ->condition('menu_name', $menu_name)
-        ->sort('id', 'ASC')
-        ->range(0, 1);
-      $result = $query->execute();
-
-      $id = (!empty($result)) ? reset($result) : FALSE;
-    }
-    // Check all allowed menus if a link does not exist in the default menu.
-    if (!$id && !empty($type_menus)) {
-      $query = \Drupal::entityQuery('menu_link_content')
-        ->condition('link.uri', 'entity:node/' . $node->id())
-        ->condition('menu_name', array_values($type_menus), 'IN')
-        ->sort('id', 'ASC')
-        ->range(0, 1);
-      $result = $query->execute();
-
-      $id = (!empty($result)) ? reset($result) : FALSE;
-    }
-    if ($id) {
-      $menu_link = MenuLinkContent::load($id);
-      $menu_link = \Drupal::service('entity.repository')->getTranslationFromContext($menu_link);
-      $defaults = array(
-        'entity_id' => $menu_link->id(),
-        'id' => $menu_link->getPluginId(),
-        'title' => $menu_link->getTitle(),
-        'title_max_length' => $menu_link->getFieldDefinitions()['title']->getSetting('max_length'),
-        'description' => $menu_link->getDescription(),
-        'menu_name' => $menu_link->getMenuName(),
-        'parent' => $menu_link->getParentId(),
-        'weight' => $menu_link->getWeight(),
-      );
-    }
-  }
-
-  if (!$defaults) {
-    // Get the default max_length of a menu link title from the base field
-    // definition.
-    $field_definitions = \Drupal::entityManager()->getBaseFieldDefinitions('menu_link_content');
-    $max_length = $field_definitions['title']->getSetting('max_length');
-    $defaults = array(
-      'entity_id' => 0,
-      'id' => '',
-      'title' => '',
-      'title_max_length' => $max_length,
-      'description' => '',
-      'menu_name' => $menu_name,
-      'parent' => '',
-      'weight' => 0,
-    );
-  }
-  return $defaults;
-}
-
-/**
- * Implements hook_form_BASE_FORM_ID_alter() for node_form.
- *
- * Adds menu item fields to the node form.
- *
- * @see menu_ui_form_node_form_submit()
- */
-function menu_ui_form_node_form_alter(&$form, FormStateInterface $form_state) {
-  // Generate a list of possible parents (not including this link or descendants).
-  // @todo This must be handled in a #process handler.
-  $node = $form_state->getFormObject()->getEntity();
-  $defaults = menu_ui_get_menu_link_defaults($node);
-  /** @var \Drupal\node\NodeTypeInterface $node_type */
-  $node_type = $node->type->entity;
-  /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */
-  $menu_parent_selector = \Drupal::service('menu.parent_form_selector');
-  $menu_names = menu_ui_get_menus();
-  $type_menus = $node_type->getThirdPartySetting('menu_ui', 'available_menus', array('main'));
-  $available_menus = array();
-  foreach ($type_menus as $menu) {
-    $available_menus[$menu] = $menu_names[$menu];
-  }
-  if ($defaults['id']) {
-    $default = $defaults['menu_name'] . ':' . $defaults['parent'];
-  }
-  else {
-    $default = $node_type->getThirdPartySetting('menu_ui', 'parent', 'main:');
-  }
-  $parent_element = $menu_parent_selector->parentSelectElement($default, $defaults['id'], $available_menus);
-  // If no possible parent menu items were found, there is nothing to display.
-  if (empty($parent_element)) {
-    return;
-  }
-
-  $form['menu'] = array(
-    '#type' => 'details',
-    '#title' => t('Menu settings'),
-    '#access' => \Drupal::currentUser()->hasPermission('administer menu'),
-    '#open' => (bool) $defaults['id'],
-    '#group' => 'advanced',
-    '#attached' => array(
-      'library' => array('menu_ui/drupal.menu_ui'),
-    ),
-    '#tree' => TRUE,
-    '#weight' => -2,
-    '#attributes' => array('class' => array('menu-link-form')),
-  );
-  $form['menu']['enabled'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Provide a menu link'),
-    '#default_value' => (int) (bool) $defaults['id'],
-  );
-  $form['menu']['link'] = array(
-    '#type' => 'container',
-    '#parents' => array('menu'),
-    '#states' => array(
-      'invisible' => array(
-        'input[name="menu[enabled]"]' => array('checked' => FALSE),
-      ),
-    ),
-  );
-
-  // Populate the element with the link data.
-  foreach (array('id', 'entity_id') as $key) {
-    $form['menu']['link'][$key] = array('#type' => 'value', '#value' => $defaults[$key]);
-  }
-
-  $form['menu']['link']['title'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Menu link title'),
-    '#default_value' => $defaults['title'],
-    '#maxlength' => $defaults['title_max_length'],
-  );
-
-  $form['menu']['link']['description'] = array(
-    '#type' => 'textarea',
-    '#title' => t('Description'),
-    '#default_value' => $defaults['description'],
-    '#rows' => 1,
-    '#description' => t('Shown when hovering over the menu link.'),
-  );
-
-  $form['menu']['link']['menu_parent'] = $parent_element;
-  $form['menu']['link']['menu_parent']['#title'] = t('Parent item');
-  $form['menu']['link']['menu_parent']['#attributes']['class'][] = 'menu-parent-select';
-
-  $form['menu']['link']['weight'] = array(
-    '#type' => 'number',
-    '#title' => t('Weight'),
-    '#default_value' => $defaults['weight'],
-    '#description' => t('Menu links with lower weights are displayed before links with higher weights.'),
-  );
-
-  foreach (array_keys($form['actions']) as $action) {
-    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
-      $form['actions'][$action]['#submit'][] = 'menu_ui_form_node_form_submit';
-    }
-  }
-}
-
-/**
- * Form submission handler for menu item field on the node form.
- *
- * @see menu_ui_form_node_form_alter()
- */
-function menu_ui_form_node_form_submit($form, FormStateInterface $form_state) {
-  $node = $form_state->getFormObject()->getEntity();
-  if (!$form_state->isValueEmpty('menu')) {
-    $values = $form_state->getValue('menu');
-    if (empty($values['enabled'])) {
-      if ($values['entity_id']) {
-        $entity = MenuLinkContent::load($values['entity_id']);
-        $entity->delete();
-      }
-    }
-    elseif (trim($values['title']))  {
-      // Decompose the selected menu parent option into 'menu_name' and 'parent',
-      // if the form used the default parent selection widget.
-      if (!empty($values['menu_parent'])) {
-        list($menu_name, $parent) = explode(':', $values['menu_parent'], 2);
-        $values['menu_name'] = $menu_name;
-        $values['parent'] = $parent;
-      }
-      _menu_ui_node_save($node, $values);
-    }
-  }
-}
-
-/**
- * Implements hook_form_FORM_ID_alter().
- *
- * Adds menu options to the node type form.
- *
- * @see NodeTypeForm::form().
- * @see menu_ui_form_node_type_form_submit().
- */
-function menu_ui_form_node_type_form_alter(&$form, FormStateInterface $form_state) {
-  /** @var \Drupal\Core\Menu\MenuParentFormSelectorInterface $menu_parent_selector */
-  $menu_parent_selector = \Drupal::service('menu.parent_form_selector');
-  $menu_options = menu_ui_get_menus();
-  /** @var \Drupal\node\NodeTypeInterface $type */
-  $type = $form_state->getFormObject()->getEntity();
-  $form['menu'] = array(
-    '#type' => 'details',
-    '#title' => t('Menu settings'),
-    '#attached' => array(
-      'library' => array('menu_ui/drupal.menu_ui.admin'),
-    ),
-    '#group' => 'additional_settings',
-  );
-  $form['menu']['menu_options'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Available menus'),
-    '#default_value' => $type->getThirdPartySetting('menu_ui', 'available_menus', array('main')),
-    '#options' => $menu_options,
-    '#description' => t('The menus available to place links in for this content type.'),
-  );
-  // @todo See if we can avoid pre-loading all options by changing the form or
-  //   using a #process callback. https://www.drupal.org/node/2310319
-  //   To avoid an 'illegal option' error after saving the form we have to load
-  //   all available menu parents. Otherwise, it is not possible to dynamically
-  //   add options to the list using ajax.
-  $options_cacheability = new CacheableMetadata();
-  $options = $menu_parent_selector->getParentSelectOptions('', NULL, $options_cacheability);
-  $form['menu']['menu_parent'] = array(
-    '#type' => 'select',
-    '#title' => t('Default parent item'),
-    '#default_value' => $type->getThirdPartySetting('menu_ui', 'parent', 'main:'),
-    '#options' => $options,
-    '#description' => t('Choose the menu item to be the default parent for a new link in the content authoring form.'),
-    '#attributes' => array('class' => array('menu-title-select')),
-  );
-  $options_cacheability->applyTo($form['menu']['menu_parent']);
-
-  $form['#validate'][] = 'menu_ui_form_node_type_form_validate';
-  $form['#entity_builders'][] = 'menu_ui_form_node_type_form_builder';
-}
-
-/**
- * Submit handler for forms with menu options.
- *
- * @see menu_ui_form_node_type_form_alter().
- */
-function menu_ui_form_node_type_form_validate(&$form, FormStateInterface $form_state) {
-  $available_menus = array_filter($form_state->getValue('menu_options'));
-  // If there is at least one menu allowed, the selected item should be in
-  // one of them.
-  if (count($available_menus)) {
-    $menu_item_id_parts = explode(':', $form_state->getValue('menu_parent'));
-    if (!in_array($menu_item_id_parts[0], $available_menus)) {
-      $form_state->setErrorByName('menu_parent', t('The selected menu item is not under one of the selected menus.'));
-    }
-  }
-  else {
-    $form_state->setValue('menu_parent', '');
-  }
-}
-
-/**
- * Entity builder for the node type form with menu options.
- *
- * @see menu_ui_form_node_type_form_alter().
- */
-function menu_ui_form_node_type_form_builder($entity_type, NodeTypeInterface $type, &$form, FormStateInterface $form_state) {
-  $type->setThirdPartySetting('menu_ui', 'available_menus', array_values(array_filter($form_state->getValue('menu_options'))));
-  $type->setThirdPartySetting('menu_ui', 'parent', $form_state->getValue('menu_parent'));
-}
-
-/**
  * Return an associative array of the custom menus names.
  *
  * @param bool $all
diff --git a/core/modules/menu_ui/menu_ui.routing.yml b/core/modules/menu_ui/menu_ui.routing.yml
index 7f94a6d..9e1312f 100644
--- a/core/modules/menu_ui/menu_ui.routing.yml
+++ b/core/modules/menu_ui/menu_ui.routing.yml
@@ -38,6 +38,19 @@ menu_ui.link_reset:
     _permission: 'administer menu'
     _custom_access: '\Drupal\menu_ui\Form\MenuLinkResetForm::linkIsResettable'
 
+menu_ui.link_delete:
+  path: '/admin/structure/menu/link/{menu_link_plugin}/delete'
+  defaults:
+    _form: 'Drupal\menu_ui\Form\MenuLinkDeleteForm'
+    _title: 'Delete menu link'
+  options:
+    parameters:
+      menu_link_plugin:
+        type: menu_link_plugin
+  requirements:
+    _permission: 'administer menu'
+    _custom_access: '\Drupal\menu_ui\Form\MenuLinkDeleteForm::linkIsDeletable'
+
 entity.menu.add_form:
   path: '/admin/structure/menu/add'
   defaults:
diff --git a/core/modules/menu_ui/src/Form/MenuLinkDeleteForm.php b/core/modules/menu_ui/src/Form/MenuLinkDeleteForm.php
new file mode 100644
index 0000000..9dc086e
--- /dev/null
+++ b/core/modules/menu_ui/src/Form/MenuLinkDeleteForm.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\menu_ui\Form\MenuLinkDeleteForm.
+ */
+
+namespace Drupal\menu_ui\Form;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Menu\MenuLinkManagerInterface;
+use Drupal\Core\Menu\MenuLinkInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Defines a generic confirmation form for deleting a single menu link.
+ */
+class MenuLinkDeleteForm extends ConfirmFormBase {
+
+  /**
+   * The menu link manager.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkManagerInterface
+   */
+  protected $menuLinkManager;
+
+  /**
+   * The menu link.
+   *
+   * @var \Drupal\Core\Menu\MenuLinkInterface
+   */
+  protected $link;
+
+  /**
+   * Constructs a MenuLinkResetForm object.
+   *
+   * @param \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager
+   *   The menu link manager.
+   */
+  public function __construct(MenuLinkManagerInterface $menu_link_manager) {
+    $this->menuLinkManager = $menu_link_manager;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('plugin.manager.menu.link')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'menu_link_delete_confirm';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Are you sure you want to delete the link %item?', array('%item' => $this->link->getTitle()));
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelUrl() {
+    if ($this->link) {
+      return new Url('entity.menu.edit_form', array(
+        'menu' => $this->link->getMenuName(),
+      ));
+    }
+    return new Url('<front>');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDescription() {
+    return $this->t('The link will be deleted. This action cannot be undone.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return $this->t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, MenuLinkInterface $menu_link_plugin = NULL) {
+    $this->link = $menu_link_plugin;
+
+    $form = parent::buildForm($form, $form_state);
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $this->link = $this->menuLinkManager->removeDefinition($this->link->getPluginId());
+    drupal_set_message($this->t('The menu link was deleted.'));
+    $form_state->setRedirectUrl($this->getCancelUrl());
+  }
+
+  /**
+   * Checks access based on whether the link can be deleted.
+   *
+   * @param \Drupal\Core\Menu\MenuLinkInterface $menu_link_plugin
+   *   The menu link plugin being checked.
+   *
+   * @return \Drupal\Core\Access\AccessResultInterface
+   *   The access result.
+   */
+  public function linkIsDeletable(MenuLinkInterface $menu_link_plugin) {
+    return AccessResult::allowedIf($menu_link_plugin->isDeletable())->setCacheable(FALSE);
+  }
+
+}
diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php
index dfbea9e..1472e95 100644
--- a/core/modules/menu_ui/src/MenuForm.php
+++ b/core/modules/menu_ui/src/MenuForm.php
@@ -410,9 +410,17 @@ protected function buildOverviewTreeForm($tree, $delta) {
             'url' => Url::fromRoute('menu_ui.link_reset', ['menu_link_plugin' => $link->getPluginId()]),
           );
         }
-        elseif ($delete_link = $link->getDeleteRoute()) {
-          $operations['delete']['url'] = $delete_link;
-          $operations['delete']['query'] = $this->getDestinationArray();
+        elseif ($link->isDeletable()) {
+          // Allow for a custom delete link per plugin.
+          $delete_route = $link->getDeleteRoute();
+          if ($delete_route) {
+            $operations['delete']['url'] = $delete_route;
+          }
+          else {
+            // Fall back to the standard delete link.
+            $operations['delete']['url'] = Url::fromRoute('menu_ui.link_delete', ['menu_link_plugin' => $link->getPluginId()]);
+          }
+          $operations['delete']['query']['destination'] = $this->entity->url();
           $operations['delete']['title'] = $this->t('Delete');
         }
         if ($link->isTranslatable()) {
diff --git a/core/modules/menu_ui/src/Tests/MenuNodeTest.php b/core/modules/menu_ui/src/Tests/MenuNodeTest.php
index 0022d58..1b0ac2e 100644
--- a/core/modules/menu_ui/src/Tests/MenuNodeTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuNodeTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\menu_ui\Tests;
 
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
 use Drupal\simpletest\WebTestBase;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\menu_link_content\Entity\MenuLinkContent;
@@ -31,7 +33,22 @@ class MenuNodeTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('menu_ui', 'test_page_test', 'node', 'block', 'locale', 'language', 'content_translation');
+  public static $modules = array('menu_ui', 'test_page_test', 'node', 'block', 'menu_link', 'locale', 'language', 'content_translation');
+
+  /**
+   * @var \Drupal\field\Entity\FieldConfig
+   */
+  protected $fieldConfig;
+
+  /**
+   * @var \Drupal\field\Entity\FieldStorageConfig
+   */
+  protected $fieldStorageConfig;
+
+  /**
+   * @var \Drupal\field\Entity\FieldStorageConfig
+   */
+  protected $fieldConfigArticle;
 
   protected function setUp() {
     parent::setUp();
@@ -40,6 +57,25 @@ protected function setUp() {
     $this->drupalPlaceBlock('page_title_block');
 
     $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
+    $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
+
+    $this->fieldStorageConfig = FieldStorageConfig::create(['field_name' => 'menu', 'entity_type' => 'node', 'type' => 'menu_link']);
+    $this->fieldStorageConfig->save();
+    $this->fieldConfig = FieldConfig::create(['entity_type' => 'node', 'bundle' => 'page', 'field_name' => 'menu']);
+    $this->fieldConfig->save();
+    entity_get_form_display('node', 'page', 'default')
+      ->setComponent('menu', [
+        'type' => 'menu_link_default',
+      ])
+      ->save();
+
+    $this->fieldConfigArticle = FieldConfig::create(['entity_type' => 'node', 'bundle' => 'article', 'field_name' => 'menu']);
+    $this->fieldConfigArticle->save();
+    entity_get_form_display('node', 'article', 'default')
+      ->setComponent('menu', [
+        'type' => 'menu_link_default',
+      ])
+      ->save();
 
     $this->editor = $this->drupalCreateUser(array(
       'access administration pages',
@@ -73,15 +109,12 @@ function testMenuNodeFormWidget() {
     $this->assertPattern('/<input .* id="edit-menu-title" .* maxlength="' . $max_length . '" .* \/>/', 'Menu link title field has correct maxlength in node add form.');
 
     // Disable the default main menu, so that no menus are enabled.
-    $edit = array(
-      'menu_options[main]' => FALSE,
-    );
-    $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
+    $this->fieldConfig->settings['available_menus']['menu'] = FALSE;
+    $this->fieldConfig->save();
 
     // Verify that no menu settings are displayed and nodes can be created.
     $this->drupalGet('node/add/page');
     $this->assertText(t('Create Basic page'));
-    $this->assertNoText(t('Menu settings'));
     $node_title = $this->randomMachineName();
     $edit = array(
       'title[0][value]' => $node_title,
@@ -93,22 +126,15 @@ function testMenuNodeFormWidget() {
 
     // Test that we cannot set a menu item from a menu that is not set as
     // available.
-    $edit = array(
-      'menu_options[tools]' => 1,
-      'menu_parent' => 'main:',
-    );
-    $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
-    $this->assertText(t('The selected menu item is not under one of the selected menus.'));
-    $this->assertNoRaw(t('The content type %name has been updated.', array('%name' => 'Basic page')));
+    $this->fieldConfig->settings['available_menus']['tools'] = 'tools';
+    $this->fieldConfig->settings['parent'] = 'main:';
+    $this->fieldConfig->save();
 
     // Enable Tools menu as available menu.
-    $edit = array(
-      'menu_options[main]' => 1,
-      'menu_options[tools]' => 1,
-      'menu_parent' => 'main:',
-    );
-    $this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
-    $this->assertRaw(t('The content type %name has been updated.', array('%name' => 'Basic page')));
+    $this->fieldConfig->settings['available_menus']['tools'] = 'tools';
+    $this->fieldConfig->settings['available_menus']['main'] = 'main';
+    $this->fieldConfig->settings['parent'] = 'main:';
+    $this->fieldConfig->save();
 
     // Test that we can preview a node that will create a menu item.
     $edit = array(
@@ -131,13 +157,14 @@ function testMenuNodeFormWidget() {
     $this->assertNoLink($node_title);
 
     // Edit the node, enable the menu link setting, but skip the link title.
+    // We still expect to have a link to the entity label of the node.
     $edit = array(
-      'menu[enabled]' => 1,
+      'menu[0][enabled]' => 1,
     );
     $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
-    // Assert that there is no link for the node.
+    // Assert that there is a link for the node.
     $this->drupalGet('test-page');
-    $this->assertNoLink($node_title);
+    $this->assertLink($node->label());
 
     // Use not only the save button, but also the two special buttons:
     // 'Save and publish' as well as 'Save and keep published'.
@@ -171,9 +198,8 @@ function testMenuNodeFormWidget() {
     $this->drupalLogin($this->editor);
     // Edit the node and create a menu link.
     $edit = array(
-      'menu[enabled]' => 1,
-      'menu[title]' => $node_title,
-      'menu[weight]' => 17,
+      'menu[0][enabled]' => 1,
+      'menu[0][weight]' => 17,
     );
     $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
     // Assert that the link exists.
@@ -181,9 +207,12 @@ function testMenuNodeFormWidget() {
     $this->assertLink($node_title);
 
     $this->drupalGet('node/' . $node->id() . '/edit');
-    $this->assertFieldById('edit-menu-weight', 17, 'Menu weight correct in edit form');
+    $this->assertFieldById('edit-menu-0-weight', 17, 'Menu weight correct in edit form');
     $this->assertPattern('/<input .* id="edit-menu-title" .* maxlength="' . $max_length . '" .* \/>/', 'Menu link title field has correct maxlength in node edit form.');
 
+    // Ensure that the menu link field is opened up by default.
+    $this->assertFieldById('edit-menu-0-enabled', 1, 'Provide a menu link checkbox is checked.');
+
     // Disable the menu link, then edit the node--the link should stay disabled.
     $link_id = menu_ui_get_menu_link_defaults($node)['entity_id'];
     /** @var \Drupal\menu_link_content\Entity\MenuLinkContent $link */
@@ -196,13 +225,17 @@ function testMenuNodeFormWidget() {
 
     // Edit the node and remove the menu link.
     $edit = array(
-      'menu[enabled]' => FALSE,
+      'menu[0][enabled]' => FALSE,
     );
     $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
     // Assert that there is no link for the node.
     $this->drupalGet('test-page');
     $this->assertNoLink($node_title);
 
+    // Ensure that the menu link is also no longer stored.
+    $plugin_id = $node->menu->first()->getMenuPluginId();
+    $this->assertFalse(\Drupal::service('plugin.manager.menu.link')->hasDefinition($plugin_id));
+
     // Add a menu link to the Administration menu.
     $item = MenuLinkContent::create(array(
       'link' => [['uri' => 'entity:node/' . $node->id()]],
@@ -217,12 +250,13 @@ function testMenuNodeFormWidget() {
     $this->assertText('Provide a menu link', 'Link in not allowed menu not shown in node edit form');
     // Assert that the link is still in the Administration menu after save.
     $this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save'));
-    $link = MenuLinkContent::load($item->id());
+    $link = \Drupal::service('plugin.manager.menu.link')->getDefinition($node->menu->first()->getMenuPluginId());
     $this->assertTrue($link, 'Link in not allowed menu still exists after saving node');
 
     // Move the menu link back to the Tools menu.
-    $item->menu_name->value = 'tools';
-    $item->save();
+    $node->menu->menu_name = 'tools';
+    $node->save();
+
     // Create a second node.
     $child_node = $this->drupalCreateNode(array('type' => 'article'));
     // Assign a menu link to the second node, being a child of the first one.
@@ -236,10 +270,10 @@ function testMenuNodeFormWidget() {
     // Edit the first node.
     $this->drupalGet('node/'. $node->id() .'/edit');
     // Assert that it is not possible to set the parent of the first node to itself or the second node.
-    $this->assertNoOption('edit-menu-menu-parent', 'tools:'. $item->getPluginId());
-    $this->assertNoOption('edit-menu-menu-parent', 'tools:'. $child_item->getPluginId());
+    $this->assertNoOption('edit-menu-0-menu-parent', 'tools:'. $node->menu->first()->getMenuPluginId());
+    $this->assertNoOption('edit-menu-0-menu-parent', 'tools:'. $child_node->menu->first()->getMenuPluginId());
     // Assert that unallowed Administration menu is not available in options.
-    $this->assertNoOption('edit-menu-menu-parent', 'admin:');
+    $this->assertNoOption('edit-menu-0-menu-parent', 'admin:');
   }
 
   /**
diff --git a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php b/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
index 6548208..75e5cf1 100644
--- a/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/src/Tests/Menu/BreadcrumbTest.php
@@ -8,8 +8,9 @@
 namespace Drupal\system\Tests\Menu;
 
 use Drupal\Core\Url;
-use Drupal\node\Entity\NodeType;
 use Drupal\user\RoleInterface;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\field\Entity\FieldStorageConfig;
 
 /**
  * Tests breadcrumbs functionality.
@@ -23,7 +24,7 @@ class BreadcrumbTest extends MenuTestBase {
    *
    * @var array
    */
-  public static $modules = array('menu_test', 'block');
+  public static $modules = array('menu_test', 'block', 'menu_link');
 
   /**
    * An administrative user.
@@ -171,11 +172,19 @@ function testBreadCrumbs() {
     // @todo Also test all themes? Manually testing led to the suspicion that
     //   breadcrumbs may differ, possibly due to theme overrides.
     $menus = array('main', 'tools');
-    // Alter node type menu settings.
-    $node_type = NodeType::load($type);
-    $node_type->setThirdPartySetting('menu_ui', 'available_menus', $menus);
-    $node_type->setThirdPartySetting('menu_ui', 'parent', 'tools:');
-    $node_type->save();
+    // Add a menu field to the node type.
+    $field_storage_config = FieldStorageConfig::create(['field_name' => 'menu', 'entity_type' => 'node', 'type' => 'menu_link']);
+    $field_storage_config->save();
+    $field_config = FieldConfig::create(['entity_type' => 'node', 'bundle' => $type, 'field_name' => 'menu']);
+    $field_config->settings['available_menus'] = array_combine($menus, $menus);
+    $field_config->settings['default_menu_parent'] = 'tools:';
+    $field_config->save();
+
+    entity_get_form_display('node', $type, 'default')
+      ->setComponent('menu', [
+        'type' => 'menu_link_default',
+      ])
+      ->save();
 
     foreach ($menus as $menu) {
       // Create a parent node in the current menu.
@@ -183,14 +192,11 @@ function testBreadCrumbs() {
       $node2 = $this->drupalCreateNode(array(
         'type' => $type,
         'title' => $title,
-        'menu' => array(
-          'enabled' => 1,
-          'title' => 'Parent ' . $title,
-          'description' => '',
-          'menu_name' => $menu,
-          'parent' => '',
-        ),
       ));
+      $node2->menu->title = 'Parent ' . $title;
+      $node2->menu->description = '';
+      $node2->menu->menu_name = $menu;
+      $node2->menu->parent = '';
 
       if ($menu == 'tools') {
         $parent = $node2;
@@ -209,7 +215,7 @@ function testBreadCrumbs() {
     $link = reset($menu_links);
 
     $edit = array(
-      'menu[menu_parent]' => $link->getMenuName() . ':' . $link->getPluginId(),
+      'menu[0][menu_parent]' => $link->getMenuName() . ':' . $link->getPluginId(),
     );
     $this->drupalPostForm('node/' . $parent->id() . '/edit', $edit, t('Save and keep published'));
     $expected = array(
@@ -217,10 +223,10 @@ function testBreadCrumbs() {
     );
     $trail = $home + $expected;
     $tree = $expected + array(
-      'node/' . $parent->id() => $parent->menu['title'],
+      'node/' . $parent->id() => $parent->menu->title,
     );
     $trail += array(
-      'node/' . $parent->id() => $parent->menu['title'],
+      'node/' . $parent->id() => $parent->menu->title,
     );
 
     // Add a taxonomy term/tag to last node, and add a link for that term to the
diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
index 79156b2..26d29ea 100644
--- a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
+++ b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
@@ -80,4 +80,9 @@ content:
       size: 60
       placeholder: ''
     third_party_settings: {  }
+  field_menu:
+    weight: 32
+    settings: {  }
+    third_party_settings: {  }
+    type: menu_link_default
 hidden: {  }
diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
index 1fef06d..a04c484 100644
--- a/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
+++ b/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
@@ -3,10 +3,12 @@ status: true
 dependencies:
   config:
     - field.field.node.page.body
+    - field.field.node.page.field_menu
     - node.type.page
   module:
     - path
     - text
+    - menu_link
 id: node.page.default
 targetEntityType: node
 bundle: page
@@ -57,4 +59,9 @@ content:
       size: 60
       placeholder: ''
     third_party_settings: {  }
+  field_menu:
+    weight: 32
+    settings: {  }
+    third_party_settings: {  }
+    type: menu_link_default
 hidden: {  }
diff --git a/core/profiles/standard/config/install/field.field.node.article.field_menu.yml b/core/profiles/standard/config/install/field.field.node.article.field_menu.yml
new file mode 100644
index 0000000..178853b
--- /dev/null
+++ b/core/profiles/standard/config/install/field.field.node.article.field_menu.yml
@@ -0,0 +1,24 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_menu
+    - node.type.article
+  module:
+    - menu_link
+id: node.article.field_menu
+field_name: field_menu
+entity_type: node
+bundle: article
+label: Menu link
+description: ''
+required: false
+translatable: true
+default_value: {  }
+default_value_callback: ''
+settings:
+  available_menus:
+    - main
+  default_menu_parent: 'main:'
+third_party_settings: {  }
+field_type: menu_link
diff --git a/core/profiles/standard/config/install/field.field.node.page.field_menu.yml b/core/profiles/standard/config/install/field.field.node.page.field_menu.yml
new file mode 100644
index 0000000..c8445a1
--- /dev/null
+++ b/core/profiles/standard/config/install/field.field.node.page.field_menu.yml
@@ -0,0 +1,24 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_menu
+    - node.type.page
+  module:
+    - menu_link
+id: node.page.field_menu
+field_name: field_menu
+entity_type: node
+bundle: page
+label: Menu link
+description: ''
+required: false
+translatable: true
+default_value: {  }
+default_value_callback: ''
+settings:
+  available_menus:
+    - main
+  default_menu_parent: 'main:'
+third_party_settings: {  }
+field_type: menu_link
diff --git a/core/profiles/standard/config/install/field.storage.node.field_menu.yml b/core/profiles/standard/config/install/field.storage.node.field_menu.yml
new file mode 100644
index 0000000..cb69efc
--- /dev/null
+++ b/core/profiles/standard/config/install/field.storage.node.field_menu.yml
@@ -0,0 +1,17 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - menu_link
+    - node
+id: node.field_menu
+field_name: field_menu
+entity_type: node
+type: menu_link
+settings: {  }
+module: menu_link
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
diff --git a/core/profiles/standard/src/Tests/StandardTest.php b/core/profiles/standard/src/Tests/StandardTest.php
index 391c049..bb8c4ee 100644
--- a/core/profiles/standard/src/Tests/StandardTest.php
+++ b/core/profiles/standard/src/Tests/StandardTest.php
@@ -49,6 +49,8 @@ function testStandard() {
       'skip comment approval',
       'create article content',
       'create page content',
+      'edit own page content',
+      'administer menu',
     ));
     $this->drupalLogin($this->adminUser);
     // Configure the block.
@@ -105,6 +107,16 @@ function testStandard() {
     $this->assertText('Foobar');
     $this->assertNoText('Then she picked out two somebodies, Sally and me');
 
+    // Ensure that the field_menu link got created.
+    $node = $this->drupalCreateNode(array(
+      'type' => 'page',
+      'title' => 'Foobar',
+      'promote' => 1,
+      'status' => 1,
+    ));
+    $this->drupalGet("node/{$node->id()}/edit");
+    $this->assertFieldById('edit-field-menu-0-enabled', FALSE);
+
     // Ensure block body exists.
     $this->drupalGet('block/add');
     $this->assertFieldByName('body[0][value]');
diff --git a/core/profiles/standard/standard.info.yml b/core/profiles/standard/standard.info.yml
index 82af32e..9c77190 100644
--- a/core/profiles/standard/standard.info.yml
+++ b/core/profiles/standard/standard.info.yml
@@ -15,6 +15,7 @@ dependencies:
   - contextual
   - contact
   - menu_link_content
+  - menu_link
   - datetime
   - block_content
   - quickedit
