diff --git src/bp-core/admin/bp-core-admin-settings.php src/bp-core/admin/bp-core-admin-settings.php
index 023d2cea4..e2f4cffcc 100644
--- src/bp-core/admin/bp-core-admin-settings.php
+++ src/bp-core/admin/bp-core-admin-settings.php
@@ -203,6 +203,27 @@ function bp_admin_setting_callback_members_invitations() {
 	do_action( 'bp_admin_settings_after_members_invitations' );
 }
 
+/**
+ * Allow new users to request membership to the network.
+ *
+ * @since 10.0.0
+ */
+function bp_admin_setting_callback_membership_requests() {
+?>
+	<input id="bp-enable-membership-requests" name="bp-enable-membership-requests" type="checkbox" value="1" <?php checked( bp_get_membership_requests_required( 'raw' ) ); ?> <?php if ( bp_get_signup_allowed() ) { echo 'disabled="disabled"'; } ?> />
+	<label for="bp-enable-membership-requests"><?php esc_html_e( 'Allow visitors to request site membership. If enabled, an administrator must approve each new site membership request.', 'buddypress' ); ?></label>
+	<?php if ( bp_get_signup_allowed() ) : ?>
+		<p class="description"><?php esc_html_e( 'Public registration is currently enabled. If you wish to require approval for new memberships, disable public registration and enable the membership requests feature.', 'buddypress' ); ?></p>
+	<?php endif; ?>
+	<?php
+	/**
+	 * Fires after the output of the membership requests settings section.
+	 *
+	 * @since 10.0.0
+	 */
+	do_action( 'bp_admin_settings_after_membership_requests' );
+}
+
 /** XProfile ******************************************************************/
 
 /**
diff --git src/bp-core/admin/js/bp-thickbox.js src/bp-core/admin/js/bp-thickbox.js
new file mode 100644
index 000000000..0bafd38fa
--- /dev/null
+++ src/bp-core/admin/js/bp-thickbox.js
@@ -0,0 +1,52 @@
+/**
+ * Improves the Thickbox library for BuddyPress needs.
+ *
+ * @since 10.0.0
+ */
+( function( $ ) {
+	window.bpAdjustThickbox = function( label, padding ) {
+		$( '#TB_window' ).attr( {
+							'role': 'dialog',
+							'aria-label': label
+						} )
+						.addClass( 'plugin-details-modal' )
+						.removeClass( 'thickbox-loading' );
+
+
+		if ( ! padding ) {
+			padding = 0;
+		}
+
+		$( '#TB_ajaxContent' ).prop( 'style', 'height: 100%; width: auto; padding: ' + padding + '; border: none;' );
+
+		try {
+			var tabbables = $( ':tabbable', '#TB_ajaxContent' ), lastTabbable = tabbables.last();
+
+			// Move the focus to the Modal's close button once the last Hello link was tabbed out.
+			$( '#TB_window' ).on( 'keydown', function( event ) {
+				var keyCode;
+
+				if ( event.key !== undefined ) {
+					keyCode = event.key;
+				} else {
+					// event.keyCode is deprecated.
+					keyCode = event.keyCode;
+				}
+
+				if ( 9 === keyCode && ! event.shiftKey && $( lastTabbable ).prop( 'classList' ).value === $( event.target ).prop( 'classList' ).value ) {
+					event.preventDefault();
+
+					$( '#TB_closeWindowButton' ).trigger( 'focus' );
+				}
+
+				if ( 9 === keyCode && event.shiftKey && 'TB_closeWindowButton' === $( event.target ).prop( 'id' ) ) {
+					event.preventDefault();
+
+					$( lastTabbable ).trigger( 'focus' );
+				}
+			} );
+		} catch ( error ) {
+			return;
+		}
+	};
+} ( jQuery ) );
diff --git src/bp-core/admin/js/hello.js src/bp-core/admin/js/hello.js
index 47c996579..77461a559 100644
--- src/bp-core/admin/js/hello.js
+++ src/bp-core/admin/js/hello.js
@@ -19,32 +19,7 @@
 		}
 
 		window.tb_show( 'BuddyPress', '#TB_inline?inlineId=bp-hello-container' );
-
-		$( '#TB_window' ).attr( {
-							'role': 'dialog',
-							'aria-label': bpHelloStrings.modalLabel
-						} )
-						.addClass( 'plugin-details-modal' )
-						.removeClass( 'thickbox-loading' );
-
-		$( '#TB_ajaxContent' ).prop( 'style', 'height: 100%; width: auto; padding: 0; border: none;' );
-
-		var tabbables = $( ':tabbable', '#TB_ajaxContent' ), lastTabbable = tabbables.last();
-
-		// Move the focus to the Modal's close button once the last Hello link was tabbed out.
-		$( '#TB_window' ).on( 'keydown', function( event ) {
-			if ( 9 === event.keyCode && ! event.shiftKey && $( lastTabbable ).prop( 'classList' ).value === $( event.target ).prop( 'classList' ).value ) {
-				event.preventDefault();
-
-				$( '#TB_closeWindowButton' ).focus();
-			}
-
-			if ( 9 === event.keyCode && event.shiftKey && 'TB_closeWindowButton' === $( event.target ).prop( 'id' ) ) {
-				event.preventDefault();
-
-				$( lastTabbable ).focus();
-			}
-		} );
+		window.bpAdjustThickbox( bpHelloStrings.modalLabel );
 	};
 
 	/**
diff --git src/bp-core/bp-core-filters.php src/bp-core/bp-core-filters.php
index 85a8978d2..b41c54410 100644
--- src/bp-core/bp-core-filters.php
+++ src/bp-core/bp-core-filters.php
@@ -473,21 +473,31 @@ function bp_core_activation_signup_blog_notification( $domain, $path, $title, $u
 		),
 	);
 
-	$signups = BP_Signup::get(
-		array(
-			'user_login' => $user,
-		)
-	);
-
+	$signup     = bp_members_get_signup_by( 'activation_key', $key );
 	$salutation = $user;
-	if ( $signups && bp_is_active( 'xprofile' ) ) {
-		$signup = $signups['signups'][0];
+	if ( $signup && bp_is_active( 'xprofile' ) ) {
 		if ( isset( $signup->meta[ 'field_' . bp_xprofile_fullname_field_id() ] ) ) {
 			$salutation = $signup->meta[ 'field_' . bp_xprofile_fullname_field_id() ];
 		}
 	}
 
-	bp_send_email( 'core-user-registration-with-blog', array( array( $user_email => $salutation ) ), $args );
+	/**
+	 * Filters if BuddyPress should send an activation key for a new multisite signup.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @param string $user       The user's login name.
+	 * @param string $user_email The user's email address.
+	 * @param string $key        The activation key created in wpmu_signup_blog().
+	 * @param string $domain     The new blog domain.
+	 * @param string $path       The new blog path.
+	 * @param string $title      The site title.
+	 */
+	if ( apply_filters( 'bp_core_signup_send_activation_key_multisite_blog', true, $user, $user_email, $key, $domain, $path, $title ) ) {
+
+		bp_send_email( 'core-user-registration-with-blog', array( array( $user_email => $salutation ) ), $args );
+
+	}
 
 	// Return false to stop the original WPMU function from continuing.
 	return false;
@@ -556,13 +566,52 @@ function bp_core_activation_signup_user_notification( $user, $user_email, $key,
 			'user.id'      => $user_id,
 		),
 	);
-	bp_send_email( 'core-user-registration', array( array( $user_email => $salutation ) ), $args );
+
+	/**
+	 * Filters if BuddyPress should send an activation key for a new multisite signup.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @param string $user       The user's login name.
+	 * @param string $user_email The user's email address.
+	 * @param string $key        The activation key created in wpmu_signup_blog().
+	 */
+	if ( apply_filters( 'bp_core_signup_send_activation_key_multisite', true, $user, $user_email, $key ) ) {
+
+		bp_send_email( 'core-user-registration', array( array( $user_email => $salutation ) ), $args );
+
+	}
+
 
 	// Return false to stop the original WPMU function from continuing.
 	return false;
 }
 add_filter( 'wpmu_signup_user_notification', 'bp_core_activation_signup_user_notification', 1, 4 );
 
+/**
+ * Ensure that some meta values are set for new multisite signups.
+ *
+ * @since 10.0.0
+ *
+ * @see wpmu_signup_user() for a full description of params.
+ *
+ * @param array $meta Signup meta data. Default empty array.
+ * @return array Signup meta data.
+ */
+function bp_core_add_meta_to_multisite_signups( $meta ) {
+
+	// Ensure that sent_date and count_sent are set in meta.
+	if ( ! isset( $meta['sent_date'] ) ) {
+		$meta['sent_date'] = '0000-00-00 00:00:00';
+	}
+	if ( ! isset( $meta['count_sent'] ) ) {
+		$meta['count_sent'] = 0;
+	}
+
+	return $meta;
+}
+add_filter( 'signup_user_meta', 'bp_core_add_meta_to_multisite_signups' );
+
 /**
  * Filter the page title for BuddyPress pages.
  *
diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php
index 0e66f4cb7..fd938861f 100644
--- src/bp-core/bp-core-functions.php
+++ src/bp-core/bp-core-functions.php
@@ -3792,6 +3792,8 @@ function bp_core_replace_tokens_in_text( $text, $tokens ) {
  * Get a list of emails for populating the email post type.
  *
  * @since 2.5.1
+ * @since 10.0.0 Added members-membership-request and
+ *               members-membership-request-rejected email types.
  *
  * @return array
  */
@@ -3952,6 +3954,22 @@ function bp_email_get_schema() {
 			/* translators: do not remove {} brackets or translate its contents. */
 			'post_excerpt' => __( "{{inviter.name}} has invited you to join the site \"{{site.name}}\".\n\n{{usermessage}}\n\nTo accept your invitation, visit: {{{invite.accept_url}}}\n\nTo learn more about the site, visit: {{{site.url}}}.\nTo view {{inviter.name}}'s profile, visit: {{{inviter.url}}}", 'buddypress' ),
 		),
