Index: wp-admin/includes/class-wp-users-list-table.php
===================================================================
--- wp-admin/includes/class-wp-users-list-table.php	(リビジョン 45519)
+++ wp-admin/includes/class-wp-users-list-table.php	(作業コピー)
@@ -504,15 +504,7 @@
 						$r .= "$avatar $edit";
 						break;
 					case 'name':
-						if ( $user_object->first_name && $user_object->last_name ) {
-							$r .= "$user_object->first_name $user_object->last_name";
-						} elseif ( $user_object->first_name ) {
-							$r .= $user_object->first_name;
-						} elseif ( $user_object->last_name ) {
-							$r .= $user_object->last_name;
-						} else {
-							$r .= '<span aria-hidden="true">&#8212;</span><span class="screen-reader-text">' . _x( 'Unknown', 'name' ) . '</span>';
-						}
+						$r.= $user_object->nickname ?: $user_object->display_name;
 						break;
 					case 'email':
 						$r .= "<a href='" . esc_url( "mailto:$email" ) . "'>$email</a>";
Index: wp-admin/includes/user.php
===================================================================
--- wp-admin/includes/user.php	(リビジョン 45519)
+++ wp-admin/includes/user.php	(作業コピー)
@@ -88,12 +88,11 @@
 			$user->user_url = preg_match( '/^(' . $protocols . '):/is', $user->user_url ) ? $user->user_url : 'http://' . $user->user_url;
 		}
 	}
-	if ( isset( $_POST['first_name'] ) ) {
-		$user->first_name = sanitize_text_field( $_POST['first_name'] );
+	foreach ( wp_get_user_name_parts() as $key => $label ) {
+		if ( isset( $_POST[ $key ] ) ) {
+			$user->{$key} = sanitize_text_field( $_POST[ $key ] );
+		}
 	}
-	if ( isset( $_POST['last_name'] ) ) {
-		$user->last_name = sanitize_text_field( $_POST['last_name'] );
-	}
 	if ( isset( $_POST['nickname'] ) ) {
 		$user->nickname = sanitize_text_field( $_POST['nickname'] );
 	}
Index: wp-admin/user-edit.php
===================================================================
--- wp-admin/user-edit.php	(リビジョン 45519)
+++ wp-admin/user-edit.php	(作業コピー)
@@ -425,16 +425,13 @@
 </td></tr>
 		<?php } ?>
 
-<tr class="user-first-name-wrap">
-	<th><label for="first_name"><?php _e( 'First Name' ); ?></label></th>
-	<td><input type="text" name="first_name" id="first_name" value="<?php echo esc_attr( $profileuser->first_name ); ?>" class="regular-text" /></td>
+<?php foreach ( wp_get_user_name_parts() as $key => $label ) : ?>
+<tr class="user-<?php echo esc_attr( str_replace( '_', '-', $key ) ) ?>-wrap">
+	<th><label for="<?php echo esc_attr( $key ) ?>"><?php echo esc_html( $label ); ?></label></th>
+	<td><input type="text" name="<?php echo esc_attr( $key ) ?>" id="<?php echo esc_attr( $key ) ?>" value="<?php echo esc_attr( $profileuser->{$key}); ?>" class="regular-text" /></td>
 </tr>
+<?php endforeach; ?>
 
-<tr class="user-last-name-wrap">
-	<th><label for="last_name"><?php _e( 'Last Name' ); ?></label></th>
-	<td><input type="text" name="last_name" id="last_name" value="<?php echo esc_attr( $profileuser->last_name ); ?>" class="regular-text" /></td>
-</tr>
-
 <tr class="user-nickname-wrap">
 	<th><label for="nickname"><?php _e( 'Nickname' ); ?> <span class="description"><?php _e( '(required)' ); ?></span></label></th>
 	<td><input type="text" name="nickname" id="nickname" value="<?php echo esc_attr( $profileuser->nickname ); ?>" class="regular-text" /></td>
@@ -445,29 +442,25 @@
 	<td>
 		<select name="display_name" id="display_name">
 		<?php
