Index: src/wp-admin/includes/user.php
===================================================================
--- src/wp-admin/includes/user.php	(リビジョン 45519)
+++ src/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: src/wp-admin/user-edit.php
===================================================================
--- src/wp-admin/user-edit.php	(リビジョン 45519)
+++ src/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>
Index: src/wp-includes/user.php
===================================================================
--- src/wp-includes/user.php	(リビジョン 45519)
+++ src/wp-includes/user.php	(作業コピー)
@@ -2135,6 +2135,59 @@
 }
 
 /**
+ * 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() {
+	$default = [
+		'first_name'  => __( 'First Name' ),
+		'middle_name' => __( 'Middle Name' ),
+		'last_name'   => __( 'Last Name' ),
+	];
+	$user_locale = get_user_locale();
+	/**
+	 * Filters user name parts.
+	 *
+	 * @since 5.3.0
+	 *
+	 * @param array  $name_parts  An associative array consists of user_meta key as key and label as value.
+	 * @param string $user_locale User locale
+	 */
+	$name_parts = (array) apply_filters( 'user_name_parts', $default, $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.
+	 */
+	$name_order = _x( 'first_name,last_name', 'Name order. 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 ( $name_parts ) {
+		return isset( $name_parts[ $key ] );
+	} );
+	$allowed_parts = [];
+	foreach ( $name_order as $key ) {
+		$allowed_parts[ $key ] = $name_parts[ $key ];
+	}
+	return empty( $allowed_parts ) ? [
+		'first_name'  => __( 'First Name' ),
+		'last_name'   => __( 'Last Name' ),
+	] : $allowed_parts;
+}
+
+/**
  * Set up the user contact methods.
  *
  * Default contact methods were removed in 3.6. A filter dictates contact methods.