+		'members-membership-request' => array(
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_title'   => __( '{{requesting-user.user_login}} would like to join {{site.name}}', 'buddypress' ),
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_content' => __( "{{requesting-user.user_login}} would like to join the site: &quot;{{site.name}}&quot;.\n\n<a href=\"{{{manage.url}}}\">Manage the request</a>.", 'buddypress' ),
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_excerpt' => __( "{{requesting-user.user_login}} would like to join the site \"{{site.name}}\".\n\nTo manage the request, visit: {{{manage.url}}}.", 'buddypress' ),
+		),
+		'members-membership-request-rejected' => array(
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_title'   => __( 'Your request to join {{site.name}} has been declined', 'buddypress' ),
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_content' => __( "Sorry, your request to join the site &quot;{{site.name}}&quot; has been declined.", 'buddypress' ),
+			/* translators: do not remove {} brackets or translate its contents. */
+			'post_excerpt' => __( "Sorry, your request to join the site \"{{site.name}}\" has been declined.", 'buddypress' ),
+		),
 	) );
 }
 
@@ -4124,25 +4142,42 @@ function bp_email_get_type_schema( $field = 'description' ) {
 		),
 	);
 
+	$members_membership_request= array(
+		'description'	   => __( 'Someone has requested membership on this site.', 'buddypress' ),
+		'named_salutation' => true,
+		'unsubscribe'	   => array(
+			'meta_key' => 'notification_members_membership_request',
+			'message'  => __( 'You will no longer receive emails when people submit requests to join this site.', 'buddypress' ),
+		),
+	);
+
+	$members_membership_request_rejected= array(
+		'description'	   => __( 'A site membership request has been rejected.', 'buddypress' ),
+		'named_salutation' => false,
+		'unsubscribe'	   => false,
+	);
+
 	$types = array(
-		'activity-comment'                   => $activity_comment,
-		'activity-comment-author'            => $activity_comment_author,
-		'activity-at-message'                => $activity_at_message,
-		'groups-at-message'                  => $groups_at_message,
-		'core-user-registration'             => $core_user_registration,
-		'core-user-registration-with-blog'   => $core_user_registration_with_blog,
-		'friends-request'                    => $friends_request,
-		'friends-request-accepted'           => $friends_request_accepted,
-		'groups-details-updated'             => $groups_details_updated,
-		'groups-invitation'                  => $groups_invitation,
-		'groups-member-promoted'             => $groups_member_promoted,
-		'groups-membership-request'          => $groups_membership_request,
-		'messages-unread'                    => $messages_unread,
-		'settings-verify-email-change'       => $settings_verify_email_change,
-		'groups-membership-request-accepted' => $groups_membership_request_accepted,
-		'groups-membership-request-rejected' => $groups_membership_request_rejected,
-		'core-user-activation'               => $core_user_activation,
-		'bp-members-invitation'              => $members_invitation,
+		'activity-comment'                    => $activity_comment,
+		'activity-comment-author'             => $activity_comment_author,
+		'activity-at-message'                 => $activity_at_message,
+		'groups-at-message'                   => $groups_at_message,
+		'core-user-registration'              => $core_user_registration,
+		'core-user-registration-with-blog'    => $core_user_registration_with_blog,
+		'friends-request'                     => $friends_request,
+		'friends-request-accepted'            => $friends_request_accepted,
+		'groups-details-updated'              => $groups_details_updated,
+		'groups-invitation'                   => $groups_invitation,
+		'groups-member-promoted'              => $groups_member_promoted,
+		'groups-membership-request'           => $groups_membership_request,
+		'messages-unread'                     => $messages_unread,
+		'settings-verify-email-change'        => $settings_verify_email_change,
+		'groups-membership-request-accepted'  => $groups_membership_request_accepted,
+		'groups-membership-request-rejected'  => $groups_membership_request_rejected,
+		'core-user-activation'                => $core_user_activation,
+		'bp-members-invitation'               => $members_invitation,
+		'members-membership-request'          => $members_membership_request,
+		'members-membership-request-rejected' => $members_membership_request_rejected,
 	);
 
 	if ( $field !== 'all' ) {
diff --git src/bp-core/bp-core-template.php src/bp-core/bp-core-template.php
index a88cd6800..9ef914ed9 100644
--- src/bp-core/bp-core-template.php
+++ src/bp-core/bp-core-template.php
@@ -3192,7 +3192,11 @@ function bp_get_title_parts( $seplocation = 'right' ) {
 
 	// Sign up page.
 	} elseif ( bp_is_register_page() ) {
-		$bp_title_parts = array( __( 'Create an Account', 'buddypress' ) );
+		if ( bp_get_membership_requests_required() ) {
+			$bp_title_parts = array( __( 'Request Membership', 'buddypress' ) );
+		} else {
+			$bp_title_parts = array( __( 'Create an Account', 'buddypress' ) );
+		}
 
 	// Activation page.
 	} elseif ( bp_is_activation_page() ) {
diff --git src/bp-core/bp-core-update.php src/bp-core/bp-core-update.php
index 03710213c..6468ace39 100644
--- src/bp-core/bp-core-update.php
+++ src/bp-core/bp-core-update.php
@@ -278,6 +278,12 @@ function bp_version_updater() {
 		if ( $raw_db_version < 12850 ) {
 			bp_update_to_8_0();
 		}
+
+		// Version 10.0.0.
+		if ( $raw_db_version < 13150 ) {
+			bp_update_to_10_0();
+		}
+
 	}
 
 	/* All done! *************************************************************/
@@ -704,6 +710,44 @@ function bp_core_get_8_0_upgrade_email_schema( $emails ) {
 	return $new_emails;
 }
 
+/**
+ * 10.0.0 update routine.
+ *
+ * - Install new BP Emails for membership requests.
+ *
+ * @since 10.0.0
+ */
+function bp_update_to_10_0() {
+
+	// Install membership request emails.
+	add_filter( 'bp_email_get_schema', 'bp_core_get_10_0_upgrade_email_schema' );
+
+	bp_core_install_emails();
+
+	remove_filter( 'bp_email_get_schema', 'bp_core_get_10_0_upgrade_email_schema' );
+}
+
+/**
+ * Select only the emails that need to be installed with version 10.0.
+ *
+ * @since 10.0.0
+ *
+ * @param array $emails The array of emails schema.
+ */
+function bp_core_get_10_0_upgrade_email_schema( $emails ) {
+	$new_emails = array();
+
+	if ( isset( $emails['members-membership-request'] ) ) {
+		$new_emails['members-membership-request'] = $emails['members-membership-request'];
+	}
+
+	if ( isset( $emails['members-membership-request-rejected'] ) ) {
+		$new_emails['members-membership-request-rejected'] = $emails['members-membership-request-rejected'];
+	}
+
+	return $new_emails;
+}
+
 /**
  * Updates the component field for new_members type.
  *
diff --git src/bp-core/classes/class-bp-admin.php src/bp-core/classes/class-bp-admin.php
index 9b7a87508..0fe584430 100644
--- src/bp-core/classes/class-bp-admin.php
+++ src/bp-core/classes/class-bp-admin.php
@@ -482,6 +482,12 @@ class BP_Admin {
 			register_setting( 'buddypress', 'bp-enable-members-invitations', 'intval' );
 		}
 
+		// Membership requests.
+		if ( bp_is_active( 'members', 'membership_requests' ) ) {
+			add_settings_field( 'bp-enable-membership-requests', __( 'Membership Requests', 'buddypress' ), 'bp_admin_setting_callback_membership_requests', 'buddypress', 'bp_members' );
+			register_setting( 'buddypress', 'bp-enable-membership-requests', 'intval' );
+		}
+
 		/* XProfile Section **************************************************/
 
 		if ( bp_is_active( 'xprofile' ) ) {
@@ -1282,10 +1288,17 @@ class BP_Admin {
 				'footer'       => true,
 			),
 
+			// 10.0
+			'bp-thickbox' => array(
+				'file'         => "{$url}bp-thickbox{$min}.js",
+				'dependencies' => array( 'thickbox' ),
+				'footer'       => true,
+			),
+
 			// 3.0
 			'bp-hello-js' => array(
 				'file'         => "{$url}hello{$min}.js",
-				'dependencies' => array( 'thickbox', 'wp-api-request' ),
+				'dependencies' => array( 'bp-thickbox', 'wp-api-request' ),
 				'footer'       => true,
 			),
 		) );
diff --git src/bp-core/classes/class-bp-invitation-manager.php src/bp-core/classes/class-bp-invitation-manager.php
index d92a76b7a..718384e7d 100644
--- src/bp-core/classes/class-bp-invitation-manager.php
+++ src/bp-core/classes/class-bp-invitation-manager.php
@@ -227,7 +227,7 @@ abstract class BP_Invitation_Manager {
 	 * 	   @type int    $item_id ID associated with the invitation and class.
 	 * 	   @type int    $secondary_item_id secondary ID associated with the
 	 *			        invitation and class.
-	 * 	   @type string $type @TODO. < missing description.
+	 * 	   @type string $type    Type of record this is: 'invite' or 'request'.
 	 * 	   @type string $content Extra information provided by the requester
 	 *			        or inviter.
 	 * 	   @type string $date_modified Date the invitation was last modified.
diff --git src/bp-members/admin/js/signup-preview.js src/bp-members/admin/js/signup-preview.js
new file mode 100644
index 000000000..15c200ea7
--- /dev/null
+++ src/bp-members/admin/js/signup-preview.js
@@ -0,0 +1,23 @@
+/* global bpSignupPreview */
+/**
+ * Opens a modal to preview a signup/membership request.
+ *
+ * @since 10.0.0
+ */
+( function( $ ) {
+	// Bail if not set or if Thickbox is not available.
+	if ( typeof bpSignupPreview === 'undefined' || 'function' !== typeof window.tb_show ) {
+		return;
+	}
+
+	$( function() {
+		$( '.bp-thickbox' ).on( 'click', function( e ) {
+			e.preventDefault();
+
+			var fragment = $( e.target ).prop( 'href' ).split( '#TB_inline&' )[1];
+
+			window.tb_show( 'BuddyPress', '#TB_inline?' + fragment );
+			window.bpAdjustThickbox( bpSignupPreview.modalLabel, '1em' );
+		} );
+	} );
+}( jQuery ) );
diff --git src/bp-members/bp-members-admin.php src/bp-members/bp-members-admin.php
index 1b80fe190..3aa4e01d7 100644
--- src/bp-members/bp-members-admin.php
+++ src/bp-members/bp-members-admin.php
@@ -112,3 +112,67 @@ function bp_members_type_admin_updated_messages( $messages = array() ) {
 	return $messages;
 }
 add_filter( 'term_updated_messages', 'bp_members_type_admin_updated_messages' );
+
+/**
+ * Formats xprofile field data about a signup/membership request for display.
+ *
+ * Operates recursively on arrays, which are then imploded with commas.
+ *
+ * @since 10.0.0
+ *
+ * @param string|array $value Field value.
+ */
+function bp_members_admin_format_xprofile_field_for_display( $value ) {
+	if ( is_array( $value ) ) {
+		$value = array_map( 'bp_signup_format_xprofile_field_for_display', $value );
+		$value = implode( ', ', $value );
+	} else {
+		$value = stripslashes( $value );
+		$value = esc_html( $value );
+	}
+
+	return $value;
+}
+
+/**
+ * Outputs Informations about a signup/membership request into a modal inside the Signups Admin Screen.
+ *
+ * @since 10.0.0
+ *
+ * @param array $signup_field_labels The Signup field labels.
+ * @param object|null $signup_object The signup data object.
+ */
+function bp_members_admin_preview_signup_profile_info( $signup_field_labels = array(), $signup_object = null ) {
+	if ( ! isset( $signup_object->meta ) || ! $signup_field_labels ) {
+		return;
+	}
+
+	// Init ids.
+	$profile_field_ids = array();
+
+	// Get all xprofile field IDs except field 1.
+	if ( ! empty( $signup_object->meta['profile_field_ids'] ) ) {
+		$profile_field_ids = array_flip( explode( ',', $signup_object->meta['profile_field_ids'] ) );
+		unset( $profile_field_ids[1] );
+	}
+	?>
+	<div id="signup-info-modal-<?php echo $signup_object->id; ?>" style="display:none;">
+		<h1><?php printf( '%1$s (%2$s)', esc_html( $signup_object->user_name ), esc_html( $signup_object->user_email ) ); ?></h1>
+		<h2><?php esc_html_e( 'Extended Profile Information', 'buddypress' ); ?></h2>
+
+		<table class="signup-profile-data-drawer wp-list-table widefat fixed striped">
+			<?php if ( 1 <= count( $profile_field_ids ) ): foreach ( array_keys( $profile_field_ids ) as $profile_field_id ) :
+				$field_value = isset( $signup_object->meta[ "field_{$profile_field_id}" ] ) ? $signup_object->meta[ "field_{$profile_field_id}" ] : ''; ?>
+				<tr>
+					<td class="column-fields"><?php echo esc_html( $signup_field_labels[ $profile_field_id ] ); ?></td>
+					<td><?php echo bp_members_admin_format_xprofile_field_for_display( $field_value ); ?></td>
+				</tr>
+			<?php endforeach; else:  ?>
+				<tr>
+					<td><?php esc_html_e( 'There is no additional information to display.', 'buddypress' ); ?></td>
+				</tr>
+			<?php endif; ?>
+		</table>
+	</div>
+	<?php
+}
diff --git src/bp-members/bp-members-functions.php src/bp-members/bp-members-functions.php
index 93fd7cafd..e61bdf632 100644
--- src/bp-members/bp-members-functions.php
+++ src/bp-members/bp-members-functions.php
@@ -2388,24 +2388,18 @@ function bp_core_signup_send_validation_email( $user_id, $user_email, $key, $sal
 	bp_send_email( 'core-user-registration', $to, $args );
 
 	// Record that the activation email has been sent.
-	$signups = BP_Signup::get(
-		array(
-			'activation_key' => $key,
-		)
-	);
+	$signup = bp_members_get_signup_by( 'activation_key', $key );
 
-	if ( ! empty( $signups['signups'] ) ) {
-		foreach ( $signups['signups'] as $signup ) {
-			$meta = array(
-				'sent_date'  => current_time( 'mysql', true ),
-				'count_sent' => $signup->count_sent + 1
-			);
+	if ( $signup ) {
+		$meta = array(
+			'sent_date'  => current_time( 'mysql', true ),
+			'count_sent' => $signup->count_sent + 1
+		);
 
-			BP_Signup::update( array(
-				'signup_id' => $signup->id,
-				'meta'      => $meta,
-			) );
-		}
+		BP_Signup::update( array(
+			'signup_id' => $signup->id,
+			'meta'      => $meta,
+		) );
 	}
 }
 
@@ -2450,25 +2444,47 @@ function bp_core_signup_disable_inactive( $user = null, $username = '', $passwor
 	}
 
 	// Unactivated user account found!
-	// Set up the feedback message.
-	$signup_id = $signup['signups'][0]->signup_id;
-
-	$resend_url_params = array(
-		'action' => 'bp-resend-activation',
-		'id'     => $signup_id,
-	);
+	/*
+	 * Don't allow users to resend their own activation email
+	 * when membership requests are enabled.
+	 */
+	if ( bp_get_membership_requests_required() ) {
+		$error_message = sprintf(
+			'<strong>%1$s</strong> %2$s',
+			esc_html_x( 'Error:', 'Warning displayed on the WP Login screen', 'buddypress' ),
+			esc_html_x( 'Your membership request has not yet been approved.', 'Error message displayed on the WP Login screen', 'buddypress' )
+		);
+	} else {
+		// Set up the feedback message.
+		$signup_id = $signup['signups'][0]->signup_id;
 
-	$resend_url = wp_nonce_url(
-		add_query_arg( $resend_url_params, wp_login_url() ),
-		'bp-resend-activation'
-	);
+		$resend_url_params = array(
+			'action' => 'bp-resend-activation',
+			'id'     => $signup_id,
+		);
 
-	$resend_string = '<br /><br />';
+		$resend_url = wp_nonce_url(
+			add_query_arg( $resend_url_params, wp_login_url() ),
+			'bp-resend-activation'
+		);
 
-	/* translators: %s: the activation url */
-	$resend_string .= sprintf( __( 'If you have not received an email yet, <a href="%s">click here to resend it</a>.', 'buddypress' ), esc_url( $resend_url ) );
+		$error_message = sprintf(
+			'<strong>%1$s</strong> %2$s<br /><br />%3$s',
+			esc_html_x( 'Error:', 'Warning displayed on the WP Login screen', 'buddypress' ),
+			esc_html_x( 'Your account has not been activated. Check your email for the activation link.', 'Error message displayed on the WP Login screen', 'buddypress' ),
+			sprintf(
+				/* translators: %s: the link to resend the activation email. */
+				esc_html_x( 'If you have not received an email yet, %s.', 'WP Login screen message', 'buddypress' ),
+				sprintf(
+					'<a href="%1$s">%2$s</a>',
+					esc_url( $resend_url ),
+					esc_html_x( 'click here to resend it', 'Text of the link to resend the activation email', 'buddypress' )
+				)
+			)
+		);
+	}
 
-	return new WP_Error( 'bp_account_not_activated', __( '<strong>Error</strong>: Your account has not been activated. Check your email for the activation link.', 'buddypress' ) . $resend_string );
+	return new WP_Error( 'bp_account_not_activated', $error_message );
 }
 add_filter( 'authenticate', 'bp_core_signup_disable_inactive', 30, 3 );
 
@@ -3694,3 +3710,42 @@ function bp_get_members_invitation_from_request() {
 	 */
 	return apply_filters( 'bp_get_members_invitation_from_request', $invite );
 }
+
+/**
+ * Get WP_User object corresponding to a record in the signups table.
+ *
+ * @since 10.0.0
+ *
+ * @param string $field Which fields to search by. Possible values are
+ *                      activation_key, user_email, id.
+ * @param string $value Value to search by.
+ * @return bool|BP_Signup $signup Found signup, returns first found
+ *                                if more than one is found.
+ */
+function bp_members_get_signup_by( $field = 'activation_key', $value = '' ) {
+	switch ( $field ) {
+		case 'activation_key':
+		case 'user_email':
+			$key = $field;
+			break;
+
+		case 'id':
+		default:
+			$key = 'include';
+			break;
+	}
+
+	$signups = BP_Signup::get(
+		array(
+			$key => $value,
+		)
+	);
+
+	if ( ! empty( $signups['signups'] ) ) {
+		$signup = current( $signups['signups'] );
+	} else {
+		$signup = false;
+	}
+
+	return $signup;
+}
diff --git src/bp-members/bp-members-invitations.php src/bp-members/bp-members-invitations.php
index 73f50e09b..2fadc0e94 100644
--- src/bp-members/bp-members-invitations.php
+++ src/bp-members/bp-members-invitations.php
@@ -183,3 +183,42 @@ function bp_members_invitations_delete_optedout_invites( $optout ) {
 	);
 }
 add_action( 'bp_optout_after_save', 'bp_members_invitations_delete_optedout_invites' );
+
+/**
+ * If a user submits a site membership request, but there's a
+ * sent invitation to her, bypass the manual approval of the request.
+ *
+ * @since 10.0.0
+ *
+ * @param bool  $send    Whether or not this membership request should be approved
+ *                       immediately and the activation email sent.
+ *                       Default is `false` meaning that the request should be
+ *                       manually approved by a site admin.
+ * @param array $details The details of the request.
+ */
+function bp_members_invitations_maybe_bypass_request_approval( $send, $details ) {
+	if ( ! bp_get_members_invitations_allowed() ) {
+		return $send;
+	}
+
+	// We'll need the prospective user's email address.
+	if ( empty( $details['user_email'] ) ) {
+		return $send;
+	}
+
+	$invites = bp_members_invitations_get_invites(
+		array(
+			'invitee_email' => $details['user_email'],
+			'invite_sent'   => 'sent'
+		)
+	);
+
+	// If pending invitations exist, send the verification mail.
+	if ( $invites ) {
+		$send = true;
+	}
+
+	return $send;
+}
+add_filter( 'bp_members_membership_requests_bypass_manual_approval', 'bp_members_invitations_maybe_bypass_request_approval', 10, 2 );
+add_filter( 'bp_members_membership_requests_bypass_manual_approval_multisite', 'bp_members_invitations_maybe_bypass_request_approval', 10, 2 );
diff --git src/bp-members/bp-members-membership-requests.php src/bp-members/bp-members-membership-requests.php
new file mode 100644
index 000000000..a55f71726
--- /dev/null
+++ src/bp-members/bp-members-membership-requests.php
@@ -0,0 +1,444 @@
+<?php
+/**
+ * BuddyPress Membership Requests
+ *
+ * @package BuddyPress
+ * @subpackage MembersMembershipRequest
+ * @since 10.0.0
+ */
+
+// Exit if accessed directly.
+defined( 'ABSPATH' ) || exit;
+
+/**
+ * Single site: When a user creates a membership request,
+ * prevent the sending of the activation email so that
+ * the site admins can send it manually.
+ *
+ * @since 10.0.0
+ *
+ * @param bool   $send           Whether or not to send the activation key.
+ * @param int    $user_id        User ID to send activation key to.
+ * @param string $user_email     User email to send activation key to.
+ * @param string $activation_key Activation key to be sent.
+ * @param array  $usermeta       Miscellaneous metadata about the user (blog-specific
+ *                               signup data, xprofile data, etc).
+ * @return bool Whether or not to send the activation key.
+ */
+function bp_members_membership_requests_cancel_activation_email( $send, $user_id = 0, $user_email = '', $activation_key = '', $usermeta = array() ) {
+
+	$details = array(
+		'user_id'        => $user_id,
+		'user_email'     => $user_email,
+		'activation_key' => $activation_key,
+		'usermeta'       => $usermeta,
+	);
+
+	/**
+	 * Allow some membership requests to be approved immediately.
+	 * For example, you might want to approve all requests
+	 * coming from users with certain email address domains.
+	 * If `true` is returned the activation email will be sent to the user.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @param bool  $send    Whether or not this membership request should be approved
+	 *                       immediately and the activation email sent.
+	 *                       Default is `false` meaning that the request should be
+	 *                       manually approved by a site admin.
+	 * @param array $details The details of the request.
+	 */
+	$send = apply_filters( 'bp_members_membership_requests_bypass_manual_approval', false, $details );
+
+	// If the registration process has been interrupted, this is a new membership request.
+	if ( ! $send ) {
+		$signup = bp_members_get_signup_by( 'activation_key', $activation_key );
+
+		/**
+		 * Fires when a site membership request has been created and is pending.
+		 *
+		 * @since 10.0.0
+		 *
+		 * @param BP_Signup $signup  The signup object that has been created.
+		 * @param array     $details The details of the request.
+		 */
+		do_action( 'bp_members_membership_request_submitted', $signup, $details );
+	}
+
+	return $send;
+}
+add_filter( 'bp_core_signup_send_activation_key', 'bp_members_membership_requests_cancel_activation_email', 10, 5 );
+
+/**
+ * WP Multisite: When a user creates a membership request,
+ * prevent the sending of the activation email so that
+ * the site admins can send it manually.
+ *
+ * @since 10.0.0
+ *
+ * @param bool   $send           Whether or not to send the activation key.
+ * @param string $user_login     User login name.
+ * @param string $user_email     User email address.
+ * @param string $activation_key Activation key created in wpmu_signup_user().
+ * @return bool Whether or not to send the activation key.
+ */
+function bp_members_membership_requests_cancel_activation_email_multisite( $send = true, $user_login = '', $user_email = '', $activation_key = '' ) {
+
+	$details = array(
+		'user_login'     => $user_login,
+		'user_email'     => $user_email,
+		'activation_key' => $activation_key,
+	);
+
+	/**
+	 * Allow some membership requests to be approved immediately.
+	 * For example, you might want to approve all requests
+	 * coming from users with certain email address domains.
+	 * If `true` is returned the activation email will be sent to the user.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @param bool  $send    Whether or not this membership request should be approved
+	 *                       immediately and the activation email sent.
+	 *                       Default is `false` meaning that the request should be
+	 *                       manually approved by a site admin.
+	 * @param array $details The details of the request.
+	 */
+	$send = apply_filters( 'bp_members_membership_requests_bypass_manual_approval_multisite', false, $details );
+
+	// If the registration process has been interrupted, this is a new membership request.
+	if ( ! $send ) {
+		$signup = bp_members_get_signup_by( 'activation_key', $activation_key );
+
+		/**
+		 * Fires when a site membership request has been created and is pending.
+		 *
+		 * @since 10.0.0
+		 *
+		 * @param BP_Signup $signup  The signup object that has been created.
+		 * @param array     $details The details of the request.
+		 */
+		do_action( 'bp_members_membership_request_submitted', $signup, $details );
+	}
+
+	return $send;
+}
+add_filter( 'bp_core_signup_send_activation_key_multisite', 'bp_members_membership_requests_cancel_activation_email_multisite', 10, 4 );
+add_filter( 'bp_core_signup_send_activation_key_multisite_blog', 'bp_members_membership_requests_cancel_activation_email_multisite', 10, 4 );
+
+/**
+ * Notifications
+ *********************************************************************/
+
+/**
+ * Notify site admins about a new membership request.
+ *
+ * @since 10.0.0
+ *
+ * @param BP_Signup $signup  The signup object that has been created.
+ */
+function bp_members_membership_requests_notify_site_admins( $signup ) {
+
+	if ( ! isset( $signup->signup_id ) ) {
+		return;
+	}
+
+	// Notify all site admins so the request can be handled.
+	$admin_ids = get_users(
+		array(
+			'fields' => 'ids',
+			'role'   => 'administrator',
+		)
+	);
+
+	foreach ( $admin_ids as $admin_id ) {
+		// Trigger a BuddyPress Notification.
+		if ( bp_is_active( 'notifications' ) ) {
+			bp_notifications_add_notification(
+				array(
+					'user_id'          => $admin_id,
+					'item_id'          => $signup->signup_id,
+					'component_name'   => buddypress()->members->id,
+					'component_action' => 'membership_request_submitted',
+					'date_notified'    => bp_core_current_time(),
+					'is_new'           => 1,
+				)
+			);
+		}
+
+		// Bail if member opted out of receiving this email.
+		if ( 'no' === bp_get_user_meta( $admin_id, 'notification_members_membership_request', true ) ) {
+			return;
+		}
+
+		$unsubscribe_args = array(
+			'user_id'           => $admin_id,
+			'notification_type' => 'members-membership-request',
+		);
+
+		$manage_url = add_query_arg(
+			array(
+				'mod_req'   => 1,
+				'page'      => 'bp-signups',
+				'signup_id' => $signup->signup_id,
+				'action'    => 'resend',
+			),
+			bp_get_admin_url( 'users.php' )
+		);
+
+		$args  = array(
+			'tokens' => array(
+				'admin.id'                   => $admin_id,
+				'manage.url'                 => esc_url_raw( $manage_url ),
+				'requesting-user.user_login' => esc_html( $signup->user_login ),
+				'unsubscribe'                => esc_url( bp_email_get_unsubscribe_link( $unsubscribe_args ) ),
+			),
+		);
+
+		bp_send_email( 'members-membership-request', (int) $admin_id, $args );
+	}
+}
+add_action( 'bp_members_membership_request_submitted', 'bp_members_membership_requests_notify_site_admins' );
+
+/**
+ * Send a message to the requesting user when his or her
+ * site membership request has been rejected.
+ *
+ * @since 10.0.0
+ *
+ * @param array $signup_ids Array of pending IDs to delete.
+ */
+function bp_members_membership_requests_send_rejection_mail( $signup_ids ) {
+	$signups = BP_Signup::get(
+		array(
+			'include' => $signup_ids,
+		)
+	);
+
+	if ( empty( $signups['signups'] ) ) {
+		return;
+	}
+
+	foreach ( $signups['signups'] as $signup ) {
+		if ( ! empty( $signup->user_email ) ) {
+			bp_send_email( 'members-membership-request-rejected', $signup->user_email );
+		}
+	}
+}
+add_action( 'bp_core_signup_before_delete', 'bp_members_membership_requests_send_rejection_mail' );
+
+/**
+ * When a request is approved, activated or deleted,
+ * delete the associated notifications.
+ *
+ * @since 10.0.0
+ *
+ * @param array $signup_ids Array of changing signup IDs.
+ */
+function bp_members_membership_requests_delete_notifications_on_change( $signup_ids ) {
+	foreach ( $signup_ids as $signup_id ) {
+		BP_Notifications_Notification::delete(
+			array(
+				'item_id'          => $signup_id,
+				'component_action' => 'membership_request_submitted',
+			)
+		);
+	}
+}
+add_action( 'bp_core_signup_after_resend',   'bp_members_membership_requests_delete_notifications_on_change' );
+add_action( 'bp_core_signup_after_activate', 'bp_members_membership_requests_delete_notifications_on_change' );
+add_action( 'bp_core_signup_after_delete',   'bp_members_membership_requests_delete_notifications_on_change' );
+
+/**
+ * In the Nouveau template pack, when membership requests are required,
+ * change registration form submit button label to "Submit Request".
+ *
+ * @since 10.0.0
+ *
+ * @return string $retval the HTML for the request membership link.
+ */
+function bp_members_membership_requests_filter_complete_signup_button( $buttons ) {
+
+	$buttons['register']['attributes']['value'] = __( 'Submit Request', 'buddypress' );
+	return $buttons;
+}
+add_filter( 'bp_nouveau_get_submit_button', 'bp_members_membership_requests_filter_complete_signup_button' );
+
+
+/**
+ * Administration: Change certain behavior and labels
+ * on the WP Admin > Users > Manage Signups screen.
+ *********************************************************************/
+
+/**
+ * Filter the actions available on the signups list table.
+ *
+ * @since 10.0.0
+ *
+ * @param array  $actions       Array of actions and corresponding links.
+ * @param object $signup_object The signup data object.
+ */
+function bp_members_membership_requests_filter_signup_row_actions( $actions, $signup_object ) {
+
+	// Rename the "email" resend option when membership requests are active.
+	$email_link = add_query_arg(
+		array(
+			'page'	    => 'bp-signups',
+			'signup_id' => $signup_object->id,
+			'action'    => 'resend',
+		),
+		bp_get_admin_url( 'users.php' )
+	);
+
+	$resend_label = ( 0 === $signup_object->count_sent ) ? __( 'Approve Request', 'buddypress' ) : __( 'Resend Approval', 'buddypress' );
+
+	$actions['resend'] = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $email_link ), esc_html( $resend_label ) );
+
+	// Add a link to view profile info when membership requests and xprofile are active.
+	if ( bp_is_active( 'xprofile' ) ) {
+		$profile_link = add_query_arg(
+			array(
+				'page'	   => 'bp-signups#TB_inline',
+				'inlineId' => 'signup-info-modal-' . $signup_object->id,
+			),
+			bp_get_admin_url( 'users.php' )
+		);
+
+		$actions['profile'] = sprintf( '<a href="%1$s" class="bp-thickbox">%2$s</a>', esc_url( $profile_link ), esc_html__( 'Profile Info', 'buddypress' ) );
+	}
+
+	return $actions;
+}
+add_filter( 'bp_members_ms_signup_row_actions', 'bp_members_membership_requests_filter_signup_row_actions', 10, 2 );
+
+/**
+ * Filter the bulk actions available on the signups list table.
+ *
+ * @since 10.0.0
+ *
+ * @param array $actions Array of actions and corresponding links.
+ * @return array         List of actions and corresponding links.
+ */
+function bp_members_membership_requests_filter_signup_bulk_actions( $actions ) {
+	// Rename the "email" resend option when membership requests are active.
+	$actions['resend'] = esc_html_x( 'Approve', 'Pending signup action', 'buddypress' );
+	return $actions;
+}
+add_filter( 'bp_members_ms_signup_bulk_actions', 'bp_members_membership_requests_filter_signup_bulk_actions' );
+
+/**
+ * Filter the "Last Sent" column header on the pending users table.
+ *
+ * @since 10.0.0
+ *
+ * @param array $columns Array of columns to display.
+ * @return array List of columns to display.
+ */
+function bp_members_membership_requests_filter_signup_table_date_sent_header( $columns ) {
+	$columns['date_sent'] = esc_html__( 'Approved', 'buddypress' );
+	return $columns;
+}
+add_filter( 'bp_members_signup_columns', 'bp_members_membership_requests_filter_signup_table_date_sent_header' );
+add_filter( 'bp_members_ms_signup_columns', 'bp_members_membership_requests_filter_signup_table_date_sent_header' );
+
+/**
+ * Filter the "Last Sent" column message on the pending users table.
+ *
+ * @since 10.0.0
+ *
+ * @param string      $message "Not yet sent" message.
+ * @param object|null $signup  Signup object instance.
+ * @return string              "Not yet approved" message, if needed. Unchanged message otherwise.
+ */
+function bp_members_membership_requests_filter_signup_table_unsent_message( $message, $signup ) {
+	if ( 0 === $signup->count_sent ) {
+		$message = esc_html__( 'Not yet approved', 'buddypress' );
+	}
+
+	return $message;
+}
+add_filter( 'bp_members_signup_date_sent_unsent_message', 'bp_members_membership_requests_filter_signup_table_unsent_message', 10, 2 );
+add_filter( 'bp_members_ms_signup_date_sent_unsent_message', 'bp_members_membership_requests_filter_signup_table_unsent_message', 10, 2 );
+
+/**
+ * Filter/add "Request Membership" links in the following locations:
+ * - BP login widget,
+ * - Sidebar register link,
+ * - WP Toolbar,
+ * - WP login form.
+ *********************************************************************/
+
+/**
+ * Add "Request Membership" link to Widget login form.
+ *
+ * @since 10.0.0
+ *
+ * @return string $retval the HTML for the request membership link.
+ */
+function bp_members_membership_requests_add_link_to_widget_login_form() {
+	?>
+	<span class="bp-login-widget-request-membership-link"><a href="<?php echo esc_url( bp_get_signup_page() ); ?>"><?php esc_html_e( 'Request Membership', 'buddypress' ); ?></a></span>
+	<?php
+}
+add_action( 'bp_login_widget_form', 'bp_members_membership_requests_add_link_to_widget_login_form' );
+
+/**
+ * Filter the "Register" link from `wp_register()` as used in
+ * `sidebar.php` and the WP Core meta widget.
+ *
+ * @since 10.0.0
+ *
+ * @param string $link The HTML code for the link to the Registration or Admin page.
+ * @return string      An empty string or the HTML code for the link to the Membership request page.
+ */
+function bp_members_membership_requests_filter_sidebar_register_link( $link ) {
+	// $link should be an empty string when public registration is disabled.
+	if ( ! is_user_logged_in() && empty( $link ) ) {
+		$link = '<a href="' . esc_url( wp_registration_url() ) . '">' . esc_html__( 'Request Membership', 'buddypress' ) . '</a>';
+	}
+
+	return $link;
+}
+add_filter( 'register', 'bp_members_membership_requests_filter_sidebar_register_link' );
+
+/**
+ * Add a "Request Membership" link to the WP Toolbar.
+ * Priority 21 should place it just after the "Log In" link.
+ *
+ * @since 10.0.0
+ *
+ * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance, passed by reference
+ */
+function bp_members_membership_requests_add_toolbar_link( $wp_admin_bar ) {
+	if ( is_user_logged_in() ) {
+		return;
+	}
+
+	$args = array(
+		'id'    => 'bp-request-membership',
+		'title' => __( 'Request Membership', 'buddypress' ),
+		'href'  => wp_registration_url(),
+		'meta'  => array(
+			'class' => 'buddypress-request-membership',
+			'title' => __( 'Request Membership', 'buddypress' ),
+		),
+	);
+
+	$wp_admin_bar->add_node( $args );
+}
+add_action( 'admin_bar_menu', 'bp_members_membership_requests_add_toolbar_link', 21 );
+
+/**
+ * Add a "Request Membership" link to the WP Login form.
+ *
+ * @since 10.0.0
+ *
+ * @param string $link HTML link to the home URL of the current site.
+ * @return string      HTML link to the home URL of the current site and the one to request a membership.
+ */
+function bp_members_membership_requests_add_link_wp_login( $link ) {
+	$link_separator = apply_filters( 'login_link_separator', ' | ' );
+
+	return $link . $link_separator . '<a href="' . esc_url( wp_registration_url() ) . '">' . esc_html__( 'Request Membership', 'buddypress' ) . '</a>';
+}
+add_action( 'login_site_html_link', 'bp_members_membership_requests_add_link_wp_login' );
diff --git src/bp-members/bp-members-notifications.php src/bp-members/bp-members-notifications.php
index 93cee7b89..08285bcb6 100644
--- src/bp-members/bp-members-notifications.php
+++ src/bp-members/bp-members-notifications.php
@@ -61,6 +61,30 @@ function members_format_notifications( $action, $item_id, $secondary_item_id, $t
 				}
 			}
 			break;
