diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index ff20f28..dffcc68 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -518,7 +518,7 @@ function drupal_serve_page_from_cache(Response $response, Request $request) {
  * variable text such as user names or link URLs into translated text. Variable
  * substitution looks like this:
  * @code
- * $text = t("@name's blog", array('@name' => user_format_name($account)));
+ * $text = t("@name's blog", array('@name' => $account->getDisplayName()));
  * @endcode
  * Basically, you can put variables like @name into your string, and t() will
  * substitute their sanitized values at translation time. (See the
diff --git a/core/lib/Drupal/Core/Session/AccountInterface.php b/core/lib/Drupal/Core/Session/AccountInterface.php
index ede2854..eb7221f 100644
--- a/core/lib/Drupal/Core/Session/AccountInterface.php
+++ b/core/lib/Drupal/Core/Session/AccountInterface.php
@@ -120,24 +120,27 @@ public function getPreferredLangcode($fallback_to_default = TRUE);
   public function getPreferredAdminLangcode($fallback_to_default = TRUE);
 
   /**
-   * Returns the username of this account.
+   * Returns the unique username of this account.
    *
-   * By default, the passed-in object's 'name' property is used if it exists, or
-   * else, the site-defined value for the 'anonymous' variable. However, a module
-   * may override this by implementing
-   * hook_user_format_name_alter(&$name, $account).
-   *
-   * @see hook_user_format_name_alter()
-   *
-   * @return
-   *   An unsanitized string with the username to display. The code receiving
-   *   this result must ensure that \Drupal\Component\Utility\String::checkPlain()
-   *   is called on it before it is
-   *   printed to the page.
+   * @return string
+   *   An unsanitized string with the unique username. The code receiving this
+   *   result must ensure that \Drupal\Component\Utility\String::checkPlain()
+   *   is called on it before it is printed to the page.
    */
   public function getUsername();
 
   /**
+   * Returns the display name of this account.
+   *
+   * @return string
+   *   An unsanitized string with the user name to display. The code receiving
+   *   this result must ensure that
+   *   \Drupal\Component\Utility\String::checkPlain() is called on it before it
+   *   is printed to the page or used in a template.
+   */
+  public function getDisplayName();
+
+  /**
    * Returns the email address of this account.
    *
    * @return string
diff --git a/core/lib/Drupal/Core/Session/AccountProxy.php b/core/lib/Drupal/Core/Session/AccountProxy.php
index f9d0d35..8349e03 100644
--- a/core/lib/Drupal/Core/Session/AccountProxy.php
+++ b/core/lib/Drupal/Core/Session/AccountProxy.php
@@ -168,6 +168,14 @@ public function getUsername() {
   /**
    * {@inheritdoc}
    */
+  public function getDisplayName() {
+    return $this->getAccount()->getDisplayName();
+  }
+
+
+  /**
+   * {@inheritdoc}
+   */
   public function getEmail() {
     return $this->getAccount()->getEmail();
   }
diff --git a/core/modules/action/src/Plugin/Action/EmailAction.php b/core/modules/action/src/Plugin/Action/EmailAction.php
index d93152d..acb35c7 100644
--- a/core/modules/action/src/Plugin/Action/EmailAction.php
+++ b/core/modules/action/src/Plugin/Action/EmailAction.php
@@ -162,7 +162,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#default_value' => $this->configuration['message'],
       '#cols' => '80',
       '#rows' => '20',
-      '#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
+      '#description' => t('The message that should be sent. You may include placeholders like [node:title], [user:display-name], [user:name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
     );
     return $form;
   }
diff --git a/core/modules/action/src/Plugin/Action/MessageAction.php b/core/modules/action/src/Plugin/Action/MessageAction.php
index c87b606..c8ddd4a 100644
--- a/core/modules/action/src/Plugin/Action/MessageAction.php
+++ b/core/modules/action/src/Plugin/Action/MessageAction.php
@@ -78,7 +78,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#default_value' => $this->configuration['message'],
       '#required' => TRUE,
       '#rows' => '8',
-      '#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:name], and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
+      '#description' => t('The message to be displayed to the current user. You may include placeholders like [node:title], [user:display-name], [user:name] and [comment:body] to represent data that will be different each time message is sent. Not all placeholders will be available in all contexts.'),
     );
     return $form;
   }
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index e4b674f..7a68ee4 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -584,23 +584,7 @@ function comment_preview(CommentInterface $comment, FormStateInterface $form_sta
   $entity = $comment->getCommentedEntity();
 
   if (!$form_state->getErrors()) {
-    // Attach the user and time information.
-    $author_name = $comment->getAuthorName();
-    if (!empty($author_name)) {
-      $account = user_load_by_name($author_name);
-    }
-    elseif (\Drupal::currentUser()->isAuthenticated() && empty($comment->is_anonymous)) {
-      $account = \Drupal::currentUser();
-    }
-
-    if (!empty($account) && $account->isAuthenticated()) {
-      $comment->setOwner($account);
-      $comment->setAuthorName(String::checkPlain($account->getUsername()));
-    }
-    elseif (empty($author_name)) {
-      $comment->setAuthorName(\Drupal::config('user.settings')->get('anonymous'));
-    }
-
+    // Attach the time information.
     $created_time = !is_null($comment->getCreatedTime()) ? $comment->getCreatedTime() : REQUEST_TIME;
     $comment->setCreatedTime($created_time);
     $comment->changed->value = REQUEST_TIME;
diff --git a/core/modules/comment/src/CommentForm.php b/core/modules/comment/src/CommentForm.php
index fbb7442..d215a82 100644
--- a/core/modules/comment/src/CommentForm.php
+++ b/core/modules/comment/src/CommentForm.php
@@ -207,6 +207,12 @@ public function form(array $form, FormStateInterface $form_state) {
       '#value' => ($comment->id() ? !$comment->getOwnerId() : $this->currentUser->isAnonymous()),
     );
 
+    // Set the uid on new comments to the current user.
+    $form['uid'] = array(
+      '#type' => 'value',
+      '#value' => $comment->id() ? $comment->getOwnerId() : $this->currentUser->id(),
+    );
+
     return parent::form($form, $form_state, $comment);
   }
 
@@ -298,13 +304,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     parent::submitForm($form, $form_state);
     /** @var \Drupal\comment\CommentInterface $comment */
     $comment = $this->entity;
-    // If the comment was posted by a registered user, assign the author's ID.
-    // @todo Too fragile. Should be prepared and stored in comment_form()
-    // already.
-    $author_name = $comment->getAuthorName();
-    if (!$comment->is_anonymous && !empty($author_name) && ($account = user_load_by_name($author_name))) {
-      $comment->setOwner($account);
-    }
+
     // If the comment was posted by an anonymous user and no author name was
     // required, use "Anonymous" by default.
     if ($comment->is_anonymous && (!isset($author_name) || $author_name === '')) {
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 99ac31f..b1e28f7 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -98,7 +98,7 @@ function contact_mail($key, &$message, $params) {
     '!subject' => $contact_message->getSubject(),
     '!form' => !empty($params['contact_form']) ? $params['contact_form']->label() : NULL,
     '!form-url' => \Drupal::url('<current>', [], ['absolute' => TRUE, 'language' => $language]),
-    '!sender-name' => user_format_name($sender),
+    '!sender-name' => $sender->getDisplayName(),
   );
   if ($sender->isAuthenticated()) {
     $variables['!sender-url'] = $sender->url('canonical', array('absolute' => TRUE, 'language' => $language));
@@ -126,7 +126,7 @@ function contact_mail($key, &$message, $params) {
     case 'user_mail':
     case 'user_copy':
       $variables += array(
-        '!recipient-name' => user_format_name($params['recipient']),
+        '!recipient-name' => $params['recipient']->getDisplayName(),
         '!recipient-edit-url' => $params['recipient']->url('edit-form', array('absolute' => TRUE, 'language' => $language)),
       );
       $message['subject'] .= t('[!site-name] !subject', $variables, $options);
diff --git a/core/modules/contact/src/Controller/ContactController.php b/core/modules/contact/src/Controller/ContactController.php
index cffbf5a..a90cd64 100644
--- a/core/modules/contact/src/Controller/ContactController.php
+++ b/core/modules/contact/src/Controller/ContactController.php
@@ -128,7 +128,7 @@ public function contactPersonalPage(UserInterface $user) {
     ));
 
     $form = $this->entityFormBuilder()->getForm($message);
-    $form['#title'] = $this->t('Contact @username', array('@username' => $user->getUsername()));
+    $form['#title'] = $this->t('Contact @username', array('@username' => $user->getDisplayName()));
     return $form;
   }
 
diff --git a/core/modules/file/src/Tests/FileFieldPathTest.php b/core/modules/file/src/Tests/FileFieldPathTest.php
index bf166ed..6bbf697 100644
--- a/core/modules/file/src/Tests/FileFieldPathTest.php
+++ b/core/modules/file/src/Tests/FileFieldPathTest.php
@@ -46,7 +46,7 @@ function testUploadPath() {
 
     // Check the path when used with tokens.
     // Change the path to contain multiple token directories.
-    $this->updateFileField($field_name, $type_name, array('file_directory' => '[current-user:uid]/[current-user:name]'));
+    $this->updateFileField($field_name, $type_name, array('file_directory' => '[current-user:uid]/[current-user:display-name]'));
 
     // Upload a new file into the token subdirectories.
     $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
diff --git a/core/modules/file/src/Tests/FileTokenReplaceTest.php b/core/modules/file/src/Tests/FileTokenReplaceTest.php
index 84d599f..8c01e07 100644
--- a/core/modules/file/src/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/src/Tests/FileTokenReplaceTest.php
@@ -54,7 +54,7 @@ function testFileTokenReplacement() {
     $tests['[file:created:short]'] = format_date($file->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
     $tests['[file:changed]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->getId());
     $tests['[file:changed:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->getId());
-    $tests['[file:owner]'] = String::checkPlain(user_format_name($this->admin_user));
+    $tests['[file:owner]'] = String::checkPlain($this->admin_user->getDisplayName());
     $tests['[file:owner:uid]'] = $file->getOwnerId();
 
     // Test to make sure that we generated something for each token.
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index 19db072..fef3893 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -484,7 +484,7 @@ function template_preprocess_forums(&$variables) {
         }
         $forum_submitted = array('#theme' => 'forum_submitted', '#topic' => (object) array(
           'uid' => $topic->getOwnerId(),
-          'name' => $topic->getOwner()->getUsername(),
+          'name' => $topic->getOwner()->getDisplayName(),
           'created' => $topic->getCreatedTime(),
         ));
         $variables['topics'][$id]->submitted = drupal_render($forum_submitted);
diff --git a/core/modules/node/src/Plugin/views/row/Rss.php b/core/modules/node/src/Plugin/views/row/Rss.php
index 0b1acac..0a03d0b 100644
--- a/core/modules/node/src/Plugin/views/row/Rss.php
+++ b/core/modules/node/src/Plugin/views/row/Rss.php
@@ -123,7 +123,7 @@ public function render($row) {
       ),
       array(
         'key' => 'dc:creator',
-        'value' => $node->getOwner()->getUsername(),
+        'value' => $node->getOwner()->getDisplayName(),
       ),
       array(
         'key' => 'guid',
diff --git a/core/modules/rdf/rdf.module b/core/modules/rdf/rdf.module
index 50b6f36..007cf16 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -362,7 +362,7 @@ function rdf_preprocess_user(&$variables) {
         '#attributes' => array(
           'about' => $account->url(),
           'property' => $name_mapping['properties'],
-          'content' => $account->getUsername(),
+          'content' => $account->getDisplayName(),
           'lang' => '',
         ),
       );
diff --git a/core/modules/shortcut/src/Form/SwitchShortcutSet.php b/core/modules/shortcut/src/Form/SwitchShortcutSet.php
index 496fa07..faac03a 100644
--- a/core/modules/shortcut/src/Form/SwitchShortcutSet.php
+++ b/core/modules/shortcut/src/Form/SwitchShortcutSet.php
@@ -198,7 +198,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       ));
       $set->save();
       $replacements = array(
-        '%user' => $this->user->label(),
+        '%user' => $this->user->getDisplayName(),
         '%set_name' => $set->label(),
         '@switch-url' => $this->url($this->routeMatch->getRouteName(), array('user' => $this->user->id())),
       );
@@ -220,7 +220,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       /* @var \Drupal\shortcut\Entity\ShortcutSet $set */
       $set = $this->shortcutSetStorage->load($form_state->getValue('set'));
       $replacements = array(
-        '%user' => $this->user->label(),
+        '%user' => $this->user->getDisplayName(),
         '%set_name' => $set->label(),
       );
       drupal_set_message($account_is_user ? $this->t('You are now using the %set_name shortcut set.', $replacements) : $this->t('%user is now using the %set_name shortcut set.', $replacements));
diff --git a/core/modules/user/config/install/user.mail.yml b/core/modules/user/config/install/user.mail.yml
index 436ff53..cea80f6 100644
--- a/core/modules/user/config/install/user.mail.yml
+++ b/core/modules/user/config/install/user.mail.yml
@@ -1,28 +1,28 @@
 cancel_confirm:
-  body: "[user:name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n--  [site:name] team"
-  subject: 'Account cancellation request for [user:name] at [site:name]'
+  body: "[user:display-name],\n\nA request to cancel your account has been made at [site:name].\n\nYou may now cancel your account on [site:url-brief] by clicking this link or copying and pasting it into your browser:\n\n[user:cancel-url]\n\nNOTE: The cancellation of your account is not reversible.\n\nThis link expires in one day and nothing will happen if it is not used.\n\n--  [site:name] team"
+  subject: 'Account cancellation request for [user:display-name] at [site:name]'
 password_reset:
-  body: "[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n--  [site:name] team"
-  subject: 'Replacement login information for [user:name] at [site:name]'
+  body: "[user:display-name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYou may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password. It expires after one day and nothing will happen if it's not used.\n\n--  [site:name] team"
+  subject: 'Replacement login information for [user:display-name] at [site:name]'
 register_admin_created:
-  body: "[user:name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
+  body: "[user:display-name],\n\nA site administrator at [site:name] has created an account for you. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
   subject: 'An administrator created an account for you at [site:name]'
 register_no_approval_required:
-  body: "[user:name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
-  subject: 'Account details for [user:name] at [site:name]'
+  body: "[user:display-name],\n\nThank you for registering at [site:name]. You may now log in by clicking this link or copying and pasting it to your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
+  subject: 'Account details for [user:display-name] at [site:name]'
 register_pending_approval:
-  body: "[user:name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n--  [site:name] team"
-  subject: 'Account details for [user:name] at [site:name] (pending admin approval)'
+  body: "[user:display-name],\n\nThank you for registering at [site:name]. Your application for an account is currently pending approval. Once it has been approved, you will receive another email containing information about how to log in, set your password, and other details.\n\n\n--  [site:name] team"
+  subject: 'Account details for [user:display-name] at [site:name] (pending admin approval)'
 register_pending_approval_admin:
-  body: "[user:name] has applied for an account.\n\n[user:edit-url]"
-  subject: 'Account details for [user:name] at [site:name] (pending admin approval)'
+  body: "[user:display-name] has applied for an account.\n\n[user:edit-url]"
+  subject: 'Account details for [user:display-name] at [site:name] (pending admin approval)'
 status_activated:
-  body: "[user:name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
-  subject: 'Account details for [user:name] at [site:name] (approved)'
+  body: "[user:display-name],\n\nYour account at [site:name] has been activated.\n\nYou may now log in by clicking this link or copying and pasting it into your browser:\n\n[user:one-time-login-url]\n\nThis link can only be used once to log in and will lead you to a page where you can set your password.\n\nAfter setting your password, you will be able to log in at [site:login-url] in the future using:\n\nusername: [user:name]\npassword: Your password\n\n--  [site:name] team"
+  subject: 'Account details for [user:display-name] at [site:name] (approved)'
 status_blocked:
-  body: "[user:name],\n\nYour account on [site:name] has been blocked.\n\n--  [site:name] team"
-  subject: 'Account details for [user:name] at [site:name] (blocked)'
+  body: "[user:name],\n\nYour account on [site:display-name] has been blocked.\n\n--  [site:name] team"
+  subject: 'Account details for [user:display-name] at [site:name] (blocked)'
 status_canceled:
-  body: "[user:name],\n\nYour account on [site:name] has been canceled.\n\n--  [site:name] team"
-  subject: 'Account details for [user:name] at [site:name] (canceled)'
+  body: "[user:display-name],\n\nYour account on [site:name] has been canceled.\n\n--  [site:name] team"
+  subject: 'Account details for [user:display-name] at [site:name] (canceled)'
 langcode: en
diff --git a/core/modules/user/src/AccountSettingsForm.php b/core/modules/user/src/AccountSettingsForm.php
index bce6a60..478b124 100644
--- a/core/modules/user/src/AccountSettingsForm.php
+++ b/core/modules/user/src/AccountSettingsForm.php
@@ -185,7 +185,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     );
     // These email tokens are shared for all settings, so just define
     // the list once to help ensure they stay in sync.
-    $email_token_help = $this->t('Available variables are: [site:name], [site:url], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
+    $email_token_help = $this->t('Available variables are: [site:name], [site:url], [user:display-name], [user:name], [user:mail], [site:login-url], [site:url-brief], [user:edit-url], [user:one-time-login-url], [user:cancel-url].');
 
     $form['email_admin_created'] = array(
       '#type' => 'details',
diff --git a/core/modules/user/src/Controller/UserController.php b/core/modules/user/src/Controller/UserController.php
index 51fe046..ace4225 100644
--- a/core/modules/user/src/Controller/UserController.php
+++ b/core/modules/user/src/Controller/UserController.php
@@ -159,7 +159,7 @@ public function userPage() {
    *   The user account name.
    */
   public function userTitle(UserInterface $user = NULL) {
-    return $user ? Xss::filter($user->getUsername()) : '';
+    return $user ? Xss::filter($user->getDisplayName()) : '';
   }
 
   /**
diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php
index 99c91db..d6554df 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -420,7 +420,16 @@ public function isAnonymous() {
    * {@inheritdoc}
    */
   public function getUsername() {
-    $name = $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
+    $name = $this->get('name')->value ?: '';;
+    \Drupal::moduleHandler()->alter('user_format_name', $name, $this);
+    return $name;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDisplayName() {
+    $name = $this->getUsername() ?: \Drupal::config('user.settings')->get('anonymous');
     \Drupal::moduleHandler()->alter('user_format_name', $name, $this);
     return $name;
   }
diff --git a/core/modules/user/src/Form/UserPasswordResetForm.php b/core/modules/user/src/Form/UserPasswordResetForm.php
index 69b4588..c6e8c56 100644
--- a/core/modules/user/src/Form/UserPasswordResetForm.php
+++ b/core/modules/user/src/Form/UserPasswordResetForm.php
@@ -71,11 +71,11 @@ public function getFormID() {
    */
   public function buildForm(array $form, FormStateInterface $form_state, AccountInterface $user = NULL, $expiration_date = NULL, $timestamp = NULL, $hash = NULL) {
     if ($expiration_date) {
-      $form['message'] = array('#markup' => $this->t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $user->getUsername(), '%expiration_date' => $expiration_date)));
+      $form['message'] = array('#markup' => $this->t('<p>This is a one-time login for %user_name and will expire on %expiration_date.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $user->getDisplayName(), '%expiration_date' => $expiration_date)));
     }
     else {
       // No expiration for first time login.
-      $form['message'] = array('#markup' => $this->t('<p>This is a one-time login for %user_name.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $user->getUsername())));
+      $form['message'] = array('#markup' => $this->t('<p>This is a one-time login for %user_name.</p><p>Click on this button to log in to the site and change your password.</p>', array('%user_name' => $user->getDisplayName())));
     }
 
     $form['#title'] = 'Reset Password';
@@ -103,7 +103,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
     /** @var $user \Drupal\user\UserInterface */
     $user = $form_state->getValue('user');
     user_login_finalize($user);
-    $this->logger->notice('User %name used one-time login link at time %timestamp.', array('%name' => $user->getUsername(), '%timestamp' => $form_state->getValue('timestamp')));
+    $this->logger->notice('User %name used one-time login link at time %timestamp.', array('%name' => $user->getDisplayName(), '%timestamp' => $form_state->getValue('timestamp')));
     drupal_set_message($this->t('You have just used your one-time login link. It is no longer necessary to use this link to log in. Please change your password.'));
     // Let the user's password be changed without the current password check.
     $token = Crypt::randomBytesBase64(55);
diff --git a/core/modules/user/src/Plugin/Search/UserSearch.php b/core/modules/user/src/Plugin/Search/UserSearch.php
index cee66e8..fcccc99 100644
--- a/core/modules/user/src/Plugin/Search/UserSearch.php
+++ b/core/modules/user/src/Plugin/Search/UserSearch.php
@@ -148,7 +148,7 @@ public function execute() {
 
     foreach ($accounts as $account) {
       $result = array(
-        'title' => $account->getUsername(),
+        'title' => $account->getDisplayName(),
         'link' => $account->url('canonical', array('absolute' => TRUE)),
       );
       if ($this->currentUser->hasPermission('administer users')) {
diff --git a/core/modules/user/src/Plugin/views/field/Name.php b/core/modules/user/src/Plugin/views/field/Name.php
index 0d5a768..0e816ba 100644
--- a/core/modules/user/src/Plugin/views/field/Name.php
+++ b/core/modules/user/src/Plugin/views/field/Name.php
@@ -24,18 +24,8 @@
 class Name extends User {
 
   /**
-   * Overrides \Drupal\user\Plugin\views\field\User::init().
-   *
-   * Add uid in the query so we can test for anonymous if needed.
+   * {@inheritdoc}
    */
-  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
-    parent::init($view, $display, $options);
-
-    if (!empty($this->options['overwrite_anonymous']) || !empty($this->options['format_username'])) {
-      $this->additional_fields['uid'] = 'uid';
-    }
-  }
-
   protected function defineOptions() {
     $options = parent::defineOptions();
 
@@ -80,26 +70,29 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    * {@inheritdoc}
    */
   protected function renderLink($data, ResultRow $values) {
-    $account = entity_create('user');
-    $account->uid = $this->getValue($values, 'uid');
-    $account->name = $this->getValue($values);
-    if (!empty($this->options['link_to_user']) || !empty($this->options['overwrite_anonymous'])) {
-      if (!empty($this->options['overwrite_anonymous']) && !$account->id()) {
-        // This is an anonymous user, and we're overriting the text.
+    $account = $this->getEntity($values);
+
+    if (!empty($this->options['overwrite_anonymous']) && !$account->id()) {
+        // This is an anonymous user, and we're overwriting the text.
         return String::checkPlain($this->options['anonymous_text']);
-      }
-      elseif (!empty($this->options['link_to_user'])) {
-        $account->name = $this->getValue($values);
+    }
+
+    if (!empty($this->options['link_to_user'])) {
+      if (!empty($this->options['format_username'])) {
         $username = array(
           '#theme' => 'username',
           '#account' => $account,
         );
         return drupal_render($username);
       }
+      else {
+        return parent::renderLink($data, $values);
+      }
     }
+
     // If we want a formatted username, do that.
     if (!empty($this->options['format_username'])) {
-      return user_format_name($account);
+      return $account->getDisplayName();
     }
     // Otherwise, there's no special handling, so return the data directly.
     return $data;
diff --git a/core/modules/user/src/Tests/UserEditedOwnAccountTest.php b/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
index bee1a9b..75e0418 100644
--- a/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
+++ b/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
@@ -15,6 +15,12 @@
  * @group user
  */
 class UserEditedOwnAccountTest extends WebTestBase {
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('user_form_test');
 
   function testUserEditedOwnAccount() {
     // Change account setting 'Who can register accounts?' to Administrators
diff --git a/core/modules/user/src/Tests/UserEntityCallbacksTest.php b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
index 5c4e93c..bb1c444 100644
--- a/core/modules/user/src/Tests/UserEntityCallbacksTest.php
+++ b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
@@ -22,12 +22,13 @@ class UserEntityCallbacksTest extends WebTestBase {
    *
    * @var array
    */
-  public static $modules = array('user');
+  public static $modules = array('user', 'user_name_test');
 
   /**
    * @var \Drupal\user\UserInterface
    */
   protected $account;
+  protected $anonymous;
 
   protected function setUp() {
     parent::setUp();
@@ -46,6 +47,13 @@ function testLabelCallback() {
     $name = $this->randomMachineName();
     $this->config('user.settings')->set('anonymous', $name)->save();
     $this->assertEqual($this->anonymous->label(), $name, 'The variable anonymous should be used for name of uid 0');
+    $this->assertEqual($this->anonymous->getUserName(), '', 'The raw anonymous user name should be empty string');
+
+    // Set to test the altered username.
+    \Drupal::state()->set('user_name_test_altered_name', 'altered');
+
+    $this->assertEqual($this->account->getDisplayName(), $this->account->name->value . 'altered', 'The user display name should be altered.');
+    $this->assertEqual($this->account->getUsername(), $this->account->name->value, 'The user name should not be altered.');
   }
 
   /**
diff --git a/core/modules/user/src/Tests/UserTokenReplaceTest.php b/core/modules/user/src/Tests/UserTokenReplaceTest.php
index 897e2aa..7219b25 100644
--- a/core/modules/user/src/Tests/UserTokenReplaceTest.php
+++ b/core/modules/user/src/Tests/UserTokenReplaceTest.php
@@ -55,7 +55,8 @@ function testUserTokenReplacement() {
     // Generate and test sanitized tokens.
     $tests = array();
     $tests['[user:uid]'] = $account->id();
-    $tests['[user:name]'] = String::checkPlain(user_format_name($account));
+    $tests['[user:display-name]'] = String::checkPlain($account->getDisplayName());
+    $tests['[user:name]'] = String::checkPlain($account->getUsername());
     $tests['[user:mail]'] = String::checkPlain($account->getEmail());
     $tests['[user:url]'] = $account->url('canonical', $url_options);
     $tests['[user:edit-url]'] = $account->url('edit-form', $url_options);
@@ -63,7 +64,8 @@ function testUserTokenReplacement() {
     $tests['[user:last-login:short]'] = format_date($account->getLastLoginTime(), 'short', '', NULL, $language_interface->getId());
     $tests['[user:created]'] = format_date($account->getCreatedTime(), 'medium', '', NULL, $language_interface->getId());
     $tests['[user:created:short]'] = format_date($account->getCreatedTime(), 'short', '', NULL, $language_interface->getId());
-    $tests['[current-user:name]'] = String::checkPlain(user_format_name($global_account));
+    $tests['[current-user:display-name]'] = String::checkPlain($global_account->getDisplayName());
+    $tests['[current-user:name]'] = String::checkPlain($global_account->getUsername());
 
     // Test to make sure that we generated something for each token.
     $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
@@ -74,9 +76,11 @@ function testUserTokenReplacement() {
     }
 
     // Generate and test unsanitized tokens.
-    $tests['[user:name]'] = user_format_name($account);
+    $tests['[user:display-name]'] = $account->getDisplayName();
+    $tests['[user:name]'] = $account->getUsername();
     $tests['[user:mail]'] = $account->getEmail();
-    $tests['[current-user:name]'] = user_format_name($global_account);
+    $tests['[current-user:display-name]'] = $global_account->getDisplayName();
+    $tests['[current-user:name]'] = $global_account->getUsername();
 
     foreach ($tests as $input => $expected) {
       $output = $token_service->replace($input, array('user' => $account), array('langcode' => $language_interface->getId(), 'sanitize' => FALSE));
diff --git a/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php b/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
index c0067c9..4b1ce2b 100644
--- a/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
+++ b/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
@@ -25,28 +25,27 @@ class HandlerFieldUserNameTest extends UserTestBase {
   public static $testViews = array('test_views_handler_field_user_name');
 
   public function testUserName() {
-    $this->drupalLogin($this->drupalCreateUser(array('access user profiles')));
+    $new_user = $this->drupalCreateUser(array('access user profiles'));
+    $this->drupalLogin($new_user);
 
     $view = Views::getView('test_views_handler_field_user_name');
     $this->executeView($view);
 
     $view->field['name']->options['link_to_user'] = TRUE;
-    $username = $view->result[0]->users_field_data_name = $this->randomMachineName();
-    $view->result[0]->users_field_data_uid = 1;
-    $render = $view->field['name']->advancedRender($view->result[0]);
+    $username = $view->result[3]->users_field_data_name;
+    $render = $view->field['name']->advancedRender($view->result[3]);
     $this->assertTrue(strpos($render, $username) !== FALSE, 'If link to user is checked the username should be part of the output.');
-    $this->assertTrue(strpos($render, 'user/1') !== FALSE, 'If link to user is checked the link to the user should appear as well.');
+    $this->assertTrue(strpos($render, 'user/' . $new_user->id()) !== FALSE, 'If link to user is checked the link to the user should appear as well.');
+    $view->destroy();
+    $this->executeView($view);
 
     $view->field['name']->options['link_to_user'] = FALSE;
-    $username = $view->result[0]->users_field_data_name = $this->randomMachineName();
-    $view->result[0]->users_field_data_uid = 1;
-    $render = $view->field['name']->advancedRender($view->result[0]);
+    $username = $view->result[2]->users_field_data_name;
+    $render = $view->field['name']->advancedRender($view->result[2]);
     $this->assertIdentical($render, $username, 'If the user is not linked the username should be printed out for a normal user.');
 
-    $view->result[0]->users_field_data_uid = 0;
-    $anon_name = $this->config('user.settings')->get('anonymous');
-    $view->result[0]->users_field_data_name = '';
     $render = $view->field['name']->advancedRender($view->result[0]);
+    $anon_name = \Drupal::config('user.settings')->get('anonymous');
     $this->assertIdentical($render, $anon_name , 'For user0 it should use the default anonymous name by default.');
 
     $view->field['name']->options['overwrite_anonymous'] = TRUE;
diff --git a/core/modules/user/src/UserAutocomplete.php b/core/modules/user/src/UserAutocomplete.php
index cb75d5b..f180041 100644
--- a/core/modules/user/src/UserAutocomplete.php
+++ b/core/modules/user/src/UserAutocomplete.php
@@ -84,7 +84,7 @@ public function getMatches($string, $include_anonymous = FALSE) {
 
       $controller = $this->entityManager->getStorage('user');
       foreach ($controller->loadMultiple($uids) as $account) {
-        $matches[] = array('value' => $account->getUsername(), 'label' => String::checkPlain($account->getUsername()));
+        $matches[] = array('value' => $account->getUsername(), 'label' => String::checkPlain($account->getDisplayName()));
       }
     }
 
diff --git a/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml b/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml
new file mode 100644
index 0000000..8a5e1cc
--- /dev/null
+++ b/core/modules/user/tests/modules/user_name_test/user_name_test.info.yml
@@ -0,0 +1,7 @@
+name: 'User name tests'
+type: module
+description: 'Support module for user name testing.'
+package: Testing
+version: VERSION
+core: 8.x
+hidden: true
diff --git a/core/modules/user/tests/modules/user_name_test/user_name_test.module b/core/modules/user/tests/modules/user_name_test/user_name_test.module
new file mode 100644
index 0000000..2d791a8
--- /dev/null
+++ b/core/modules/user/tests/modules/user_name_test/user_name_test.module
@@ -0,0 +1,12 @@
+<?php
+/**
+ *  * @file
+ *   * User name tests bootstrap file.
+ *    */
+
+/**
+ *  * Implements hook_user_format_name_alter().
+ *   */
+function user_name_test_user_format_name_alter(&$name, $account) {
+  $name .= \Drupal::state()->get('user_name_test_altered_name');
+  }
diff --git a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
index 9a9bac5..78bf41a 100644
--- a/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
+++ b/core/modules/user/tests/modules/user_test_views/test_views/views.view.test_views_handler_field_user_name.yml
@@ -52,6 +52,21 @@ display:
         type: default
       row:
         type: fields
+      sorts:
+        uid:
+          id: uid
+          table: users
+          field: uid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          order: ASC
+          exposed: false
+          expose:
+            label: ''
+          plugin_id: standard
+          entity_type: user
+          entity_field: uid
       field_langcode: '***LANGUAGE_language_content***'
       field_langcode_add_to_query: null
     display_plugin: default
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index 928a56a..cc7812e 100644
--- a/core/modules/user/user.api.php
+++ b/core/modules/user/user.api.php
@@ -107,17 +107,17 @@ function hook_user_cancel_methods_alter(&$methods) {
 /**
  * Alter the username that is displayed for a user.
  *
- * Called by user_format_name() to allow modules to alter the username that's
+ * Called by $user->getDisplayName() to allow modules to alter the username that's
  * displayed. Can be used to ensure user privacy in situations where
  * $account->name is too revealing.
  *
  * @param $name
- *   The string that user_format_name() will return.
+ *   The string that $user->getDisplayName() will return.
  *
  * @param $account
- *   The account object passed to user_format_name().
+ *   The account object.
  *
- * @see user_format_name()
+ * @see $account->getDisplayName()
  */
 function hook_user_format_name_alter(&$name, $account) {
   // Display the user's uid instead of name.
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index fa26302..87377db 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -465,7 +465,7 @@ function user_preprocess_block(&$variables) {
 /**
  * Format a username.
  *
- * @param \Drupal\Core\Session\Interface $account
+ *   Use \Drupal\Core\Session\AccountInterface::getDisplayName().
  *   The account object for the user whose name is to be formatted.
  *
  * @return
@@ -477,7 +477,7 @@ function user_preprocess_block(&$variables) {
  *   Use \Drupal\Core\Session\Interface::getUsername().
  */
 function user_format_name(AccountInterface $account) {
-  return $account->getUsername();
+  return $account->getDisplayName();
 }
 
 /**
@@ -533,7 +533,9 @@ function template_preprocess_username(&$variables) {
   // unsanitized version, in case other preprocess functions want to implement
   // their own shortening logic or add markup. If they do so, they must ensure
   // that $variables['name'] is safe for printing.
-  $name = $variables['name_raw'] = $account->getUsername();
+  $name  = $account->getDisplayName();
+  $variables['name_raw'] = $account->getUsername();
+
   if (Unicode::strlen($name) > 20) {
     $name = Unicode::truncate($name, 15, FALSE, TRUE);
     $variables['truncated'] = TRUE;
@@ -812,8 +814,8 @@ function _user_cancel($edit, $account, $method) {
       }
       $account->block();
       $account->save();
-      drupal_set_message(t('%name has been disabled.', array('%name' => $account->getUsername())));
-      $logger->notice('Blocked user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'));
+      drupal_set_message(t('%name has been disabled.', array('%name' => $account->getDisplayName())));
+      $logger->notice('Blocked user: %name %email.', array('%name' => $account->getDisplayName(), '%email' => '<' . $account->getEmail() . '>'));
       break;
 
     case 'user_cancel_reassign':
@@ -823,8 +825,8 @@ function _user_cancel($edit, $account, $method) {
         _user_mail_notify('status_canceled', $account);
       }
       $account->delete();
-      drupal_set_message(t('%name has been deleted.', array('%name' => $account->getUsername())));
-      $logger->notice('Deleted user: %name %email.', array('%name' => $account->getUsername(), '%email' => '<' . $account->getEmail() . '>'));
+      drupal_set_message(t('%name has been deleted.', array('%name' => $account->getDisplayName())));
+      $logger->notice('Deleted user: %name %email.', array('%name' => $account->getDisplayName(), '%email' => '<' . $account->getEmail() . '>'));
       break;
   }
 
@@ -1446,7 +1448,7 @@ function user_toolbar() {
     '#type' => 'toolbar_item',
     'tab' => array(
       '#type' => 'link',
-      '#title' => $user->getUsername(),
+      '#title' => $user->getDisplayName(),
       '#url' => Url::fromRoute('user.page'),
       '#attributes' => array(
         'title' => t('My account'),
@@ -1480,7 +1482,7 @@ function user_toolbar() {
 function user_logout() {
   $user = \Drupal::currentUser();
 
-  \Drupal::logger('user')->notice('Session closed for %name.', array('%name' => $user->getUsername()));
+  \Drupal::logger('user')->notice('Session closed for %name.', array('%name' => $user->getDisplayName()));
 
   \Drupal::moduleHandler()->invokeAll('user_logout', array($user));
 
diff --git a/core/modules/user/user.tokens.inc b/core/modules/user/user.tokens.inc
index 073b90f..a676232 100644
--- a/core/modules/user/user.tokens.inc
+++ b/core/modules/user/user.tokens.inc
@@ -27,7 +27,11 @@ function user_token_info() {
     'description' => t("The unique ID of the user account."),
   );
   $user['name'] = array(
-    'name' => t("Name"),
+    'name' => t("Display Name"),
+    'description' => t("The display name of the user account."),
+  );
+  $user['username'] = array(
+    'name' => t("Login Name"),
     'description' => t("The login name of the user account."),
   );
   $user['mail'] = array(
@@ -88,11 +92,15 @@ function user_tokens($type, $tokens, array $data = array(), array $options = arr
           $replacements[$original] = $account->id() ?: t('not yet assigned');
           break;
 
-        case 'name':
-          $name = user_format_name($account);
+        case 'display-name':
+          $name = $account->getDisplayName();
           $replacements[$original] = $sanitize ? String::checkPlain($name) : $name;
           break;
 
+        case 'name':
+          $username = $account->getUsername();
+          $replacements[$original] = $sanitize ? String::checkPlain($username) : $username;
+          break;
         case 'mail':
           $replacements[$original] = $sanitize ? String::checkPlain($account->getEmail()) : $account->getEmail();
           break;