-			$public_display                     = array();
-			$public_display['display_nickname'] = $profileuser->nickname;
-			$public_display['display_username'] = $profileuser->user_login;
-
-		if ( ! empty( $profileuser->first_name ) ) {
-			$public_display['display_firstname'] = $profileuser->first_name;
+		$public_display                     = array();
+		$public_display['display_nickname'] = $profileuser->nickname;
+		$public_display['display_username'] = $profileuser->user_login;
+		$user_name = [];
+		foreach ( array_keys( wp_get_user_name_parts() ) as $key ) {
+			if ( ! empty( $profileuser->{$key} ) ) {
+				$user_name[] = $profileuser->{$key};
+			}
 		}
-
-		if ( ! empty( $profileuser->last_name ) ) {
-			$public_display['display_lastname'] = $profileuser->last_name;
+		if ( $user_name ) {
+			$public_display[ 'display_name_parts' ] = implode( wp_user_name_parts_glue( $profileuser ), $user_name );
 		}
-
-		if ( ! empty( $profileuser->first_name ) && ! empty( $profileuser->last_name ) ) {
-			$public_display['display_firstlast'] = $profileuser->first_name . ' ' . $profileuser->last_name;
-			$public_display['display_lastfirst'] = $profileuser->last_name . ' ' . $profileuser->first_name;
-		}
-
+		
 		if ( ! in_array( $profileuser->display_name, $public_display ) ) { // Only add this if it isn't duplicated elsewhere
 			$public_display = array( 'display_displayname' => $profileuser->display_name ) + $public_display;
 		}
 
-			$public_display = array_map( 'trim', $public_display );
-			$public_display = array_unique( $public_display );
+		$public_display = array_map( 'trim', $public_display );
+		$public_display = array_unique( $public_display );
 
 		foreach ( $public_display as $id => $item ) {
 			?>
Index: wp-admin/user-new.php
===================================================================
--- wp-admin/user-new.php	(リビジョン 45519)
+++ wp-admin/user-new.php	(作業コピー)
@@ -453,14 +453,19 @@
 	$creating = isset( $_POST['createuser'] );
 
 	$new_user_login             = $creating && isset( $_POST['user_login'] ) ? wp_unslash( $_POST['user_login'] ) : '';
-	$new_user_firstname         = $creating && isset( $_POST['first_name'] ) ? wp_unslash( $_POST['first_name'] ) : '';
-	$new_user_lastname          = $creating && isset( $_POST['last_name'] ) ? wp_unslash( $_POST['last_name'] ) : '';
 	$new_user_email             = $creating && isset( $_POST['email'] ) ? wp_unslash( $_POST['email'] ) : '';
 	$new_user_uri               = $creating && isset( $_POST['url'] ) ? wp_unslash( $_POST['url'] ) : '';
 	$new_user_role              = $creating && isset( $_POST['role'] ) ? wp_unslash( $_POST['role'] ) : '';
 	$new_user_send_notification = $creating && ! isset( $_POST['send_user_notification'] ) ? false : true;
 	$new_user_ignore_pass       = $creating && isset( $_POST['noconfirmation'] ) ? wp_unslash( $_POST['noconfirmation'] ) : '';
-
+	$new_user_name_parts        = [];
+	foreach ( wp_get_user_name_parts() as $user_name_key => $label ) {
+		$new_user_name_parts[] = [
+			'key'   => $user_name_key,
+			'value' => $creating && isset( $_POST[ $user_name_key ] ) ? wp_unslash( $_POST[ $user_name_key ] ) : '',
+			'label' => $label,
+		];
+	}
 	?>
 <table class="form-table" role="presentation">
 	<tr class="form-field form-required">
@@ -472,15 +477,17 @@
 		<td><input name="email" type="email" id="email" value="<?php echo esc_attr( $new_user_email ); ?>" /></td>
 	</tr>
 	<?php if ( ! is_multisite() ) { ?>
+		<?php foreach ( $new_user_name_parts as $name_part ) : ?>
+			<tr class="form-field">
+				<th scope="row">
+					<label for="<?php echo esc_attr( $name_part['key'] ) ?>"><?php echo esc_html( $name_part['label'] ); ?> </label>
+				</th>
+				<td>
+					<input name="<?php echo esc_attr( $name_part['key'] ) ?>" type="text" id="<?php echo esc_attr( $name_part['key'] ) ?>" value="<?php echo esc_attr( $name_part['value'] ); ?>"/>
+				</td>
+			</tr>
+		<?php endforeach; ?>
 	<tr class="form-field">
-		<th scope="row"><label for="first_name"><?php _e( 'First Name' ); ?> </label></th>
-		<td><input name="first_name" type="text" id="first_name" value="<?php echo esc_attr( $new_user_firstname ); ?>" /></td>
-	</tr>
-	<tr class="form-field">
-		<th scope="row"><label for="last_name"><?php _e( 'Last Name' ); ?> </label></th>
-		<td><input name="last_name" type="text" id="last_name" value="<?php echo esc_attr( $new_user_lastname ); ?>" /></td>
-	</tr>
-	<tr class="form-field">
 		<th scope="row"><label for="url"><?php _e( 'Website' ); ?></label></th>
 		<td><input name="url" type="url" id="url" class="code" value="<?php echo esc_attr( $new_user_uri ); ?>" /></td>
 	</tr>
Index: wp-includes/user.php
===================================================================
--- wp-includes/user.php	(リビジョン 45519)
+++ wp-includes/user.php	(作業コピー)
@@ -1629,62 +1629,43 @@
 	 */
 	$user_email = apply_filters( 'pre_user_email', $raw_user_email );
 
-	/*
-	 * If there is no update, just check for `email_exists`. If there is an update,
-	 * check if current email and new email are the same, or not, and check `email_exists`
-	 * accordingly.
-	 */
-	if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) )
-		&& ! defined( 'WP_IMPORTING' )
-		&& email_exists( $user_email )
-	) {
-		return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) );
+	foreach ( wp_get_user_name_parts() as $name_key => $label ) {
+		$name_part = empty( $userdata[ $name_key ] ) ? '' : $userdata[ $name_key ];
+		/**
+		 * Filters a user's name part before the user is created or updated.
+		 *
+		 * This filter is backward compatibility for 'pre_user_first_name' and 'pre_user_last_name'.
+		 *
+		 * @since 5.3.0
+		 *
+		 * @param string $name_part The user's
+		 */
+		$meta[ $name_key ] = apply_filters( "pre_user_{$name_key}", $name_part );
+		/**
+		 * Filters a user's name part before the user is created or updated.
+		 *
+		 * @since 5.3.0
+		 *
+		 * @param string $name_part_value The user's name part value. e.g. "John"
+		 * @param string $name_part_name  The user's name part key.   e.g. "first_name"
+		 * @param array  $userdata        User data array.
+		 * @param bool   $update          If updating, true.
+		 */
+		$meta[ $name_key ] = apply_filters( "pre_user_name_part", $name_part, $name_key, $userdata, $update );
 	}