+
+		case 'membership_request_submitted':
+			// $item_id is the id of the signup, not the user ID.
+			$signup = new BP_Signup( $item_id );
+
+			// Set up the string and the filter.
+			if ( (int) $total_items > 1 ) {
+				$link   = bp_get_notifications_permalink();
+				$amount = 'multiple';
+
+				$text = sprintf( __( '%d people have requested site membership.', 'buddypress' ), (int) $total_items );
+			} else {
+				$link   = add_query_arg( array(
+					'mod_req'   => 1,
+					'page'      => 'bp-signups',
+					'signup_id' => $item_id,
+					'action'    => 'resend',
+				), bp_get_admin_url( 'users.php' ) );
+				$amount = 'single';
+
+				/* translators: %s: new user name */
+				$text = sprintf( __( '%s has requested site membership.', 'buddypress' ),  esc_html( $signup->user_login ) );
+			}
+			break;
 	}
 
 	// Return either an HTML link or an array, depending on the requested format.
@@ -167,13 +191,37 @@ function bp_members_mark_read_accepted_invitation_notification() {
 			'is_new' => false,
 		),
 		array(
-			'user_id' => bp_loggedin_user_id(),
-			'item_id' => bp_displayed_user_id(),
+			'user_id'          => bp_loggedin_user_id(),
+			'item_id'          => bp_displayed_user_id(),
+			'component_action' => 'accepted_invitation',
 		)
 	);
 }
 add_action( 'bp_screens', 'bp_members_mark_read_accepted_invitation_notification' );
 
