diff --git a/core/lib/Drupal/Core/Menu/MenuLinkDefault.php b/core/lib/Drupal/Core/Menu/MenuLinkDefault.php
index c224142..c17fe79 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkDefault.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkDefault.php
@@ -67,26 +67,14 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function getTitle() {
-    // Subclasses may pull in the request or specific attributes as parameters.
-    $options = array();
-    if (!empty($this->pluginDefinition['title_context'])) {
-      $options['context'] = $this->pluginDefinition['title_context'];
-    }
-    $args = array();
-    if (isset($this->pluginDefinition['title_arguments']) && $title_arguments = $this->pluginDefinition['title_arguments']) {
-      $args = (array) $title_arguments;
-    }
-    return $this->t($this->pluginDefinition['title'], $args, $options);
+    return (string) $this->pluginDefinition['title'];
   }
 
   /**
    * {@inheritdoc}
    */
   public function getDescription() {
-    if ($this->pluginDefinition['description']) {
-      return $this->t($this->pluginDefinition['description']);
-    }
-    return '';
+    return (string) $this->pluginDefinition['description'];
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Menu/MenuLinkManager.php b/core/lib/Drupal/Core/Menu/MenuLinkManager.php
index b4c7760..44eeeb3 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkManager.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkManager.php
@@ -41,14 +41,9 @@ class MenuLinkManager implements MenuLinkManagerInterface {
     'route_parameters' => array(),
     // The external URL if this link has one (required if route_name is empty).
     'url' => '',
-    // The static title for the menu link. You can specify placeholders like on
-    // any translatable string and the values in title_arguments.
+    // The static title for the menu link. If this came from a YAML definition
+    // or other safe source this may be a TranslationWrapper object.
     'title' => '',
-    // The values for the menu link placeholders.
-    'title_arguments' => array(),
-    // A context for the title string.
-    // @see \Drupal\Core\StringTranslation\TranslationInterface::translate()
-    'title_context' => '',
     // The description.
     'description' => '',
     // The plugin ID of the parent link (or NULL for a top-level link).
@@ -148,8 +143,10 @@ protected function processDefinition(array &$definition, $plugin_id) {
    */
   protected function getDiscovery() {
     if (!isset($this->discovery)) {
-      $this->discovery = new YamlDiscovery('links.menu', $this->moduleHandler->getModuleDirectories());
-      $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
+      $yaml_discovery = new YamlDiscovery('links.menu', $this->moduleHandler->getModuleDirectories());
+      $yaml_discovery->addTranslatableProperty('title', 'title_context');
+      $yaml_discovery->addTranslatableProperty('description', 'description_context');
+      $this->discovery = new ContainerDerivativeDiscoveryDecorator($yaml_discovery);
     }
     return $this->discovery;
   }
diff --git a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php
index 659d6be..11e3711 100644
--- a/core/lib/Drupal/Core/Menu/MenuTreeStorage.php
+++ b/core/lib/Drupal/Core/Menu/MenuTreeStorage.php
@@ -95,8 +95,6 @@ class MenuTreeStorage implements MenuTreeStorageInterface {
     'route_parameters',
     'url',
     'title',
-    'title_arguments',
-    'title_context',
     'description',
     'parent',
     'weight',
@@ -367,7 +365,9 @@ protected function preSave(array &$link, array $original) {
     $fields['route_param_key'] = $fields['route_parameters'] ? UrlHelper::buildQuery($fields['route_parameters']) : '';
 
     foreach ($this->serializedFields() as $name) {
-      $fields[$name] = serialize($fields[$name]);
+      if (isset($fields[$name])) {
+        $fields[$name] = serialize($fields[$name]);
+      }
     }
     $this->setParents($fields, $parent, $original);
 
@@ -619,7 +619,9 @@ protected function updateParentalStatus(array $link) {
    */
   protected function prepareLink(array $link, $intersect = FALSE) {
     foreach ($this->serializedFields() as $name) {
-      $link[$name] = unserialize($link[$name]);
+      if (isset($link[$name])) {
+        $link[$name] = unserialize($link[$name]);
+      }
     }
     if ($intersect) {
       $link = array_intersect_key($link, array_flip($this->definitionFields()));
@@ -736,7 +738,9 @@ protected function loadFullMultiple(array $ids) {
     $loaded = $this->safeExecuteSelect($query)->fetchAllAssoc('id', \PDO::FETCH_ASSOC);
     foreach ($loaded as &$link) {
       foreach ($this->serializedFields() as $name) {
-        $link[$name] = unserialize($link[$name]);
+        if (isset($link[$name])) {
+          $link[$name] = unserialize($link[$name]);
+        }
       }
     }
     return $loaded;
@@ -927,15 +931,19 @@ protected function loadLinks($menu_name, MenuTreeParameters $parameters) {
     if (!empty($parameters->conditions)) {
       // Only allow conditions that are testing definition fields.
       $parameters->conditions = array_intersect_key($parameters->conditions, array_flip($this->definitionFields()));
+      $serialized = array_flip($this->serializedFields());
       foreach ($parameters->conditions as $column => $value) {
-        if (!is_array($value)) {
-          $query->condition($column, $value);
-        }
-        else {
+        if (is_array($value)) {
           $operator = $value[1];
           $value = $value[0];
-          $query->condition($column, $value, $operator);
         }
+        else {
+          $operator = '=';
+        }
+        if (isset($serialized[$column])) {
+          $value = serialize($value);
+        }
+        $query->condition($column, $value, $operator);
       }
     }
 
@@ -1242,30 +1250,18 @@ protected static function schemaDefinition() {
           'default' => '',
         ),
         'title' => array(
-          'description' => 'The text displayed for the link.',
-          'type' => 'varchar',
-          'length' => 255,
-          'not null' => TRUE,
-          'default' => '',
-        ),
-        'title_arguments' => array(
-          'description' => 'A serialized array of arguments to be passed to t() (if this plugin uses it).',
+          'description' => 'The title for the link. May be a serialized TranslationWrapper',
           'type' => 'blob',
           'size' => 'big',
           'not null' => FALSE,
           'serialize' => TRUE,
         ),
-        'title_context' => array(
-          'description' => 'The translation context for the link title.',
-          'type' => 'varchar',
-          'length' => 255,
-          'not null' => TRUE,
-          'default' => '',
-        ),
         'description' => array(
           'description' => 'The description of this link - used for admin pages and title attribute.',
-          'type' => 'text',
+          'type' => 'blob',
+          'size' => 'big',
           'not null' => FALSE,
+          'serialize' => TRUE,
         ),
         'class' => array(
           'description' => 'The class for this link plugin.',
diff --git a/core/modules/menu_link_content/src/Tests/MenuLinkContentDeriverTest.php b/core/modules/menu_link_content/src/Tests/MenuLinkContentDeriverTest.php
index c7a1ae1..7ea61d0 100644
--- a/core/modules/menu_link_content/src/Tests/MenuLinkContentDeriverTest.php
+++ b/core/modules/menu_link_content/src/Tests/MenuLinkContentDeriverTest.php
@@ -7,7 +7,9 @@
 
 namespace Drupal\menu_link_content\Tests;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Menu\MenuTreeParameters;
+use Drupal\Core\StringTranslation\TranslationWrapper;
 use Drupal\menu_link_content\Entity\MenuLinkContent;
 use Drupal\simpletest\KernelTestBase;
 use Symfony\Component\Routing\Route;
@@ -45,7 +47,7 @@ public function testRediscover() {
 
     // Set up a custom menu link pointing to a specific path.
     MenuLinkContent::create([
-      'title' => 'Example',
+      'title' => '<script>alert("Welcome to the discovered jungle!")</script>',
       'link' => [['uri' => 'internal:/example-path']],
       'menu_name' => 'tools',
     ])->save();
@@ -67,6 +69,10 @@ public function testRediscover() {
     /** @var \Drupal\Core\Menu\MenuLinkTreeElement $tree_element */
     $tree_element = reset($menu_tree);
     $this->assertEqual('route_name_2', $tree_element->link->getRouteName());
+    $title = (string) $tree_element->link->getTitle();
+    $this->assertFalse($title instanceof TranslationWrapper);
+    $this->assertIdentical('<script>alert("Welcome to the discovered jungle!")</script>', $title);
+    $this->assertFalse(SafeMarkup::isSafe($title));
   }
 
 }
diff --git a/core/modules/system/src/Tests/Menu/MenuTreeStorageTest.php b/core/modules/system/src/Tests/Menu/MenuTreeStorageTest.php
index 1df4050..57f1f2a 100644
--- a/core/modules/system/src/Tests/Menu/MenuTreeStorageTest.php
+++ b/core/modules/system/src/Tests/Menu/MenuTreeStorageTest.php
@@ -354,7 +354,6 @@ protected function addMenuLink($id, $parent = '', $route_name = 'test', $route_p
       'menu_name' => $menu_name,
       'route_name' => $route_name,
       'route_parameters' => $route_parameters,
-      'title_arguments' => array(),
       'title' => 'test',
       'parent' => $parent,
       'options' => array(),
diff --git a/core/modules/system/src/Tests/Update/UpdatePathTestBase.php b/core/modules/system/src/Tests/Update/UpdatePathTestBase.php
index fb365f0..6221c08 100644
--- a/core/modules/system/src/Tests/Update/UpdatePathTestBase.php
+++ b/core/modules/system/src/Tests/Update/UpdatePathTestBase.php
@@ -141,7 +141,15 @@ protected function setUp() {
 
     // Rebuild and reset.
     $this->rebuildAll();
-
+    // Remove the notices we get due to the menu link rebuild prior to running
+    // the system updates for the schema change.
+    foreach ($this->assertions as $key => $assertion) {
+      if ($assertion['message_group'] == 'Notice' && basename($assertion['file']) == 'MenuTreeStorage.php' && strpos($assertion['message'], 'unserialize(): Error at offset 0') !== FALSE) {
+        unset($this->assertions[$key]);
+        $this->deleteAssert($assertion['message_id']);
+        $this->results['#exception']--;
+      }
+    }
     // Replace User 1 with the user created here.
     /** @var \Drupal\user\UserInterface $account */
     $account = User::load(1);
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index a0849b1..c3990c8 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1085,3 +1085,66 @@ function system_schema() {
 
   return $schema;
 }
+
+/**
+ * Change two fields on the default menu link storage to be serialized data.
+ */
+function system_update_8001(&$sandbox = NULL) {
+  if (db_table_exists('menu_tree')) {
+    $database = \Drupal::database();
+
+    if (!isset($sandbox['current'])) {
+      $spec = array(
+        'description' => 'The title for the link. May be a serialized TranslationWrapper',
+        'type' => 'blob',
+        'size' => 'big',
+        'not null' => FALSE,
+        'serialize' => TRUE,
+      );
+      db_change_field('menu_tree', 'title', 'title', $spec);
+      $spec = array(
+        'description' => 'The description of this link - used for admin pages and title attribute.',
+        'type' => 'blob',
+        'size' => 'big',
+        'not null' => FALSE,
+        'serialize' => TRUE,
+      );
+      db_change_field('menu_tree', 'description', 'description', $spec);
+
+      $sandbox['current'] = 0;
+      $sandbox['max'] = $database->query('SELECT COUNT(mlid) FROM {menu_tree}')
+        ->fetchField();
+    }
+
+    $menu_links = $database->queryRange('SELECT mlid, title, description FROM {menu_tree} ORDER BY mlid ASC', $sandbox['current'], $sandbox['current'] + 50)
+      ->fetchAllAssoc('mlid');
+
+    foreach ($menu_links as $menu_link) {
+      $menu_link = (array) $menu_link;
+      // Convert title and description to serialized strings.
+      $menu_link['title'] = serialize($menu_link['title']);
+      $menu_link['description'] = serialize($menu_link['description']);
+
+      $database->update('menu_tree')
+        ->fields($menu_link)
+        ->condition('mlid', $menu_link['mlid'])
+        ->execute();
+
+      $sandbox['current'] += 50;
+    }
+
+    $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['current'] / $sandbox['max']);
+
+
+    if ($sandbox['#finished'] >= 1) {
+      // Drop unnecessary fields from {menu_tree}.
+      db_drop_field('menu_tree', 'title_arguments');
+      db_drop_field('menu_tree', 'title_context');
+    }
+    return t('Menu links converted');
+  }
+  else {
+    return t('Menu link conversion skipped');
+  }
+}
+