-	$nickname = empty( $userdata['nickname'] ) ? $user_login : $userdata['nickname'];
 
-	/**
-	 * Filters a user's nickname before the user is created or updated.
-	 *
-	 * @since 2.0.3
-	 *
-	 * @param string $nickname The user's nickname.
-	 */
-	$meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname );
-
-	$first_name = empty( $userdata['first_name'] ) ? '' : $userdata['first_name'];
-
-	/**
-	 * Filters a user's first name before the user is created or updated.
-	 *
-	 * @since 2.0.3
-	 *
-	 * @param string $first_name The user's first name.
-	 */
-	$meta['first_name'] = apply_filters( 'pre_user_first_name', $first_name );
-
-	$last_name = empty( $userdata['last_name'] ) ? '' : $userdata['last_name'];
-
-	/**
-	 * Filters a user's last name before the user is created or updated.
-	 *
-	 * @since 2.0.3
-	 *
-	 * @param string $last_name The user's last name.
-	 */
-	$meta['last_name'] = apply_filters( 'pre_user_last_name', $last_name );
-
 	if ( empty( $userdata['display_name'] ) ) {
 		if ( $update ) {
 			$display_name = $user_login;
-		} elseif ( $meta['first_name'] && $meta['last_name'] ) {
-			/* translators: 1: first name, 2: last name */
-			$display_name = sprintf( _x( '%1$s %2$s', 'Display name based on first name and last name' ), $meta['first_name'], $meta['last_name'] );
-		} elseif ( $meta['first_name'] ) {
-			$display_name = $meta['first_name'];
-		} elseif ( $meta['last_name'] ) {
-			$display_name = $meta['last_name'];
 		} else {
-			$display_name = $user_login;
+			// Try building non empty name.
+			$generated_name = [];
+			foreach ( array_keys( wp_get_user_name_parts() ) as $name_part_key ) {
+				if ( ! empty( $userdata[ $name_part_key ]) ) {
+					$generated_name[] = $userdata[ $name_part_key ];
+				}
+			}
+			$display_name = $generated_name ? implode( wp_user_name_parts_glue( $userdata ), $generated_name ) : $user_login;
 		}
 	} else {
 		$display_name = $userdata['display_name'];
@@ -1698,6 +1679,28 @@
 	 * @param string $display_name The user's display name.
 	 */
 	$display_name = apply_filters( 'pre_user_display_name', $display_name );
+	
+	/*
+	 * If there is no update, just check for `email_exists`. If there is an update,
+	 * check if current email and new email are the same, or not, and check `email_exists`
+	 * accordingly.
+	 */
+	if ( ( ! $update || ( ! empty( $old_user_data ) && 0 !== strcasecmp( $user_email, $old_user_data->user_email ) ) )
+		 && ! defined( 'WP_IMPORTING' )
+		 && email_exists( $user_email )
+	) {
+		return new WP_Error( 'existing_user_email', __( 'Sorry, that email address is already used!' ) );
+	}
+	$nickname = empty( $userdata['nickname'] ) ? $display_name : $userdata['nickname'];
+	
+	/**
+	 * Filters a user's nickname before the user is created or updated.
+	 *
+	 * @since 2.0.3
+	 *
+	 * @param string $nickname The user's nickname.
+	 */
+	$meta['nickname'] = apply_filters( 'pre_user_nickname', $nickname );
 
 	$description = empty( $userdata['description'] ) ? '' : $userdata['description'];
 
@@ -2131,10 +2134,89 @@
  */
 function _get_additional_user_keys( $user ) {
 	$keys = array( 'first_name', 'last_name', 'nickname', 'description', 'rich_editing', 'syntax_highlighting', 'comment_shortcuts', 'admin_color', 'use_ssl', 'show_admin_bar_front', 'locale' );
-	return array_merge( $keys, array_keys( wp_get_user_contact_methods( $user ) ) );
+	return array_merge( $keys, array_keys( wp_get_user_name_parts() ), array_keys( wp_get_user_contact_methods( $user ) ) );
 }
 
 /**
+ * Get user name parts.
+ *
+ * Default name parts are first_name and last_name.
+ *
+ * @since 5.3.0
+ *
+ * @return array An associative array consists of user_meta key as key and label as value.
+ */
+function wp_get_user_name_parts() {
+	$available_name_parts = [
+		'first_name'  => __( 'First Name' ),
+		'middle_name' => __( 'Middle Name' ),
+		'last_name'   => __( 'Last Name' ),
+		'full_name'   => __( 'Full Name' ),
+	];
+	$user_locale = get_user_locale();
+	/**
+	 * Filters user name parts.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param array  $available_name_parts  An associative array consists of user_meta key as key and label as value.
+	 * @param string $user_locale User locale
+	 */
+	$available_name_parts = (array) apply_filters( 'user_name_parts', $available_name_parts, $user_locale );
+	/*
+	 * translators: Control name order in your locale. If last name precedes first name, 'last_name,first_name'.
+	 * A middle name is required, 'first_name,middle_name,last_name'.
+	 * Other name parts can be added by user_name_parts filters.
+	 */
+	if ( /*$version_is_too_old*/ false ) {
+		$name_order = _x( 'first_name,last_name', 'Name order. Do not translate!' );
+	} else {
+		$name_order = _x( 'full_name', 'Default name order since 5.3.0. Do not translate!' );
+	}
+	/**
+	 * Order of user name parts. Must be included in name parts.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param array  $name_order  An array of user_meta key.
+	 * @param string $user_locale User locale.
+	 */
+	$name_order = (array) apply_filters( 'user_name_parts_order', array_map( 'trim', explode( ',', $name_order ) ), $user_locale );
+	$name_order = array_filter( $name_order, function( $key ) use ( $available_name_parts ) {
+		return ! empty( $available_name_parts[ $key ] );
+	} );
+	$allowed_parts = [];
+	foreach ( $name_order as $key ) {
+		$allowed_parts[ $key ] = $available_name_parts[ $key ];
+	}
+	return empty( $allowed_parts ) ? [
+		'full_name'  => __( 'Full Name' ),
+	] : $allowed_parts;
+}
+
+/**
+ * Return glue for name parts.
+ *
+ * @param null|WP_User|array $userdata
+ * @return string
+ */
+function wp_user_name_parts_glue( $userdata = null ) {
+	$glue = _x( ' ', 'User name parts glue. Do not translate!' );
+	/**
+	 * Filters the glue of name parts.
+	 *
+	 * @param string             $glue     Default ' '.
+	 * @param array|null|WP_User $userdata User data. Varies depending on context.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param string              $glue
+	 * @param array|array|WP_User $userdata
+	 */
+	return (string) apply_filters( 'default_user_display_name_glue', $glue, $userdata );
+}
+
+/**
  * Set up the user contact methods.
  *
  * Default contact methods were removed in 3.6. A filter dictates contact methods.