+/**
+ * Mark new membership request notifications as read when user visits Manage BP Signups screen.
+ *
+ * @since 10.0.0
+ */
+function bp_members_mark_read_submitted_membership_request_notification() {
+
+	$signup_screens = array( 'users_page_bp-signups', 'users_page_bp-signups-network' );
+	if ( ! wp_doing_ajax() && in_array( get_current_screen()->base, $signup_screens, true ) && ! empty( $_GET['mod_req'] ) && ! empty( $_GET['signup_id'] ) ) {
+		// Mark all notifications about this request as read.
+		BP_Notifications_Notification::update(
+			array(
+				'is_new' => false,
+			),
+			array(
+				'item_id'          => $_GET['signup_id'],
+				'component_action' => 'membership_request_submitted',
+			)
+		);
+	}
+}
+add_action( 'admin_footer', 'bp_members_mark_read_submitted_membership_request_notification' );
+
 /**
  * Add Members-related settings to the Settings > Notifications page.
  *
@@ -181,14 +229,10 @@ add_action( 'bp_screens', 'bp_members_mark_read_accepted_invitation_notification
  */
 function members_screen_notification_settings() {
 
-	// Bail early if invitations are not allowed--they are the only members notification so far.
-	if ( ! bp_get_members_invitations_allowed () ) {
+	// Bail early if invitations and requests are not allowed--they are the only members notification so far.
+	if ( ! bp_get_members_invitations_allowed() && ( ! bp_get_membership_requests_required() || ! user_can( bp_displayed_user_id(), 'bp_moderate' ) ) ) {
 		return;
 	}
-
-	if ( ! $allow_acceptance_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_invitation_accepted', true ) ) {
-		$allow_acceptance_emails = 'yes';
-	}
 	?>
 
 	<table class="notification-settings" id="members-notification-settings">
@@ -202,20 +246,47 @@ function members_screen_notification_settings() {
 		</thead>
 
 		<tbody>
-			<tr id="members-notification-settings-invitation_accepted">
-				<td></td>
-				<td><?php _ex( 'Someone accepts your membership invitation', 'Member settings on notification settings page', 'buddypress' ) ?></td>
-				<td class="yes"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-yes" value="yes" <?php checked( $allow_acceptance_emails, 'yes', true ) ?>/><label for="notification-members-invitation-accepted-yes" class="bp-screen-reader-text"><?php
-					/* translators: accessibility text */
-					_e( 'Yes, send email', 'buddypress' );
-				?></label></td>
-				<td class="no"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-no" value="no" <?php checked( $allow_acceptance_emails, 'no', true ) ?>/><label for="notification-members-invitation-accepted-no" class="bp-screen-reader-text"><?php
-					/* translators: accessibility text */
-					_e( 'No, do not send email', 'buddypress' );
-				?></label></td>
-			</tr>
 
 			<?php
+			if ( bp_get_members_invitations_allowed() ) :
+				if ( ! $allow_acceptance_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_invitation_accepted', true ) ) {
+					$allow_acceptance_emails = 'yes';
+				}
+				?>
+				<tr id="members-notification-settings-invitation_accepted">
+					<td></td>
+					<td><?php echo esc_html_x( 'Someone accepts your membership invitation', 'Member settings on notification settings page', 'buddypress' ); ?></td>
+					<td class="yes"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-yes" value="yes" <?php checked( $allow_acceptance_emails, 'yes', true ) ?>/><label for="notification-members-invitation-accepted-yes" class="bp-screen-reader-text"><?php
+						/* translators: accessibility text */
+						esc_html_e( 'Yes, send email', 'buddypress' );
+					?></label></td>
+					<td class="no"><input type="radio" name="notifications[notification_members_invitation_accepted]" id="notification-members-invitation-accepted-no" value="no" <?php checked( $allow_acceptance_emails, 'no', true ) ?>/><label for="notification-members-invitation-accepted-no" class="bp-screen-reader-text"><?php
+						/* translators: accessibility text */
+						esc_html_e( 'No, do not send email', 'buddypress' );
+					?></label></td>
+				</tr>
+				<?php
+			endif;
+
+			if ( bp_get_membership_requests_required() && user_can( bp_displayed_user_id(), 'bp_moderate' ) ) :
+				if ( ! $allow_request_emails = bp_get_user_meta( bp_displayed_user_id(), 'notification_members_membership_request', true ) ) {
+					$allow_request_emails = 'yes';
+				}
+				?>
+				<tr id="members-notification-settings-submitted_membership_request">
+					<td></td>
+					<td><?php echo esc_html_x( 'Someone has requested site membership', 'Member settings on notification settings page', 'buddypress' ) ?></td>
+					<td class="yes"><input type="radio" name="notifications[notification_members_membership_request]" id="notification-members-submitted_membership_request-yes" value="yes" <?php checked( $allow_request_emails, 'yes', true ) ?>/><label for="notification-members-submitted_membership_request-yes" class="bp-screen-reader-text"><?php
+						/* translators: accessibility text */
+						esc_html_e( 'Yes, send email', 'buddypress' );
+					?></label></td>
+					<td class="no"><input type="radio" name="notifications[notification_members_membership_request]" id="notification-members-submitted_membership_request-no" value="no" <?php checked( $allow_request_emails, 'no', true ) ?>/><label for="notification-members-submitted_membership_request-no" class="bp-screen-reader-text"><?php
+						/* translators: accessibility text */
+						esc_html_e( 'No, do not send email', 'buddypress' );
+					?></label></td>
+				</tr>
+				<?php
+			endif;
 
 			/**
 			 * Fires after the last table row on the members notification screen.
diff --git src/bp-members/bp-members-template.php src/bp-members/bp-members-template.php
index 10e6ef071..c9616ff9c 100644
--- src/bp-members/bp-members-template.php
+++ src/bp-members/bp-members-template.php
@@ -2921,6 +2921,35 @@ function bp_get_members_invitations_allowed() {
 	return apply_filters( 'bp_get_members_invitations_allowed', bp_is_active( 'members', 'invitations' ) && (bool) bp_get_option( 'bp-enable-members-invitations' ) );
 }
 
+/**
+ * Are membership requests required for joining this site?
+ *
+ * @since 10.0.0
+ *
+ * @param bool $context "raw" to fetch value from database,
+ *                      "site" to take "anyone can register" setting into account.
+ * @return bool
+ */
+function bp_get_membership_requests_required( $context = 'site' ) {
+	if ( 'raw' === $context ) {
+		$retval = bp_is_active( 'members', 'membership_requests' ) && (bool) bp_get_option( 'bp-enable-membership-requests' );
+	} else {
+		$retval = bp_is_active( 'members', 'membership_requests' ) && ! bp_get_signup_allowed() && (bool) bp_get_option( 'bp-enable-membership-requests' );
+	}
+
+	/**
+	 * Filters whether or not prospective members may submit network membership requests.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @param bool $retval Whether or not membership requests are required.
+	 * @param bool $retval Whether this is the value stored in the database ('raw')
+	 *                     or whether the site's "anyone can register" setting is
+	 *                     being considered ('site' or anything else).
+	 */
+	return apply_filters( 'bp_get_membership_requests_required', $retval, $context );
+}
+
 /**
  * Should the system create and allow access
  * to the Register and Activate pages?
@@ -2930,7 +2959,7 @@ function bp_get_members_invitations_allowed() {
  * @return bool
  */
 function bp_allow_access_to_registration_pages() {
-	$retval = bp_get_signup_allowed() || bp_get_members_invitations_allowed();
+	$retval = bp_get_signup_allowed() || bp_get_members_invitations_allowed() || bp_get_membership_requests_required();
 
 	/**
 	 * Filters whether or not the system should create and allow access
diff --git src/bp-members/classes/class-bp-members-admin.php src/bp-members/classes/class-bp-members-admin.php
index 979847a18..6c94cf20c 100644
--- src/bp-members/classes/class-bp-members-admin.php
+++ src/bp-members/classes/class-bp-members-admin.php
@@ -514,10 +514,16 @@ class BP_Members_Admin {
 		// Only show sign-ups where they belong.
 		if ( ( ! bp_is_network_activated() && ! is_network_admin() ) || ( is_network_admin() && bp_is_network_activated() ) ) {
 
+			$signups_menu_label = __( 'Manage Signups',  'buddypress' );
+
+			if ( bp_get_membership_requests_required() ) {
+				$signups_menu_label = __( 'Manage Pending Memberships',  'buddypress' );
+			}
+
 			// Manage signups.
 			$hooks['signups'] = $this->signups_page = add_users_page(
-				__( 'Manage Signups',  'buddypress' ),
-				__( 'Manage Signups',  'buddypress' ),
+				$signups_menu_label,
+				$signups_menu_label,
 				$this->capability,
 				'bp-signups',
 				array( $this, 'signups_admin' )
@@ -1687,7 +1693,7 @@ class BP_Members_Admin {
 		 */
 		$allowed_actions = apply_filters( 'bp_signups_admin_allowed_actions', array( 'do_delete', 'do_activate', 'do_resend' ) );
 
-		// Prepare the display of the Community Profile screen.
+		// Prepare the display of the Signups screen.
 		if ( ! in_array( $doaction, $allowed_actions ) || ( -1 == $doaction ) ) {
 
 			if ( is_network_admin() ) {
@@ -1709,20 +1715,34 @@ class BP_Members_Admin {
 				'<p>' . __( 'Using the search form, you can find pending accounts more easily. The Username and Email fields will be included in the search.', 'buddypress' ) . '</p>'
 			) );
 
+			$signup_help_content = '<p>' . esc_html__( 'Hovering over a row in the pending accounts list will display action links that allow you to manage pending accounts. You can perform the following actions:', 'buddypress' ) . '</p>';
+
+			if ( bp_get_membership_requests_required() ) {
+				$signup_help_content .= '<ul><li>' . esc_html__( '"Activate" will activate the user immediately without requiring that they validate their email.', 'buddypress' ) .'</li>' .
+					'<li>' . esc_html__( '"Approve Request" or "Resend Approval" takes you to the confirmation screen before being able to send the activation link to the desired pending request. You can only send the activation email once per day.', 'buddypress' ) . '</li>';
+
+				if ( bp_is_active( 'xprofile' ) ) {
+					$signup_help_content .=	'<li>' . esc_html__( '"Profile Info" will display extended profile information for the request.', 'buddypress' ) . '</li>';
+				}
+
+				$signup_help_content .= '<li>' . esc_html__( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>';
+			} else {
+				$signup_help_content .= '<ul><li>' . esc_html__( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' .
+					'<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>';
+			}
+
+			$signup_help_content .= '<p>' . esc_html__( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' .
+				'<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>';
+
 			get_current_screen()->add_help_tab( array(
 				'id'      => 'bp-signups-actions',
 				'title'   => __( 'Actions', 'buddypress' ),
-				'content' =>
-				'<p>' . __( 'Hovering over a row in the pending accounts list will display action links that allow you to manage pending accounts. You can perform the following actions:', 'buddypress' ) . '</p>' .
-				'<ul><li>' . __( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' .
-				'<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' .
-				'<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' .
-				'<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>'
+				'content' => $signup_help_content
 			) );
 
 			// Help panel - sidebar links.
 			get_current_screen()->set_help_sidebar(
-				'<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
+				'<p><strong>' . esc_html__( 'For more information:', 'buddypress' ) . '</strong></p>' .
 				'<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
 			);
 
@@ -1736,6 +1756,25 @@ class BP_Members_Admin {
 				'heading_list'       => __( 'Pending users list', 'buddypress' ),
 			) );
 
+			// Use thickbox to display the extended profile information.
+			if ( bp_is_active( 'xprofile' ) ) {
+				wp_enqueue_style( 'thickbox' );
+				wp_enqueue_script(
+					'bp-signup-preview',
+					$this->js_url . 'signup-preview' . bp_core_get_minified_asset_suffix() . '.js',
+					array( 'bp-thickbox', 'jquery' ),
+					bp_get_version(),
+					true
+				);
+				wp_localize_script(
+					'bp-signup-preview',
+					'bpSignupPreview',
+					array(
+						'modalLabel' => __( 'Profile info preview', 'buddypress' ),
+					)
+				);
+			}
+
 		} else {
 			if ( ! empty( $_REQUEST['signup_ids' ] ) ) {
 				$signups = wp_parse_id_list( $_REQUEST['signup_ids' ] );
@@ -2204,7 +2243,7 @@ class BP_Members_Admin {
 		) );
 
 		$signups    = $signups_query['signups'];
-		$signup_ids = wp_list_pluck( $signups, 'signup_id' );
+		$signup_ids = wp_list_pluck( $signups, 'id' );
 
 		// Set up strings.
 		switch ( $action ) {
@@ -2227,13 +2266,24 @@ class BP_Members_Admin {
 				break;
 
 			case 'resend' :
-				$header_text = __( 'Resend Activation Emails', 'buddypress' );
-				if ( 1 == count( $signup_ids ) ) {
-					$helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' );
+
+				if ( bp_get_membership_requests_required() ) {
+					$header_text = __( 'Approve Membership Requests', 'buddypress' );
+					if ( 1 === count( $signup_ids ) ) {
+						$helper_text = __( 'You are about to send an approval email to the following user:', 'buddypress' );
+					} else {
+						$helper_text = __( 'You are about to send approval emails to the following users:', 'buddypress' );
+					}
 				} else {
-					$helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' );
+					$header_text = __( 'Resend Activation Emails', 'buddypress' );
+					if ( 1 === count( $signup_ids ) ) {
+						$helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' );
+					} else {
+						$helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' );
+					}
 				}
 				break;
+
 		}
 
 		// These arguments are added to all URLs.
@@ -2262,7 +2312,7 @@ class BP_Members_Admin {
 
 		// Prefetch registration field data.
 		$fdata = array();
-		if ( 'activate' === $action && bp_is_active( 'xprofile' ) ) {
+		if ( bp_is_active( 'xprofile' ) && ( 'activate' == $action || ( 'resend' == $action && bp_get_membership_requests_required() ) ) ) {
 			$field_groups = bp_xprofile_get_groups( array(
 				'exclude_fields'    => 1,
 				'update_meta_cache' => false,
@@ -2286,7 +2336,11 @@ class BP_Members_Admin {
 
 			<ol class="bp-signups-list">
 			<?php foreach ( $signups as $signup ) :
-				$last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent );
+				if ( $signup->count_sent > 0 ) {
+					$last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent );
+				} else {
+					$last_notified = __( 'Not yet notified', 'buddypress' );
+				}
 				$profile_field_ids = array();
 
 				// Get all xprofile field IDs except field 1.
@@ -2298,7 +2352,7 @@ class BP_Members_Admin {
 				<li>
 					<strong><?php echo esc_html( $signup->user_login ) ?></strong>
 
-					<?php if ( 'activate' == $action ) : ?>
+					<?php if ( 'activate' == $action || ( 'resend' == $action && bp_get_membership_requests_required() ) ) : ?>
 						<table class="wp-list-table widefat fixed striped">
 							<tbody>
 								<tr>
@@ -2316,7 +2370,7 @@ class BP_Members_Admin {
 										$field_value = isset( $signup->meta[ "field_{$pid}" ] ) ? $signup->meta[ "field_{$pid}" ] : ''; ?>
 										<tr>
 											<td class="column-fields"><?php echo esc_html( $fdata[ $pid ] ); ?></td>
-											<td><?php echo $this->format_xprofile_field_for_display( $field_value ); ?></td>
+											<td><?php echo bp_members_admin_format_xprofile_field_for_display( $field_value ); ?></td>
 										</tr>
 
 									<?php endforeach;  ?>
@@ -2622,20 +2676,15 @@ class BP_Members_Admin {
 	 * Operates recursively on arrays, which are then imploded with commas.
 	 *
 	 * @since 2.8.0
+	 * @deprecated 10.0.0
 	 *
 	 * @param string|array $value Field value.
 	 * @return string
 	 */
 	protected function format_xprofile_field_for_display( $value ) {
-		if ( is_array( $value ) ) {
-			$value = array_map( array( $this, 'format_xprofile_field_for_display' ), $value );
-			$value = implode( ', ', $value );
-		} else {
-			$value = stripslashes( $value );
-			$value = esc_html( $value );
-		}
+		_deprecated_function( __METHOD__, '10.0.0', 'bp_members_admin_format_xprofile_field_for_display' );
 
-		return $value;
+		return bp_members_admin_format_xprofile_field_for_display( $value );
 	}
 
 	/**
diff --git src/bp-members/classes/class-bp-members-component.php src/bp-members/classes/class-bp-members-component.php
index 7bca5d8bb..17c82b95f 100644
--- src/bp-members/classes/class-bp-members-component.php
+++ src/bp-members/classes/class-bp-members-component.php
@@ -40,7 +40,7 @@ class BP_Members_Component extends BP_Component {
 			array(
 				'adminbar_myaccount_order' => 20,
 				'search_query_arg'         => 'members_search',
-				'features'                 => array( 'invitations' )
+				'features'                 => array( 'invitations', 'membership_requests' ),
 			)
 		);
 	}
@@ -74,6 +74,19 @@ class BP_Members_Component extends BP_Component {
 			$includes[] = 'activity';
 		}
 
+		/**
+		 * Duplicate bp_get_membership_requests_required() and
+		 * bp_get_signup_allowed() logic here,
+		 * because those functions are not available yet.
+		 * The `bp_get_signup_allowed` filter is documented in
+		 * bp-members/bp-members-template.php.
+		 */
+		$signup_allowed = apply_filters( 'bp_get_signup_allowed', (bool) bp_get_option( 'users_can_register' ) );
+		$membership_requests_enabled = (bool) bp_get_option( 'bp-enable-membership-requests' );
+		if ( bp_is_active( 'members', 'membership_requests' ) && ! $signup_allowed && $membership_requests_enabled ) {
+			$includes[] = 'membership-requests';
+		}
+
 		// Include these only if in admin.
 		if ( is_admin() ) {
 			$includes[] = 'admin';
diff --git src/bp-members/classes/class-bp-members-list-table.php src/bp-members/classes/class-bp-members-list-table.php
index 8e7733b47..0dcf21d7c 100644
--- src/bp-members/classes/class-bp-members-list-table.php
+++ src/bp-members/classes/class-bp-members-list-table.php
@@ -26,6 +26,15 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 */
 	public $signup_counts = 0;
 
+	/**
+	 * Signup profile fields.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @var array
+	 */
+	public $signup_field_labels = array();
+
 	/**
 	 * Constructor.
 	 *
@@ -138,14 +147,7 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 */
 	public function get_columns() {
 
-		/**
-		 * Filters the single site Members signup columns.
-		 *
-		 * @since 2.0.0
-		 *
-		 * @param array $value Array of columns to display.
-		 */
-		return apply_filters( 'bp_members_signup_columns', array(
+		$columns = array(
 			'cb'         => '<input type="checkbox" />',
 			'username'   => __( 'Username',    'buddypress' ),
 			'name'       => __( 'Name',        'buddypress' ),
@@ -153,7 +155,16 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 			'registered' => __( 'Registered',  'buddypress' ),
 			'date_sent'  => __( 'Last Sent',   'buddypress' ),
 			'count_sent' => __( 'Emails Sent', 'buddypress' )
-		) );
+		);
+
+		/**
+		 * Filters the single site Members signup columns.
+		 *
+		 * @since 2.0.0
+		 *
+		 * @param array $value Array of columns to display.
+		 */
+		return apply_filters( 'bp_members_signup_columns', $columns );
 	}
 
 	/**
@@ -171,7 +182,14 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 			$actions['delete'] = __( 'Delete', 'buddypress' );
 		}
 
-		return $actions;
+		/**
+		 * Filters the bulk actions for signups.
+		 *
+		 * @since 10.0.0
+		 *
+		 * @param array $actions Array of actions and corresponding labels.
+		 */
+		return apply_filters( 'bp_members_ms_signup_bulk_actions', $actions );
 	}
 
 	/**
@@ -183,7 +201,7 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 */
 	public function no_items() {
 
-		if ( bp_get_signup_allowed() ) {
+		if ( bp_get_signup_allowed() || bp_get_membership_requests_required() ) {
 			esc_html_e( 'No pending accounts found.', 'buddypress' );
 		} else {
 			$link = false;
@@ -342,6 +360,31 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 */
 	public function column_name( $signup_object = null ) {
 		echo esc_html( $signup_object->user_name );
+
+		// Insert the extended profile modal content required by thickbox.
+		if ( ! bp_is_active( 'xprofile' ) ) {
+			return;
+		}
+
+		$profile_field_ids = array();
+
+		// Fetch registration field data once only.
+		if ( ! $this->signup_field_labels ) {
+			$field_groups = bp_xprofile_get_groups(
+				array(
+					'fetch_fields'       => true,
+					'signup_fields_only' => true,
+				)
+			);
+
+			foreach( $field_groups as $field_group ) {
+				foreach( $field_group->fields as $field ) {
+					$this->signup_field_labels[ $field->id ] = $field->name;
+				}
+			}
+		}
+
+		bp_members_admin_preview_signup_profile_info( $this->signup_field_labels, $signup_object );
 	}
 
 	/**
@@ -363,7 +406,7 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 * @param object|null $signup_object The signup data object.
 	 */
 	public function column_registered( $signup_object = null ) {
-		echo mysql2date( 'Y/m/d', $signup_object->registered );
+		echo mysql2date( 'Y/m/d g:i:s a', $signup_object->registered );
 	}
 
 	/**
@@ -374,11 +417,28 @@ class BP_Members_List_Table extends WP_Users_List_Table {
 	 * @param object|null $signup_object The signup data object.
 	 */
 	public function column_date_sent( $signup_object = null ) {
-		echo mysql2date( 'Y/m/d', $signup_object->date_sent );
+		if ( $signup_object->count_sent > 0 ) {
+			echo mysql2date( 'Y/m/d g:i:s a', $signup_object->date_sent );
+		} else {
+			$message = __( 'Not yet notified', 'buddypress' );
+
+			/**
+			 * Filters the "not yet sent" message for "Last Sent"
+			 * column in Manage Signups list table.
+			 *
+			 * @since 10.0.0
+			 *
+			 * @param string      $message       "Not yet sent" message.
+			 * @param object|null $signup_object Signup object instance.
+			 */
+			$message = apply_filters( 'bp_members_signup_date_sent_unsent_message', $message, $signup_object );
+
+			echo esc_html( $message );
+		}
 	}
 
 	/**
-	 * Display number of time an activation email has been sent.
+	 * Display number of times an activation email has been sent.
 	 *
 	 * @since 2.0.0
 	 *
diff --git src/bp-members/classes/class-bp-members-ms-list-table.php src/bp-members/classes/class-bp-members-ms-list-table.php
index b8e86f906..27015f220 100644
--- src/bp-members/classes/class-bp-members-ms-list-table.php
+++ src/bp-members/classes/class-bp-members-ms-list-table.php
@@ -26,6 +26,15 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 	 */
 	public $signup_counts = 0;
 
+	/**
+	 * Signup profile fields.
+	 *
+	 * @since 10.0.0
+	 *
+	 * @var array
+	 */
+	public $signup_field_labels = array();
+
 	/**
 	 * Constructor.
 	 *
@@ -114,6 +123,11 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 
 		// Reset the screen id.
 		$this->screen->id = $reset_screen_id;
+
+		// Use thickbox to display the extended profile information.
+		if ( bp_is_active( 'xprofile' ) ) {
+			add_thickbox();
+		}
 	}
 
 	/**
@@ -125,14 +139,7 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 	 */
 	public function get_columns() {
 
-		/**
-		 * Filters the multisite Members signup columns.
-		 *
-		 * @since 2.0.0
-		 *
-		 * @param array $value Array of columns to display.
-		 */
-		return apply_filters( 'bp_members_ms_signup_columns', array(
+		$columns = array(
 			'cb'         => '<input type="checkbox" />',
 			'username'   => __( 'Username',    'buddypress' ),
 			'name'       => __( 'Name',        'buddypress' ),
@@ -140,7 +147,16 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 			'registered' => __( 'Registered',  'buddypress' ),
 			'date_sent'  => __( 'Last Sent',   'buddypress' ),
 			'count_sent' => __( 'Emails Sent', 'buddypress' )
-		) );
+		);
+
+		/**
+		 * Filters the multisite Members signup columns.
+		 *
+		 * @since 2.0.0
+		 *
+		 * @param array $value Array of columns to display.
+		 */
+		return apply_filters( 'bp_members_ms_signup_columns', $columns );
 	}
 
 	/**
@@ -158,7 +174,14 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 			$actions['delete'] = __( 'Delete', 'buddypress' );
 		}
 
-		return $actions;
+		/**
+		 * Filters the bulk actions for signups.
+		 *
+		 * @since 10.0.0
+		 *
+		 * @param array $actions Array of actions and corresponding labels.
+		 */
+		return apply_filters( 'bp_members_ms_signup_bulk_actions', $actions );
 	}
 
 	/**
@@ -169,7 +192,7 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 	 * @since 2.0.0
 	 */
 	public function no_items() {
-		if ( bp_get_signup_allowed() ) {
+		if ( bp_get_signup_allowed() || bp_get_membership_requests_required() ) {
 			esc_html_e( 'No pending accounts found.', 'buddypress' );
 		} else {
 			$link = false;
@@ -328,6 +351,31 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 	 */
 	public function column_name( $signup_object = null ) {
 		echo esc_html( $signup_object->user_name );
+
+		// Insert the extended profile modal content required by thickbox.
+		if ( ! bp_is_active( 'xprofile' ) ) {
+			return;
+		}
+
+		$profile_field_ids = array();
+
+		// Fetch registration field data once only.
+		if ( ! $this->signup_field_labels ) {
+			$field_groups = bp_xprofile_get_groups(
+				array(
+					'fetch_fields'       => true,
+					'signup_fields_only' => true,
+				)
+			);
+
+			foreach( $field_groups as $field_group ) {
+				foreach( $field_group->fields as $field ) {
+					$this->signup_field_labels[ $field->id ] = $field->name;
+				}
+			}
+		}
+
+		bp_members_admin_preview_signup_profile_info( $this->signup_field_labels, $signup_object );
 	}
 
 	/**
@@ -376,7 +424,24 @@ class BP_Members_MS_List_Table extends WP_MS_Users_List_Table {
 			$date = 'Y/m/d \<\b\r \/\> g:i:s a';
 		}
 
-		echo mysql2date( $date, $signup_object->date_sent );
+		if ( $signup_object->count_sent > 0 ) {
+			echo mysql2date( $date, $signup_object->date_sent );
+		} else {
+			$message = __( 'Not yet notified', 'buddypress' );
+
+			/**
+			 * Filters the "not yet sent" message for "Last Sent"
+			 * column in Manage Signups list table.
+			 *
+			 * @since 10.0.0
+			 *
+			 * @param string      $message       "Not yet sent" message.
+			 * @param object|null $signup_object Signup object instance.
+			 */
+			$message = apply_filters( 'bp_members_ms_signup_date_sent_unsent_message', $message, $signup_object );
+
+			echo esc_html( $message );
+		}
 	}
 
 	/**
diff --git src/bp-members/classes/class-bp-registration-theme-compat.php src/bp-members/classes/class-bp-registration-theme-compat.php
index 6a942a58b..f4e3e6855 100644
--- src/bp-members/classes/class-bp-registration-theme-compat.php
+++ src/bp-members/classes/class-bp-registration-theme-compat.php
@@ -97,10 +97,18 @@ class BP_Registration_Theme_Compat {
 	public function dummy_post() {
 		// Registration page.
 		if ( bp_is_register_page() ) {
-			$title = __( 'Create an Account', 'buddypress' );
+			if ( bp_get_membership_requests_required() ) {
+				$title = __( 'Request Membership', 'buddypress' );
+			} else {
+				$title = __( 'Create an Account', 'buddypress' );
+			}
 
 			if ( 'completed-confirmation' == bp_get_current_signup_step() ) {
-				$title = __( 'Check Your Email To Activate Your Account!', 'buddypress' );
+				if ( bp_get_membership_requests_required() ) {
+					$title = __( 'Your Membership Request has been submitted.', 'buddypress' );
+				} else {
+					$title = __( 'Check Your Email To Activate Your Account!', 'buddypress' );
+				}
 			}
 
 		// Activation page.
diff --git src/bp-members/classes/class-bp-signup.php src/bp-members/classes/class-bp-signup.php
index 9de2af9fe..76b2022d0 100644
--- src/bp-members/classes/class-bp-signup.php
+++ src/bp-members/classes/class-bp-signup.php
@@ -214,6 +214,17 @@ class BP_Signup {
 			$this->date_sent = $signup->registered;
 		}
 
+		// How many times has the activation email been sent?
+		if ( isset( $this->meta['count_sent'] ) ) {
+			$this->count_sent = absint( $this->meta['count_sent'] );
+		} else {
+			/**
+			 * Meta will not be set if this is a pre-10.0 signup.
+			 * In this case, we assume that the count is 1.
+			 */
+			$this->count_sent = 1;
+		}
+
 		/**
 		 * Calculate a diff between now & last time
 		 * an activation link has been resent.
@@ -226,14 +237,8 @@ class BP_Signup {
 		 * Set a boolean to track whether an activation link
 		 * was sent in the last day.
 		 */
-		$this->recently_sent = ( $diff < 1 * DAY_IN_SECONDS );
+		$this->recently_sent = $this->count_sent && ( $diff < 1 * DAY_IN_SECONDS );
 
-		// How many times has the activation email been sent?
-		if ( isset( $this->meta['count_sent'] ) ) {
-			$this->count_sent = absint( $this->meta['count_sent'] );
-		} else {
-			$this->count_sent = 0;
-		}
 	}
 
 	/** Static Methods *******************************************************/
diff --git src/bp-members/screens/register.php src/bp-members/screens/register.php
index 77929c442..2f3f1da1b 100644
--- src/bp-members/screens/register.php
+++ src/bp-members/screens/register.php
@@ -61,7 +61,9 @@ function bp_core_screen_signup() {
 		}
 	}
 
-	if ( ! bp_get_signup_allowed() && ! $active_invite ) {
+	$requests_enabled = bp_get_membership_requests_required();
+
+	if ( ! bp_get_signup_allowed() && ! $active_invite && ! $requests_enabled ) {
 		$bp->signup->step = 'registration-disabled';
 		// If the signup page is submitted, validate and save.
 	} elseif ( isset( $_POST['signup_submit'] ) && bp_verify_nonce_request( 'bp_new_signup' ) ) {
@@ -197,7 +199,7 @@ function bp_core_screen_signup() {
 			// No errors! Let's register those deets.
 			$active_signup = bp_core_get_root_option( 'registration' );
 
-			if ( 'none' != $active_signup ) {
+			if ( 'none' != $active_signup || $requests_enabled ) {
 
 				// Make sure the extended profiles module is enabled.
 				if ( bp_is_active( 'xprofile' ) ) {
diff --git src/bp-templates/bp-legacy/buddypress/members/register.php src/bp-templates/bp-legacy/buddypress/members/register.php
index d263470f2..dd6365b45 100644
--- src/bp-templates/bp-legacy/buddypress/members/register.php
+++ src/bp-templates/bp-legacy/buddypress/members/register.php
@@ -351,10 +351,17 @@
 			 *
 			 * @since 1.1.0
 			 */
-			do_action( 'bp_before_registration_submit_buttons' ); ?>
+			do_action( 'bp_before_registration_submit_buttons' );
+
+			if ( bp_get_membership_requests_required() ) {
+				$button_text = __( 'Submit Request', 'buddypress' );
+			} else {
+				$button_text = __( 'Complete Sign Up', 'buddypress' );
+			}
+			?>
 
 			<div class="submit">
-				<input type="submit" name="signup_submit" id="signup_submit" value="<?php esc_attr_e( 'Complete Sign Up', 'buddypress' ); ?>" />
+				<input type="submit" name="signup_submit" id="signup_submit" value="<?php echo esc_attr( $button_text ); ?>" />
 			</div>
 
 			<?php
@@ -390,7 +397,9 @@
 			do_action( 'bp_before_registration_confirmed' ); ?>
 
 			<div id="template-notices" role="alert" aria-atomic="true">
-				<?php if ( bp_registration_needs_activation() ) : ?>
+				<?php if ( bp_get_membership_requests_required() ) : ?>
+					<p><?php _e( 'You have successfully submitted your membership request! Our site moderators will review your submission and send you an activation email if your request is approved.', 'buddypress' ); ?></p>
+				<?php elseif ( bp_registration_needs_activation() ) : ?>
 					<p><?php _e( 'You have successfully created your account! To begin using this site you will need to activate your account via the email we have just sent to your address.', 'buddypress' ); ?></p>
 				<?php else : ?>
 					<p><?php _e( 'You have successfully created your account! Please log in using the username and password you have just created.', 'buddypress' ); ?></p>
diff --git src/bp-templates/bp-nouveau/includes/functions.php src/bp-templates/bp-nouveau/includes/functions.php
index 8f36ac097..3e6bb22b1 100644
--- src/bp-templates/bp-nouveau/includes/functions.php
+++ src/bp-templates/bp-nouveau/includes/functions.php
@@ -1122,7 +1122,9 @@ function bp_nouveau_get_user_feedback( $feedback_id = '' ) {
 	/*
 	 * Adjust some messages to the context.
 	 */
-	if ( 'completed-confirmation' === $feedback_id && bp_registration_needs_activation() ) {
+	if ( 'completed-confirmation' === $feedback_id && bp_get_membership_requests_required() ) {
+		$feedback_messages['completed-confirmation']['message'] = __( 'You have successfully submitted your membership request! Our site moderators will review your submission and send you an activation email if your request is approved.', 'buddypress' );
+	} elseif ( 'completed-confirmation' === $feedback_id && bp_registration_needs_activation() ) {
 		$feedback_messages['completed-confirmation']['message'] = __( 'You have successfully created your account! To begin using this site you will need to activate your account via the email we have just sent to your address.', 'buddypress' );
 	} elseif ( 'member-notifications-none' === $feedback_id ) {
 		$is_myprofile = bp_is_my_profile();
diff --git src/class-buddypress.php src/class-buddypress.php
index 981ae06a1..41be07434 100644
--- src/class-buddypress.php
+++ src/class-buddypress.php
@@ -350,7 +350,7 @@ class BuddyPress {
 		/** Versions */
 
 		$this->version    = '10.0.0-alpha';
-		$this->db_version = 12850;
+		$this->db_version = 13150;
 
 		/** Loading */
 
