diff --git a/core/includes/form.inc b/core/includes/form.inc
index d5eaa54..9c5c347 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -30,18 +30,6 @@ function form_get_cache($form_build_id, FormStateInterface $form_state) {
 }
 
 /**
- * Stores a form in the cache.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- *   Use \Drupal::formBuilder()->setCache().
- *
- * @see \Drupal\Core\Form\FormCacheInterface::setCache().
- */
-function form_set_cache($form_build_id, $form, FormStateInterface $form_state) {
-  \Drupal::formBuilder()->setCache($form_build_id, $form, $form_state);
-}
-
-/**
  * Retrieves, populates, and processes a form.
  *
  * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
index 5b227e2..a5b68af 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/OptionsSelectWidget.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldWidget;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Form\FormStateInterface;
 
@@ -48,7 +49,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    */
   protected function sanitizeLabel(&$label) {
     // Select form inputs allow unencoded HTML entities, but no HTML tags.
-    $label = decode_entities(strip_tags($label));
+    $label = String::decodeEntities(strip_tags($label));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Mail/MailFormatHelper.php b/core/lib/Drupal/Core/Mail/MailFormatHelper.php
index 3f180cc..b11a31b 100644
--- a/core/lib/Drupal/Core/Mail/MailFormatHelper.php
+++ b/core/lib/Drupal/Core/Mail/MailFormatHelper.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Mail;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Site\Settings;
 
@@ -262,7 +263,7 @@ public static function htmlToText($string, $allowed_tags = NULL) {
       else {
         // Convert inline HTML text to plain text; not removing line-breaks or
         // white-space, since that breaks newlines when sanitizing plain-text.
-        $value = trim(decode_entities($value));
+        $value = trim(String::decodeEntities($value));
         if (drupal_strlen($value)) {
           $chunk = $value;
         }
diff --git a/core/lib/Drupal/Core/Mail/MailInterface.php b/core/lib/Drupal/Core/Mail/MailInterface.php
index 64573ad..ff77d65 100644
--- a/core/lib/Drupal/Core/Mail/MailInterface.php
+++ b/core/lib/Drupal/Core/Mail/MailInterface.php
@@ -17,7 +17,8 @@
 interface MailInterface {
 
   /**
-   * Formats a message composed by drupal_mail() prior sending.
+   * Formats a message composed by
+   * \Drupal::service('plugin.manager.mail')->mail() prior sending.
    *
    * Allows to preprocess, format, and postprocess a mail message before it is
    * passed to the sending system. By default, all messages may contain HTML and
@@ -36,7 +37,8 @@
    public function format(array $message);
 
   /**
-   * Sends a message composed by drupal_mail().
+   * Sends a message composed by
+   * \Drupal::service('plugin.manager.mail')->mail().
    *
    * @param array $message
    *   Message array with at least the following elements:
diff --git a/core/lib/Drupal/Core/Mail/MailManager.php b/core/lib/Drupal/Core/Mail/MailManager.php
index decbeed..708a6c2 100644
--- a/core/lib/Drupal/Core/Mail/MailManager.php
+++ b/core/lib/Drupal/Core/Mail/MailManager.php
@@ -117,8 +117,8 @@ public function __construct(\Traversable $namespaces, CacheBackendInterface $cac
    *
    * @param array $options
    *   An array with the following key/value pairs:
-   *   - module: (string) The module name which was used by drupal_mail() to
-   *     invoke hook_mail().
+   *   - module: (string) The module name which was used by
+   *     \Drupal::service('plugin.manager.mail')->mail() to invoke hook_mail().
    *   - key: (string) A key to identify the email sent. The final message ID
    *     is a string represented as {$module}_{$key}.
    *
diff --git a/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php b/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php
index f3d7aaf..e7b5077 100644
--- a/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php
+++ b/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core\Mail\Plugin\Mail;
 
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Mail\MailFormatHelper;
 use Drupal\Core\Mail\MailInterface;
 use Drupal\Core\Site\Settings;
 
@@ -34,7 +36,7 @@ public function format(array $message) {
     // Join the body array into one string.
     $message['body'] = implode("\n\n", $message['body']);
     // Convert any HTML to plain-text.
-    $message['body'] = drupal_html_to_text($message['body']);
+    $message['body'] = MailFormatHelper::htmlToText($message['body']);
     // Wrap the mail body for sending.
     $message['body'] = drupal_wrap_mail($message['body']);
 
@@ -51,7 +53,7 @@ public function format(array $message) {
    *   TRUE if the mail was successfully accepted, otherwise FALSE.
    *
    * @see http://php.net/manual/en/function.mail.php
-   * @see drupal_mail()
+   * @see \Drupal::service('plugin.manager.mail')->mail()
    */
   public function mail(array $message) {
     // If 'Return-Path' isn't already set in php.ini, we pass it separately
@@ -65,11 +67,11 @@ public function mail(array $message) {
     }
     $mimeheaders = array();
     foreach ($message['headers'] as $name => $value) {
-      $mimeheaders[] = $name . ': ' . mime_header_encode($value);
+      $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value);
     }
     $line_endings = Settings::get('mail_line_endings', PHP_EOL);
     // Prepare mail commands.
-    $mail_subject = mime_header_encode($message['subject']);
+    $mail_subject = Unicode::mimeHeaderEncode($message['subject']);
     // Note: email uses CRLF for line-endings. PHP's API requires LF
     // on Unix and CRLF on Windows. Drupal automatically guesses the
     // line-ending format appropriate for your system. If you need to
diff --git a/core/modules/action/src/Plugin/Action/EmailAction.php b/core/modules/action/src/Plugin/Action/EmailAction.php
index 2a1e3a9..5bdc609 100644
--- a/core/modules/action/src/Plugin/Action/EmailAction.php
+++ b/core/modules/action/src/Plugin/Action/EmailAction.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Action\ConfigurableActionBase;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Mail\MailManagerInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Utility\Token;
 use Psr\Log\LoggerInterface;
@@ -48,6 +49,13 @@ class EmailAction extends ConfigurableActionBase implements ContainerFactoryPlug
   protected $logger;
 
   /**
+   * The mail manager
+   *
+   * @var \Drupal\Core\Mail\MailManagerInterface
+   */
+  protected $mailManager;
+
+  /**
    * Constructs a EmailAction object.
    *
    * @param array $configuration
@@ -62,13 +70,16 @@ class EmailAction extends ConfigurableActionBase implements ContainerFactoryPlug
    *   The entity manager.
    * @param \Psr\Log\LoggerInterface $logger
    *   A logger instance.
+   * @param \Drupal\Core\Mail\MailManagerInterface
+   *   The mail manager.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, EntityManagerInterface $entity_manager, LoggerInterface $logger) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, EntityManagerInterface $entity_manager, LoggerInterface $logger, MailManagerInterface $mail_manager) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
     $this->token = $token;
     $this->storage = $entity_manager->getStorage('user');
     $this->logger = $logger;
+    $this->mailManager = $mail_manager;
   }
 
   /**
@@ -78,7 +89,8 @@ public static function create(ContainerInterface $container, array $configuratio
     return new static($configuration, $plugin_id, $plugin_definition,
       $container->get('token'),
       $container->get('entity.manager'),
-      $container->get('logger.factory')->get('action')
+      $container->get('logger.factory')->get('action'),
+      $container->get('plugin.manager.mail')
     );
   }
 
@@ -105,7 +117,7 @@ public function execute($entity = NULL) {
     }
     $params = array('context' => $this->configuration);
 
-    if (drupal_mail('system', 'action_send_email', $recipient, $langcode, $params)) {
+    if ($this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params)) {
       $this->logger->notice('Sent email to %recipient', array('%recipient' => $recipient));
     }
     else {
diff --git a/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php b/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php
index 199e224..f6c1412 100644
--- a/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php
+++ b/core/modules/aggregator/src/Plugin/aggregator/processor/DefaultProcessor.php
@@ -11,6 +11,7 @@
 use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
 use Drupal\aggregator\Plugin\ProcessorInterface;
 use Drupal\aggregator\FeedInterface;
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Datetime\DateFormatter;
@@ -213,8 +214,8 @@ public function process(FeedInterface $feed) {
       }
 
       // Make sure the item title and author fit in the 255 varchar column.
-      $entry->setTitle(truncate_utf8($item['title'], 255, TRUE, TRUE));
-      $entry->setAuthor(truncate_utf8($item['author'], 255, TRUE, TRUE));
+      $entry->setTitle(Unicode::truncate($item['title'], 255, TRUE, TRUE));
+      $entry->setAuthor(Unicode::truncate($item['author'], 255, TRUE, TRUE));
 
       $entry->setFeedId($feed->id());
       $entry->setLink($item['link']);
diff --git a/core/modules/contact/src/MessageViewBuilder.php b/core/modules/contact/src/MessageViewBuilder.php
index 23e9b43..6852e7b 100644
--- a/core/modules/contact/src/MessageViewBuilder.php
+++ b/core/modules/contact/src/MessageViewBuilder.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityViewBuilder;
 use Drupal\Component\Utility\String;
+use Drupal\Core\Mail\MailFormatHelper;
 use Drupal\Core\Render\Element;
 
 /**
@@ -55,7 +56,7 @@ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = N
 
     if ($view_mode == 'mail') {
       // Convert field labels into headings.
-      // @todo Improve drupal_html_to_text() to convert DIVs correctly.
+      // @todo Improve Drupal\Core\Mail\MailFormatHelper::htmlToText() to convert DIVs correctly.
       foreach (Element::children($build) as $key) {
         if (isset($build[$key]['#label_display']) && $build[$key]['#label_display'] == 'above') {
           $build[$key] += array('#prefix' => '');
@@ -64,7 +65,7 @@ public function view(EntityInterface $entity, $view_mode = 'full', $langcode = N
         }
       }
       $build = array(
-        '#markup' => drupal_html_to_text(drupal_render($build)),
+        '#markup' => MailFormatHelper::htmlToText(drupal_render($build)),
       );
     }
     return $build;
diff --git a/core/modules/contact/src/Tests/ContactSitewideTest.php b/core/modules/contact/src/Tests/ContactSitewideTest.php
index beee430..5fcf023 100644
--- a/core/modules/contact/src/Tests/ContactSitewideTest.php
+++ b/core/modules/contact/src/Tests/ContactSitewideTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\contact\Tests;
 
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Mail\MailFormatHelper;
 use Drupal\simpletest\WebTestBase;
 use Drupal\Core\Entity\EntityTypeInterface;
 
@@ -299,7 +300,7 @@ function testAutoReply() {
     // We are testing the auto-reply, so there should be one email going to the sender.
     $captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
     $this->assertEqual(count($captured_emails), 1);
-    $this->assertEqual(trim($captured_emails[0]['body']), trim(drupal_html_to_text($foo_autoreply)));
+    $this->assertEqual(trim($captured_emails[0]['body']), trim(MailFormatHelper::htmlToText($foo_autoreply)));
 
     // Test the auto-reply for form 'bar'.
     $email = $this->randomMachineName(32) . '@example.com';
@@ -308,7 +309,7 @@ function testAutoReply() {
     // Auto-reply for form 'bar' should result in one auto-reply email to the sender.
     $captured_emails = $this->drupalGetMails(array('id' => 'contact_page_autoreply', 'to' => $email));
     $this->assertEqual(count($captured_emails), 1);
-    $this->assertEqual(trim($captured_emails[0]['body']), trim(drupal_html_to_text($bar_autoreply)));
+    $this->assertEqual(trim($captured_emails[0]['body']), trim(MailFormatHelper::htmlToText($bar_autoreply)));
 
     // Verify that no auto-reply is sent when the auto-reply field is left blank.
     $email = $this->randomMachineName(32) . '@example.com';
diff --git a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
index b0affe8..684e4b7 100644
--- a/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
+++ b/core/modules/contextual/src/Plugin/views/field/ContextualLinks.php
@@ -8,6 +8,7 @@
 namespace Drupal\contextual\Plugin\views\field;
 
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\Plugin\views\field\FieldPluginBase;
@@ -98,7 +99,7 @@ public function render(ResultRow $values) {
       if (!empty($title) && !empty($path)) {
         // Make sure that tokens are replaced for this paths as well.
         $tokens = $this->getRenderTokens(array());
-        $path = strip_tags(decode_entities(strtr($path, $tokens)));
+        $path = strip_tags(String::decodeEntities(strtr($path, $tokens)));
 
         $links[$field] = array(
           'href' => $path,
diff --git a/core/modules/dblog/src/Tests/DbLogTest.php b/core/modules/dblog/src/Tests/DbLogTest.php
index 925e31a..8f334d8 100644
--- a/core/modules/dblog/src/Tests/DbLogTest.php
+++ b/core/modules/dblog/src/Tests/DbLogTest.php
@@ -297,7 +297,7 @@ private function doUser() {
     $this->assertLogMessage(t('Session closed for %name.', array('%name' => $name)), 'DBLog event was recorded: [logout user]');
     // Delete user.
     $message = t('Deleted user: %name %email.', array('%name' => $name, '%email' => '<' . $user->getEmail() . '>'));
-    $message_text = truncate_utf8(Xss::filter($message, array()), 56, TRUE, TRUE);
+    $message_text = Unicode::truncate(Xss::filter($message, array()), 56, TRUE, TRUE);
     // Verify that the full message displays on the details page.
     $link = FALSE;
     if ($links = $this->xpath('//a[text()="' . html_entity_decode($message_text) . '"]')) {
@@ -650,7 +650,7 @@ protected function asText(\SimpleXMLElement $element) {
    *   The message to pass to simpletest.
    */
   protected function assertLogMessage($log_message, $message) {
-    $message_text = truncate_utf8(Xss::filter($log_message, array()), 56, TRUE, TRUE);
+    $message_text = Unicode::truncate(Xss::filter($log_message, array()), 56, TRUE, TRUE);
     // After \Drupal\Component\Utility\Xss::filter(), HTML entities should be
     // converted to their character equivalents because assertLink() uses this
     // string in xpath() to query the Document Object Model (DOM).
diff --git a/core/modules/entity_reference/src/EntityReferenceAutocomplete.php b/core/modules/entity_reference/src/EntityReferenceAutocomplete.php
index 2eeeee7..ffc9995 100644
--- a/core/modules/entity_reference/src/EntityReferenceAutocomplete.php
+++ b/core/modules/entity_reference/src/EntityReferenceAutocomplete.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\entity_reference;
 
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Tags;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
@@ -98,7 +99,7 @@ public function getMatches(FieldDefinitionInterface $field_definition, $entity_t
           $key = "$label ($entity_id)";
           // Strip things like starting/trailing white spaces, line breaks and
           // tags.
-          $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(decode_entities(strip_tags($key)))));
+          $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(String::decodeEntities(strip_tags($key)))));
           // Names containing commas or quotes must be wrapped in quotes.
           $key = Tags::encode($key);
           $matches[] = array('value' => $prefix . $key, 'label' => $label);
diff --git a/core/modules/field_ui/src/FieldOverview.php b/core/modules/field_ui/src/FieldOverview.php
index 838c116..312832f 100644
--- a/core/modules/field_ui/src/FieldOverview.php
+++ b/core/modules/field_ui/src/FieldOverview.php
@@ -8,6 +8,7 @@
 namespace Drupal\field_ui;
 
 use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\EntityListBuilderInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
@@ -228,7 +229,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $entity_t
           '@label' => $info['label'],
           '@field' => $info['field'],
         ));
