diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 27494e7..3558434 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -676,7 +676,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 084943b..7dc98ae 100644
--- a/core/lib/Drupal/Core/Session/AccountInterface.php
+++ b/core/lib/Drupal/Core/Session/AccountInterface.php
@@ -114,7 +114,17 @@ public function getPreferredLangcode($default = NULL);
   public function getPreferredAdminLangcode($default = NULL);
 
   /**
-   * Returns the username of this account.
+   * Returns the unique username of this account.
+   *
+   * @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.
    *
    * 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
@@ -123,13 +133,13 @@ public function getPreferredAdminLangcode($default = NULL);
    *
    * @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 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 getUsername();
+  public function getDisplayName();
 
   /**
    * Returns the email address of this account.
diff --git a/core/lib/Drupal/Core/Session/AccountProxy.php b/core/lib/Drupal/Core/Session/AccountProxy.php
index 56a42fa..d32c47d 100644
--- a/core/lib/Drupal/Core/Session/AccountProxy.php
+++ b/core/lib/Drupal/Core/Session/AccountProxy.php
@@ -168,6 +168,13 @@ public function getUsername() {
   /**
    * {@inheritdoc}
    */
+  public function getDisplayName() {
+    return $this->getAccount()->getDisplayName();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function getEmail() {
     return $this->getAccount()->getEmail();
   }
diff --git a/core/lib/Drupal/Core/Session/UserSession.php b/core/lib/Drupal/Core/Session/UserSession.php
index 912d755..12a37b8 100644
--- a/core/lib/Drupal/Core/Session/UserSession.php
+++ b/core/lib/Drupal/Core/Session/UserSession.php
@@ -209,6 +209,13 @@ function getPreferredAdminLangcode($default = NULL) {
    * {@inheritdoc}
    */
   public function getUsername() {
+    return $this->name ?: '';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getDisplayName() {
     $name = $this->name ?: \Drupal::config('user.settings')->get('anonymous');
     \Drupal::moduleHandler()->alter('user_format_name', $name, $this);
     return $name;
diff --git a/core/modules/action/src/Plugin/Action/EmailAction.php b/core/modules/action/src/Plugin/Action/EmailAction.php
index b973204..c1de23c 100644
--- a/core/modules/action/src/Plugin/Action/EmailAction.php
+++ b/core/modules/action/src/Plugin/Action/EmailAction.php
@@ -148,7 +148,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 ece48fa..350af1a 100644
--- a/core/modules/action/src/Plugin/Action/MessageAction.php
+++ b/core/modules/action/src/Plugin/Action/MessageAction.php
@@ -76,7 +76,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 d5391f3..c701939 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -761,23 +761,7 @@ function comment_preview(CommentInterface $comment, FormStateInterface $form_sta
   $entity = $comment->getCommentedEntity();
 
   if (!form_get_errors($form_state)) {
-    // 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 343d93a..2eeb24d 100644
--- a/core/modules/comment/src/CommentForm.php
+++ b/core/modules/comment/src/CommentForm.php
@@ -213,6 +213,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);
   }
 
@@ -309,13 +315,7 @@ public function submit(array $form, FormStateInterface $form_state) {
     /** @var \Drupal\comment\CommentInterface $comment */
     $comment = parent::submit($form, $form_state);
 
-    // 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 bee5dcf..73b4167 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -115,7 +115,7 @@ function contact_mail($key, &$message, $params) {
     '!subject' => $contact_message->getSubject(),
     '!category' => !empty($params['contact_category']) ? $params['contact_category']->label() : NULL,
     '!form-url' => url(current_path(), array('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));
@@ -143,7 +143,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' => url('user/' . $params['recipient']->id() . '/edit', 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 b257ade..a2ae2e9 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 2c1ae66..37edd85 100644
--- a/core/modules/file/src/Tests/FileFieldPathTest.php
+++ b/core/modules/file/src/Tests/FileFieldPathTest.php
@@ -43,7 +43,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 481e8f4..9df387e 100644
--- a/core/modules/file/src/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/src/Tests/FileTokenReplaceTest.php
@@ -52,7 +52,7 @@ function testFileTokenReplacement() {
     $tests['[file:created:short]'] = format_date($file->getCreatedTime(), 'short', '', NULL, $language_interface->id);
     $tests['[file:changed]'] = format_date($file->getChangedTime(), 'medium', '', NULL, $language_interface->id);
     $tests['[file:changed:short]'] = format_date($file->getChangedTime(), 'short', '', NULL, $language_interface->id);
-    $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 425b597..4f7823a 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -557,7 +557,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 9d3db7b..468dcf2 100644
--- a/core/modules/node/src/Plugin/views/row/Rss.php
+++ b/core/modules/node/src/Plugin/views/row/Rss.php
@@ -122,7 +122,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 0ee6614..b4478d0 100644
--- a/core/modules/rdf/rdf.module
+++ b/core/modules/rdf/rdf.module
@@ -363,7 +363,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 a66a890..c9fb3e3 100644
--- a/core/modules/shortcut/src/Form/SwitchShortcutSet.php
+++ b/core/modules/shortcut/src/Form/SwitchShortcutSet.php
@@ -199,7 +199,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())),
       );
@@ -223,7 +223,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) {
       /* @var \Drupal\shortcut\Entity\ShortcutSet $set */
       $set = $this->shortcutSetStorage->load($form_state['values']['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/system/system.api.php b/core/modules/system/system.api.php
index ee83508..65e5900 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1269,7 +1269,7 @@ function hook_mail($key, &$message, $params) {
   $context = $params['context'];
   $variables = array(
     '%site_name' => \Drupal::config('system.site')->get('name'),
-    '%username' => user_format_name($account),
+    '%username' => $account->getDisplayName(),
   );
   if ($context['hook'] == 'taxonomy') {
     $entity = $params['entity'];
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 06e1a09..43ccf2a 100644
--- a/core/modules/user/src/AccountSettingsForm.php
+++ b/core/modules/user/src/AccountSettingsForm.php
@@ -183,7 +183,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 2c414c1..7ba029a 100644
--- a/core/modules/user/src/Controller/UserController.php
+++ b/core/modules/user/src/Controller/UserController.php
@@ -161,7 +161,7 @@ public function userPage(Request $request) {
    *   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 307cfc2..f10adf3 100644
--- a/core/modules/user/src/Entity/User.php
+++ b/core/modules/user/src/Entity/User.php
@@ -415,7 +415,14 @@ public function isAnonymous() {
    * {@inheritdoc}
    */
   public function getUsername() {
-    $name = $this->get('name')->value ?: \Drupal::config('user.settings')->get('anonymous');
+    return $this->get('name')->value ?: '';
+  }
+
+  /**
+   * {@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 41c6e1a..1b50a42 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['values']['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['values']['timestamp']));
+    $this->logger->notice('User %name used one-time login link at time %timestamp.', array('%name' => $user->getDisplayName(), '%timestamp' => $form_state['values']['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 ce456b7..fe28da2 100644
--- a/core/modules/user/src/Plugin/Search/UserSearch.php
+++ b/core/modules/user/src/Plugin/Search/UserSearch.php
@@ -139,7 +139,7 @@ public function execute() {
 
     foreach ($accounts as $account) {
       $result = array(
-        'title' => $account->getUsername(),
+        'title' => $account->getDisplayName(),
         'link' => url('user/' . $account->id(), 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 5396bc6..8af75e9 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.
-        return String::checkPlain($this->options['anonymous_text']);
-      }
-      elseif (!empty($this->options['link_to_user'])) {
-        $account->name = $this->getValue($values);
+    $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']);
+    }
+
+    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 64ebf4e..b3ecb41 100644
--- a/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
+++ b/core/modules/user/src/Tests/UserEditedOwnAccountTest.php
@@ -16,6 +16,13 @@
  */
 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
     // only.
diff --git a/core/modules/user/src/Tests/UserEntityCallbacksTest.php b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
index b2f21c0..eb84d4b 100644
--- a/core/modules/user/src/Tests/UserEntityCallbacksTest.php
+++ b/core/modules/user/src/Tests/UserEntityCallbacksTest.php
@@ -22,13 +22,18 @@ 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;
 
+  /**
+   * @var \Drupal\user\UserInterface
+   */
+  protected $anonymous;
+
   function setUp() {
     parent::setUp();
 
@@ -46,6 +51,13 @@ function testLabelCallback() {
     $name = $this->randomName();
     \Drupal::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 fa5ac1b..986b349 100644
--- a/core/modules/user/src/Tests/UserTokenReplaceTest.php
+++ b/core/modules/user/src/Tests/UserTokenReplaceTest.php
@@ -58,7 +58,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]'] = url("user/" . $account->id(), $url_options);
     $tests['[user:edit-url]'] = url("user/" . $account->id() . "/edit", $url_options);
@@ -66,7 +67,8 @@ function testUserTokenReplacement() {
     $tests['[user:last-login:short]'] = format_date($account->getLastLoginTime(), 'short', '', NULL, $language_interface->id);
     $tests['[user:created]'] = format_date($account->getCreatedTime(), 'medium', '', NULL, $language_interface->id);
     $tests['[user:created:short]'] = format_date($account->getCreatedTime(), 'short', '', NULL, $language_interface->id);
-    $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.');
@@ -77,9 +79,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->id, 'sanitize' => FALSE));
diff --git a/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php b/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
index f28b7d8..575e875 100644
--- a/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
+++ b/core/modules/user/src/Tests/Views/HandlerFieldUserNameTest.php
@@ -25,29 +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->row_index = 0;
-
     $view->field['name']->options['link_to_user'] = TRUE;
-    $username = $view->result[0]->users_name = $this->randomName();
-    $view->result[0]->uid = 1;
-    $render = $view->field['name']->advancedRender($view->result[0]);
+    $username = $view->result[3]->users_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_name = $this->randomName();
-    $view->result[0]->uid = 1;
-    $render = $view->field['name']->advancedRender($view->result[0]);
+    $username = $view->result[2]->users_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]->uid = 0;
     $anon_name = \Drupal::config('user.settings')->get('anonymous');
-    $view->result[0]->users_name = '';
     $render = $view->field['name']->advancedRender($view->result[0]);
     $this->assertIdentical($render, $anon_name , 'For user0 it should use the default anonymous name by default.');
 
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..3603465
--- /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 8011988..3679626 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
@@ -42,6 +42,13 @@ display:
         type: default
       row:
         type: fields
+      sorts:
+        uid:
+          id: uid
+          table: users
+          field: uid
+          plugin_id: standard
+          provider: views
     display_plugin: default
     display_title: Master
     id: default
diff --git a/core/modules/user/user.api.php b/core/modules/user/user.api.php
index 34e9f7f..9baa8b4 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 c23cc2c..b000da5 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -540,10 +540,10 @@ function user_preprocess_block(&$variables) {
  *   is called on it before it is printed to the page.
  *
  * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- *   Use \Drupal\Core\Session\Interface::getUsername().
+ *   Use \Drupal\Core\Session\AccountInterface::getDisplayName().
  */
 function user_format_name(AccountInterface $account) {
-  return $account->getUsername();
+  return $account->getDisplayName();
 }
 
 /**
@@ -599,7 +599,8 @@ 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 (drupal_strlen($name) > 20) {
     $name = Unicode::truncate($name, 15, FALSE, TRUE);
     $variables['truncated'] = TRUE;
@@ -858,8 +859,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':
@@ -869,8 +870,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;
   }
 
@@ -1511,7 +1512,7 @@ function user_toolbar() {
     '#type' => 'toolbar_item',
     'tab' => array(
       '#type' => 'link',
-      '#title' => $user->getUsername(),
+      '#title' => $user->getDisplayName(),
       '#href' => 'user',
       '#attributes' => array(
         'title' => t('My account'),
@@ -1545,7 +1546,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 51579be..dfe8966 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,16 @@ 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;