-        $existing_field_options[$field_name] = truncate_utf8($text, 80, FALSE, TRUE);
+        $existing_field_options[$field_name] = Unicode::truncate($text, 80, FALSE, TRUE);
       }
       asort($existing_field_options);
       $name = '_add_existing_field';
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 06e71ae..9f83add 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -532,7 +532,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
  *   \Symfony\Component\HttpFoundation\StreamedResponse.
  */
 function file_get_content_headers(FileInterface $file) {
-  $type = mime_header_encode($file->getMimeType());
+  $type = Unicode::mimeHeaderEncode($file->getMimeType());
 
   return array(
     'Content-Type' => $type,
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index bf121b4..7af6732 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -612,7 +612,7 @@ function _filter_url_parse_full_links($match) {
   // The $i:th parenthesis in the regexp contains the URL.
   $i = 1;
 
-  $match[$i] = decode_entities($match[$i]);
+  $match[$i] = String::decodeEntities($match[$i]);
   $caption = String::checkPlain(_filter_url_trim($match[$i]));
   $match[$i] = String::checkPlain($match[$i]);
   return '<a href="' . $match[$i] . '">' . $caption . '</a>';
@@ -627,7 +627,7 @@ function _filter_url_parse_email_links($match) {
   // The $i:th parenthesis in the regexp contains the URL.
   $i = 0;
 
-  $match[$i] = decode_entities($match[$i]);
+  $match[$i] = String::decodeEntities($match[$i]);
   $caption = String::checkPlain(_filter_url_trim($match[$i]));
   $match[$i] = String::checkPlain($match[$i]);
   return '<a href="mailto:' . $match[$i] . '">' . $caption . '</a>';
@@ -642,7 +642,7 @@ function _filter_url_parse_partial_links($match) {
   // The $i:th parenthesis in the regexp contains the URL.
   $i = 1;
 
-  $match[$i] = decode_entities($match[$i]);
+  $match[$i] = String::decodeEntities($match[$i]);
   $caption = String::checkPlain(_filter_url_trim($match[$i]));
   $match[$i] = String::checkPlain($match[$i]);
   return '<a href="http://' . $match[$i] . '">' . $caption . '</a>';
diff --git a/core/modules/filter/src/Tests/FilterUnitTest.php b/core/modules/filter/src/Tests/FilterUnitTest.php
index faf7e27..00977ab 100644
--- a/core/modules/filter/src/Tests/FilterUnitTest.php
+++ b/core/modules/filter/src/Tests/FilterUnitTest.php
@@ -1016,7 +1016,7 @@ function testHtmlCorrectorFilter() {
    *   TRUE on pass, FALSE on fail.
    */
   function assertNormalized($haystack, $needle, $message = '', $group = 'Other') {
-    return $this->assertTrue(strpos(strtolower(decode_entities($haystack)), $needle) !== FALSE, $message, $group);
+    return $this->assertTrue(strpos(strtolower(String::decodeEntities($haystack)), $needle) !== FALSE, $message, $group);
   }
 
   /**
@@ -1040,6 +1040,6 @@ function assertNormalized($haystack, $needle, $message = '', $group = 'Other') {
    *   TRUE on pass, FALSE on fail.
    */
   function assertNoNormalized($haystack, $needle, $message = '', $group = 'Other') {
-    return $this->assertTrue(strpos(strtolower(decode_entities($haystack)), $needle) === FALSE, $message, $group);
+    return $this->assertTrue(strpos(strtolower(String::decodeEntities($haystack)), $needle) === FALSE, $message, $group);
   }
 }
diff --git a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
index 3aabb67..ff7b1b4 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
@@ -8,6 +8,7 @@
 namespace Drupal\link\Plugin\Field\FieldFormatter;
 
 use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FormatterBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -142,7 +143,7 @@ public function viewElements(FieldItemListInterface $items) {
 
       // Trim the link text to the desired length.
       if (!empty($settings['trim_length'])) {
-        $link_title = truncate_utf8($link_title, $settings['trim_length'], FALSE, TRUE);
+        $link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE);
       }
 
       if (!empty($settings['url_only']) && !empty($settings['url_plain'])) {
diff --git a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
index a32e611..c88b8ff 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
@@ -12,6 +12,7 @@
 
 namespace Drupal\link\Plugin\Field\FieldFormatter;
 
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Field\FieldItemListInterface;
 
 /**
@@ -67,8 +68,8 @@ public function viewElements(FieldItemListInterface $items) {
       }
       $url_title = $url->toString();
       if (!empty($settings['trim_length'])) {
-        $link_title = truncate_utf8($link_title, $settings['trim_length'], FALSE, TRUE);
-        $url_title = truncate_utf8($url_title, $settings['trim_length'], FALSE, TRUE);
+        $link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE);
+        $url_title = Unicode::truncate($url_title, $settings['trim_length'], FALSE, TRUE);
       }
 
       $element[$delta] = array(
diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php
index 4bd30cd..223acdb 100644
--- a/core/modules/link/src/Tests/LinkFieldTest.php
+++ b/core/modules/link/src/Tests/LinkFieldTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\link\Tests;
 
 use Drupal\Component\Utility\String;
+use Drupal\Component\Utility\Unicode;
 use Drupal\link\LinkItemInterface;
 use Drupal\simpletest\WebTestBase;
 
@@ -384,11 +385,11 @@ function testLinkFormatter() {
         switch ($setting) {
           case 'trim_length':
             $url = $url1;
-            $title = isset($new_value) ? truncate_utf8($title1, $new_value, FALSE, TRUE) : $title1;
+            $title = isset($new_value) ? Unicode::truncate($title1, $new_value, FALSE, TRUE) : $title1;
             $this->assertRaw('<a href="' . String::checkPlain($url) . '">' . String::checkPlain($title) . '</a>');
 
             $url = $url2;
-            $title = isset($new_value) ? truncate_utf8($title2, $new_value, FALSE, TRUE) : $title2;
+            $title = isset($new_value) ? Unicode::truncate($title2, $new_value, FALSE, TRUE) : $title2;
             $this->assertRaw('<a href="' . String::checkPlain($url) . '">' . String::checkPlain($title) . '</a>');
             break;
 
@@ -503,15 +504,15 @@ function testLinkSeparateFormatter() {
         switch ($setting) {
           case 'trim_length':
             $url = $url1;
-            $url_title = isset($new_value) ? truncate_utf8($url, $new_value, FALSE, TRUE) : $url;
+            $url_title = isset($new_value) ? Unicode::truncate($url, $new_value, FALSE, TRUE) : $url;
             $expected = '<div class="link-item">';
             $expected .= '<div class="link-url"><a href="' . String::checkPlain($url) . '">' . String::checkPlain($url_title) . '</a></div>';
             $expected .= '</div>';
             $this->assertRaw($expected);
 
             $url = $url2;
-            $url_title = isset($new_value) ? truncate_utf8($url, $new_value, FALSE, TRUE) : $url;
-            $title = isset($new_value) ? truncate_utf8($title2, $new_value, FALSE, TRUE) : $title2;
+            $url_title = isset($new_value) ? Unicode::truncate($url, $new_value, FALSE, TRUE) : $url;
+            $title = isset($new_value) ? Unicode::truncate($title2, $new_value, FALSE, TRUE) : $title2;
             $expected = '<div class="link-item">';
             $expected .= '<div class="link-title">' . String::checkPlain($title) . '</div>';
             $expected .= '<div class="link-url"><a href="' . String::checkPlain($url) . '">' . String::checkPlain($url_title) . '</a></div>';
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 846ee88..623a658 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -11,6 +11,7 @@
  */
 
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Url;
@@ -960,7 +961,7 @@ function locale_translation_use_remote_source() {
  * layout issues (div) or a possible attack vector (img).
  */
 function locale_string_is_safe($string) {
-  return decode_entities($string) == decode_entities(Xss::filter($string, array('a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var')));
+  return String::decodeEntities($string) == String::decodeEntities(Xss::filter($string, array('a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'blockquote', 'br', 'caption', 'cite', 'code', 'col', 'colgroup', 'dd', 'del', 'dfn', 'dl', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'i', 'ins', 'kbd', 'li', 'ol', 'p', 'pre', 'q', 'samp', 'small', 'span', 'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'tt', 'ul', 'var')));
 }
 
 /**
diff --git a/core/modules/path/src/Controller/PathController.php b/core/modules/path/src/Controller/PathController.php
index 5f6f3c6..c56097c 100644
--- a/core/modules/path/src/Controller/PathController.php
+++ b/core/modules/path/src/Controller/PathController.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\path\Controller;
 
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Path\AliasStorageInterface;
 use Drupal\Core\Path\AliasManagerInterface;
@@ -74,10 +75,10 @@ public function adminOverview($keys) {
     $destination = drupal_get_destination();
     foreach ($this->aliasStorage->getAliasesForAdminListing($header, $keys) as $data) {
       $row = array();
-      $row['data']['alias'] = _l(truncate_utf8($data->alias, 50, FALSE, TRUE), $data->source, array(
+      $row['data']['alias'] = _l(Unicode::truncate($data->alias, 50, FALSE, TRUE), $data->source, array(
         'attributes' => array('title' => $data->alias),
       ));
-      $row['data']['source'] = _l(truncate_utf8($data->source, 50, FALSE, TRUE), $data->source, array(
+      $row['data']['source'] = _l(Unicode::truncate($data->source, 50, FALSE, TRUE), $data->source, array(
         'alias' => TRUE,
         'attributes' => array('title' => $data->source),
       ));
diff --git a/core/modules/search/search.module b/core/modules/search/search.module
index 91afbc1..385bbe3 100644
--- a/core/modules/search/search.module
+++ b/core/modules/search/search.module
@@ -241,7 +241,7 @@ function search_update_totals() {
  */
 function search_simplify($text, $langcode = NULL) {
   // Decode entities to UTF-8
-  $text = decode_entities($text);
+  $text = String::decodeEntities($text);
 
   // Lowercase
   $text = drupal_strtolower($text);
@@ -357,7 +357,7 @@ function _search_index_truncate(&$text) {
   if (is_numeric($text)) {
     $text = ltrim($text, '0');
   }
-  $text = truncate_utf8($text, 50);
+  $text = Unicode::truncate($text, 50);
 }
 
 /**
@@ -582,7 +582,7 @@ function search_excerpt($keys, $text, $langcode = NULL) {
 
   // Prepare text by stripping HTML tags and decoding HTML entities.
   $text = strip_tags(str_replace(array('<', '>'), array(' <', '> '), $text));
-  $text = decode_entities($text);
+  $text = String::decodeEntities($text);
   $text_length = strlen($text);
 
   // Make a list of unique keywords that are actually found in the text,
@@ -663,7 +663,7 @@ function search_excerpt($keys, $text, $langcode = NULL) {
     // We didn't find any keyword matches, so just return the first part of the
     // text. We also need to re-encode any HTML special characters that we
     // entity-decoded above.
-    return String::checkPlain(truncate_utf8($text, 256, TRUE, TRUE));
+    return String::checkPlain(Unicode::truncate($text, 256, TRUE, TRUE));
   }
 
   // Sort the text ranges by starting position.
diff --git a/core/modules/search/src/Tests/SearchPageTextTest.php b/core/modules/search/src/Tests/SearchPageTextTest.php
index ede9e4c..5cb4865 100644
--- a/core/modules/search/src/Tests/SearchPageTextTest.php
+++ b/core/modules/search/src/Tests/SearchPageTextTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\search\Tests;
 
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 
 /**
@@ -58,7 +59,7 @@ function testSearchText() {
     $edit['keys'] = $search_terms;
     $this->drupalPostForm('search/node', $edit, t('Search'));
     $actual_title = (string) current($this->xpath('//title'));
-    $this->assertEqual($actual_title, decode_entities(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)))), 'Search page title is correct');
+    $this->assertEqual($actual_title, String::decodeEntities(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)))), 'Search page title is correct');
 
     $edit['keys'] = $this->searching_user->getUsername();
     $this->drupalPostForm('search/user', $edit, t('Search'));
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index e44979f..77b7f8c 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -2043,7 +2043,7 @@ protected function checkForMetaRefresh() {
         // Parse the content attribute of the meta tag for the format:
         // "[delay]: URL=[page_to_redirect_to]".
         if (preg_match('/\d+;\s*URL=(?<url>.*)/i', $refresh[0]['content'], $match)) {
-          return $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url'])));
+          return $this->drupalGet($this->getAbsoluteUrl(String::decodeEntities($match['url'])));
         }
       }
     }
diff --git a/core/modules/system/src/Tests/Mail/HtmlToTextTest.php b/core/modules/system/src/Tests/Mail/HtmlToTextTest.php
index e48ba42..72f97a9 100644
--- a/core/modules/system/src/Tests/Mail/HtmlToTextTest.php
+++ b/core/modules/system/src/Tests/Mail/HtmlToTextTest.php
@@ -8,11 +8,12 @@
 namespace Drupal\system\Tests\Mail;
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\Mail\MailFormatHelper;
 use Drupal\Core\Site\Settings;
 use Drupal\simpletest\WebTestBase;
 
 /**
- * Tests for drupal_html_to_text().
+ * Tests for Drupal\Core\Mail\MailFormatHelper::htmlToText().
  *
  * @group Mail
  */
@@ -37,7 +38,7 @@ protected function stringToHtml($text) {
   }
 
   /**
-   * Helper function for testing drupal_html_to_text().
+   * Helper function for testing Drupal\Core\Mail\MailFormatHelperr::htmlToText().
    *
    * @param $html
    *   The source HTML string to be converted.
@@ -47,13 +48,13 @@ protected function stringToHtml($text) {
    *   A text message to display in the assertion message.
    * @param $allowed_tags
    *   (optional) An array of allowed tags, or NULL to default to the full
-   *   set of tags supported by drupal_html_to_text().
+   *   set of tags supported by Drupal\Core\Mail\MailFormatHelper::htmlToText().
    */
   protected function assertHtmlToText($html, $text, $message, $allowed_tags = NULL) {
     preg_match_all('/<([a-z0-6]+)/', drupal_strtolower($html), $matches);
     $tested_tags = implode(', ', array_unique($matches[1]));
     $message .= ' (' . $tested_tags . ')';
-    $result = drupal_html_to_text($html, $allowed_tags);
+    $result = MailFormatHelper::htmlToText($html, $allowed_tags);
     $pass = $this->assertEqual($result, $text, String::checkPlain($message));
     $verbose = 'html = <pre>' . $this->stringToHtml($html)
       . '</pre><br />' . 'result = <pre>' . $this->stringToHtml($result)
@@ -66,7 +67,7 @@ protected function assertHtmlToText($html, $text, $message, $allowed_tags = NULL
   }
 
   /**
-   * Test all supported tags of drupal_html_to_text().
+   * Test all supported tags of Drupal\Core\Mail\MailFormatHelper::htmlToText().
    */
   public function testTags() {
     global $base_path, $base_url;
@@ -161,10 +162,10 @@ public function testTags() {
   }
 
   /**
-   * Test $allowed_tags argument of drupal_html_to_text().
+   * Test $allowed_tags argument of Drupal\Core\Mail\MailFormatHelper::htmlToText().
    */
   public function testDrupalHtmlToTextArgs() {
-    // The second parameter of drupal_html_to_text() overrules the allowed tags.
+    // The second parameter of Drupal\Core\Mail\MailFormatHelper::htmlToText() overrules the allowed tags.
     $this->assertHtmlToText(
       'Drupal <b>Drupal</b> Drupal',
       "Drupal *Drupal* Drupal\n",
@@ -234,7 +235,7 @@ public function testDrupalHtmlToTextBlockTagToNewline() {
       . '<ul><li>[ul-li]</li>'
       . '<li>[li-ul]</li></ul>'
       . '[text]';
-    $output = drupal_html_to_text($input);
+    $output = MailFormatHelper::htmlToText($input);
     $pass = $this->assertFalse(
       preg_match('/\][^\n]*\[/s', $output),
       'Block-level HTML tags should force newlines'
@@ -244,7 +245,7 @@ public function testDrupalHtmlToTextBlockTagToNewline() {
     }
     $output_upper = drupal_strtoupper($output);
     $upper_input = drupal_strtoupper($input);
-    $upper_output = drupal_html_to_text($upper_input);
+    $upper_output = MailFormatHelper::htmlToText($upper_input);
     $pass = $this->assertEqual(
       $upper_output,
       $output_upper,
@@ -330,7 +331,7 @@ public function testDrupalHtmlToTextParagraphs() {
   }
 
   /**
-   * Tests that drupal_html_to_text() wraps before 1000 characters.
+   * Tests that Drupal\Core\Mail\MailFormatHelper::htmlToText() wraps before 1000 characters.
    *
    * RFC 3676 says, "The Text/Plain media type is the lowest common
    * denominator of Internet email, with lines of no more than 998 characters."
@@ -343,7 +344,7 @@ public function testDrupalHtmlToTextParagraphs() {
    */
   public function testVeryLongLineWrap() {
     $input = 'Drupal<br /><p>' . str_repeat('x', 2100) . '</><br />Drupal';
-    $output = drupal_html_to_text($input);
+    $output = MailFormatHelper::htmlToText($input);
     $eol = Settings::get('mail_line_endings', PHP_EOL);
 
     $maximum_line_length = 0;
diff --git a/core/modules/system/src/Tests/Mail/MailTest.php b/core/modules/system/src/Tests/Mail/MailTest.php
index 78ebf24..3830f46 100644
--- a/core/modules/system/src/Tests/Mail/MailTest.php
+++ b/core/modules/system/src/Tests/Mail/MailTest.php
@@ -60,7 +60,7 @@ public function testCancelMessage() {
     \Drupal::state()->set('system.test_mail_collector', array());
 
     // Send a test message that simpletest_mail_alter should cancel.
-    drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language_interface->getId());
+    \Drupal::service('plugin.manager.mail')->mail('simpletest', 'cancel_test', 'cancel@example.com', $language_interface->getId());
     // Retrieve sent message.
     $captured_emails = \Drupal::state()->get('system.test_mail_collector');
     $sent_message = end($captured_emails);
@@ -82,7 +82,7 @@ public function testFromAndReplyToHeader() {
     // Send an email with a reply-to address specified.
     $from_email = 'Drupal <simpletest@example.com>';
     $reply_email = 'someone_else@example.com';
-    drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language, array(), $reply_email);
+    \Drupal::service('plugin.manager.mail')->mail('simpletest', 'from_test', 'from_test@example.com', $language, array(), $reply_email);
     // Test that the reply-to email is just the email and not the site name
     // and default sender email.
     $captured_emails = \Drupal::state()->get('system.test_mail_collector');
@@ -92,7 +92,7 @@ public function testFromAndReplyToHeader() {
     $this->assertFalse(isset($sent_message['headers']['Errors-To']), 'Errors-to header must not be set, it is deprecated.');
 
     // Send an email and check that the From-header contains the site name.
-    drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
+    \Drupal::service('plugin.manager.mail')->mail('simpletest', 'from_test', 'from_test@example.com', $language);
     $captured_emails = \Drupal::state()->get('system.test_mail_collector');
     $sent_message = end($captured_emails);
     $this->assertEqual($from_email, $sent_message['headers']['From'], 'Message is sent from the site email account.');
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index bdbc03f..f82e24a 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\Mail\MailFormatHelper;
 use Drupal\Core\Url;
 use Drupal\Core\Utility\UpdateException;
 
@@ -757,23 +758,27 @@ function hook_form_BASE_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterfa
 }
 
 /**
- * Alter an email message created with the drupal_mail() function.
+ * Alter an email message created with the
+ * \Drupal::service('plugin.manager.mail')->mail function.
  *
  * hook_mail_alter() allows modification of email messages created and sent
- * with drupal_mail(). Usage examples include adding and/or changing message
- * text, message fields, and message headers.
+ * with \Drupal::service('plugin.manager.mail')->mail(). Usage examples include
+ * adding and/or changing message text, message fields, and message headers.
  *
- * Email messages sent using functions other than drupal_mail() will not
- * invoke hook_mail_alter(). For example, a contributed module directly
+ * Email messages sent using functions other than
+ * \Drupal::service('plugin.manager.mail')->mail() will not invoke
+ * hook_mail_alter(). For example, a contributed module directly
  * calling the drupal_mail_system()->mail() or PHP mail() function
- * will not invoke this hook. All core modules use drupal_mail() for
- * messaging, it is best practice but not mandatory in contributed modules.
+ * will not invoke this hook. All core modules use
+ * \Drupal::service('plugin.manager.mail')->mail() for messaging, it is best
+ * practice but not mandatory in contributed modules.
  *
  * @param $message
  *   An array containing the message data. Keys in this array include:
  *  - 'id':
- *     The drupal_mail() id of the message. Look at module source code or
- *     drupal_mail() for possible id values.
+ *     The \Drupal::service('plugin.manager.mail')->mail() id of the message.
+ *     Look at module source code or
+ *     \Drupal::service('plugin.manager.mail')->mail() for possible id values.
  *  - 'to':
  *     The address or addresses the message will be sent to. The
  *     formatting of this string must comply with RFC 2822.
@@ -791,15 +796,16 @@ function hook_form_BASE_FORM_ID_alter(&$form, \Drupal\Core\Form\FormStateInterfa
  *     Associative array containing mail headers, such as From, Sender,
  *     MIME-Version, Content-Type, etc.
  *  - 'params':
- *     An array of optional parameters supplied by the caller of drupal_mail()
- *     that is used to build the message before hook_mail_alter() is invoked.
+ *     An array of optional parameters supplied by the caller of
+ *     \Drupal::service('plugin.manager.mail')->mail() that is used to build
+ *     the message before hook_mail_alter() is invoked.
  *  - 'language':
  *     The language object used to build the message before hook_mail_alter()
  *     is invoked.
  *  - 'send':
  *     Set to FALSE to abort sending this email message.
  *
- * @see drupal_mail()
+ * @see \Drupal::service('plugin.manager.mail')->mail()
  */
 function hook_mail_alter(&$message) {
   if ($message['id'] == 'modulename_messagekey') {
@@ -1144,33 +1150,40 @@ function hook_template_preprocess_default_variables_alter(&$variables) {
 }
 
 /**
- * Prepare a message based on parameters; called from drupal_mail().
+ * Prepare a message based on parameters; called from
+ * \Drupal::service('plugin.manager.mail')->mail().
  *
  * Note that hook_mail(), unlike hook_mail_alter(), is only called on the
- * $module argument to drupal_mail(), not all modules.
+ * $module argument to
+ * \Drupal::service('plugin.manager.mail')->mail(), not all modules.
  *
  * @param $key
  *   An identifier of the mail.
  * @param $message
  *   An array to be filled in. Elements in this array include:
- *   - id: An ID to identify the mail sent. Look at module source code
- *     or drupal_mail() for possible id values.
+ *   - id: An ID to identify the mail sent. Look at module source code or
+ *     \Drupal::service('plugin.manager.mail')->mail() for possible id values.
  *   - to: The address or addresses the message will be sent to. The
  *     formatting of this string must comply with RFC 2822.
  *   - subject: Subject of the email to be sent. This must not contain any
- *     newline characters, or the mail may not be sent properly. drupal_mail()
- *     sets this to an empty string when the hook is invoked.
+ *     newline characters, or the mail may not be sent properly.
+ *     \Drupal::service('plugin.manager.mail')->mail() sets this to an empty
+ *     string when the hook is invoked.
  *   - body: An array of lines containing the message to be sent. Drupal will
- *     format the correct line endings for you. drupal_mail() sets this to an
+ *     format the correct line endings for you.
+ *     \Drupal::service('plugin.manager.mail')->mail() sets this to an
  *     empty array when the hook is invoked.
  *   - from: The address the message will be marked as being from, which is
- *     set by drupal_mail() to either a custom address or the site-wide
- *     default email address when the hook is invoked.
+ *     set by \Drupal::service('plugin.manager.mail')->mail() to either a
+ *     custom address or the site-wide default email address when the hook is
+ *     invoked.
  *   - headers: Associative array containing mail headers, such as From,
- *     Sender, MIME-Version, Content-Type, etc. drupal_mail() pre-fills
- *     several headers in this array.
+ *     Sender, MIME-Version, Content-Type, etc.
+ *     \Drupal::service('plugin.manager.mail')->mail() pre-fills several
+ *     headers in this array.
  * @param $params
- *   An array of parameters supplied by the caller of drupal_mail().
+ *   An array of parameters supplied by the caller of
+ *   \Drupal::service('plugin.manager.mail')->mail().
  */
 function hook_mail($key, &$message, $params) {
   $account = $params['account'];
@@ -1208,7 +1221,7 @@ function hook_mail($key, &$message, $params) {
   $subject = strtr($context['subject'], $variables);
   $body = strtr($context['message'], $variables);
   $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
-  $message['body'][] = drupal_html_to_text($body);
+  $message['body'][] = MailFormatHelper::htmlToText($body);
 }
 
 /**
diff --git a/core/modules/text/text.module b/core/modules/text/text.module
index 96dcd8f..0ea98e0 100644
--- a/core/modules/text/text.module
+++ b/core/modules/text/text.module
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 
@@ -98,7 +99,7 @@ function text_summary($text, $format = NULL, $size = NULL) {
   // sentence boundaries.
 
   // The summary may not be longer than maximum length specified. Initial slice.
-  $summary = truncate_utf8($text, $size);
+  $summary = Unicode::truncate($text, $size);
 
   // Store the actual length of the UTF8 string -- which might not be the same
   // as $size.
diff --git a/core/modules/update/update.fetch.inc b/core/modules/update/update.fetch.inc
index fae02d4..135c6d1 100644
--- a/core/modules/update/update.fetch.inc
+++ b/core/modules/update/update.fetch.inc
@@ -82,7 +82,7 @@ function _update_cron_notify() {
         else {
           $target_langcode = $default_langcode;
         }
-        $message = drupal_mail('update', 'status_notify', $target, $target_langcode, $params);
+        $message = \Drupal::service('plugin.manager.mail')->mail('update', 'status_notify', $target, $target_langcode, $params);
         // Track when the last mail was successfully sent to avoid sending
         // too many emails.
         if ($message['result']) {
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index cdfc40c..fa782b9 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -442,7 +442,7 @@ function update_fetch_data_finished($success, $results) {
  *   keys, and the status reason constant (UPDATE_NOT_SECURE, etc) for the
  *   values.
  *
- * @see drupal_mail()
+ * @see \Drupal::service('plugin.manager.mail')->mail()
  * @see _update_cron_notify()
  * @see _update_message_text()
  */
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index c2037de..a9d994f 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1275,7 +1275,7 @@ function user_role_revoke_permissions($rid, array $permissions = array()) {
  * operation happens on the given user account.
  *
  * @see user_mail_tokens()
- * @see drupal_mail()
+ * @see \Drupal::service('plugin.manager.mail')->mail()
  *
  * @param $op
  *   The operation being performed on the account. Possible values:
@@ -1318,11 +1318,11 @@ function _user_mail_notify($op, $account, $langcode = NULL) {
     if (empty($site_mail)) {
       $site_mail = ini_get('sendmail_from');
     }
-    $mail = drupal_mail('user', $op, $account->getEmail(), $langcode, $params, $site_mail);
+    $mail = \Drupal::service('plugin.manager.mail')->mail('user', $op, $account->getEmail(), $langcode, $params, $site_mail);
     if ($op == 'register_pending_approval') {
       // If a user registered requiring admin approval, notify the admin, too.
       // We use the site default language for this.
-      drupal_mail('user', 'register_pending_approval_admin', $site_mail, \Drupal::languageManager()->getDefaultLanguage()->getId(), $params);
+      \Drupal::service('plugin.manager.mail')->mail('user', 'register_pending_approval_admin', $site_mail, \Drupal::languageManager()->getDefaultLanguage()->getId(), $params);
     }
   }
   return empty($mail) ? NULL : $mail['result'];
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index d8ff7ae..de9cac6 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -1060,7 +1060,7 @@ public function getArgumentsTokens() {
        // Use strip tags as there should never be HTML in the path.
        // However, we need to preserve special characters like " that
        // were removed by String::checkPlain().
-      $tokens["!$count"] = isset($this->view->args[$count - 1]) ? strip_tags(decode_entities($this->view->args[$count - 1])) : '';
+      $tokens["!$count"] = isset($this->view->args[$count - 1]) ? strip_tags(String::decodeEntities($this->view->args[$count - 1])) : '';
     }
 
     return $tokens;
diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index 486ef5a..6dc4337 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -1276,7 +1276,7 @@ public function renderText($alter) {
         $more_link_text = $this->options['alter']['more_link_text'] ? $this->options['alter']['more_link_text'] : $this->t('more');
         $more_link_text = strtr(Xss::filterAdmin($more_link_text), $tokens);
         $more_link_path = $this->options['alter']['more_link_path'];
-        $more_link_path = strip_tags(decode_entities(strtr($more_link_path, $tokens)));
+        $more_link_path = strip_tags(String::decodeEntities(strtr($more_link_path, $tokens)));
 
         // Make sure that paths which were run through _url() work as well.
         $base_path = base_path();
@@ -1354,7 +1354,7 @@ protected function renderAsLink($alter, $text, $tokens) {
       // Use strip tags as there should never be HTML in the path.
       // However, we need to preserve special characters like " that
       // were removed by String::checkPlain().
-      $path = strip_tags(decode_entities(strtr($path, $tokens)));
+      $path = strip_tags(String::decodeEntities(strtr($path, $tokens)));
 
       if (!empty($alter['path_case']) && $alter['path_case'] != 'none') {
         $path = $this->caseTransform($path, $this->options['alter']['path_case']);
@@ -1426,7 +1426,7 @@ protected function renderAsLink($alter, $text, $tokens) {
     $alt = strtr($alter['alt'], $tokens);
     // Set the title attribute of the link only if it improves accessibility
     if ($alt && $alt != $text) {
-      $options['attributes']['title'] = decode_entities($alt);
+      $options['attributes']['title'] = String::decodeEntities($alt);
     }
 
     $class = strtr($alter['link_class'], $tokens);
@@ -1514,7 +1514,7 @@ public function getRenderTokens($item) {
       // Use strip tags as there should never be HTML in the path.
       // However, we need to preserve special characters like " that
       // were removed by String::checkPlain().
-      $tokens['!' . $count] = isset($this->view->args[$count - 1]) ? strip_tags(decode_entities($this->view->args[$count - 1])) : '';
+      $tokens['!' . $count] = isset($this->view->args[$count - 1]) ? strip_tags(String::decodeEntities($this->view->args[$count - 1])) : '';
     }
 
     // Get flattened set of tokens for any array depth in query parameters.
@@ -1596,7 +1596,7 @@ protected function getTokenValuesRecursive(array $array, array $parent_keys = ar
       else {
         // Create a token key based on array element structure.
         $token_string = !empty($parent_keys) ? implode('_', $parent_keys) . '_' . $param : $param;
-        $tokens['%' . $token_string] = strip_tags(decode_entities($val));
+        $tokens['%' . $token_string] = strip_tags(String::decodeEntities($val));
       }
     }
 
diff --git a/core/modules/views/src/Plugin/views/field/Links.php b/core/modules/views/src/Plugin/views/field/Links.php
index 5912664..3438447 100644
--- a/core/modules/views/src/Plugin/views/field/Links.php
+++ b/core/modules/views/src/Plugin/views/field/Links.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Plugin\views\field;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url as UrlObject;
 
@@ -77,7 +78,7 @@ protected function getLinks() {
       }
       // Make sure that tokens are replaced for this paths as well.
       $tokens = $this->getRenderTokens(array());
-      $path = strip_tags(decode_entities(strtr($path, $tokens)));
+      $path = strip_tags(String::decodeEntities(strtr($path, $tokens)));
 
       $links[$field] = array(
         'url' => UrlObject::fromUri('base://' . $path),
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index 11ec8b0..3366469 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -1187,7 +1187,7 @@ protected function prepareFilterSelectOptions(&$options) {
       else {
         // Cast the label to a string since it can be an object.
         // @see \Drupal\Core\StringTranslation\TranslationWrapper
-        $options[$value] = strip_tags(decode_entities((string) $label));
+        $options[$value] = strip_tags(UtilityString::decodeEntities((string) $label));
       }
     }
   }
diff --git a/core/modules/views/src/Tests/Handler/FieldWebTest.php b/core/modules/views/src/Tests/Handler/FieldWebTest.php
index 6b76422..a45880c 100644
--- a/core/modules/views/src/Tests/Handler/FieldWebTest.php
+++ b/core/modules/views/src/Tests/Handler/FieldWebTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Tests\Handler;
 
+use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\views\Views;
@@ -226,14 +227,14 @@ public function testAlterUrl() {
       $expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => 'bar', 'bar' => 'baz'], 'absolute' => $absolute]);
       $alter['path'] = 'node/123?foo=bar&bar=baz';
       $result = $id_field->theme($row);
-      $this->assertSubString(decode_entities($result), decode_entities($expected_result));
+      $this->assertSubString(String::decodeEntities($result), String::decodeEntities($expected_result));
 
       // @todo The route-based URL generator strips out NULL attributes.
       // $expected_result = \Drupal::url('entity.node.canonical', ['node' => '123'], ['query' => ['foo' => NULL], 'fragment' => 'bar', 'absolute' => $absolute]);
       $expected_result = \Drupal::urlGenerator()->generateFromPath('node/123', array('query' => array('foo' => NULL), 'fragment' => 'bar', 'absolute' => $absolute));
       $alter['path'] = 'node/123?foo#bar';
       $result = $id_field->theme($row);
-      $this->assertSubString(decode_entities($result), decode_entities($expected_result));
+      $this->assertSubString(String::decodeEntities($result), String::decodeEntities($expected_result));
 
       $expected_result = \Drupal::url('<front>', [], ['absolute' => $absolute]);
       $alter['path'] = '<front>';
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index c5eda99..8e5084c 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views;
 
+use Drupal\Component\Utility\String;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Form\FormState;
 use Drupal\Core\Session\AccountInterface;
@@ -947,7 +948,7 @@ protected function _buildArguments() {
 
         // Add this argument's substitution
         $substitutions['%' . ($position + 1)] = $arg_title;
-        $substitutions['!' . ($position + 1)] = strip_tags(decode_entities($arg));
+        $substitutions['!' . ($position + 1)] = strip_tags(String::decodeEntities($arg));
 
         // Test to see if we should use this argument's title
         if (!empty($argument->options['title_enable']) && !empty($argument->options['title'])) {
diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc
index ebef6f8..8b5ea61 100644
--- a/core/modules/views/views.theme.inc
+++ b/core/modules/views/views.theme.inc
@@ -865,7 +865,7 @@ function template_preprocess_views_view_rss(&$variables) {
   // The RSS 2.0 "spec" doesn't indicate HTML can be used in the description.
   // We strip all HTML tags, but need to prevent double encoding from properly
   // escaped source data (such as &amp becoming &amp;amp;).
-  $variables['description'] = String::checkPlain(decode_entities(strip_tags($style->getDescription())));
+  $variables['description'] = String::checkPlain(String::decodeEntities(strip_tags($style->getDescription())));
 
   if ($view->display_handler->getOption('sitename_title')) {
     $title = $config->get('name');
