diff --git a/wp-includes/class-walker-nav-menu.php b/wp-includes/class-walker-nav-menu.php
index 37147e48ce..2b06d54b44 100644
--- a/wp-includes/class-walker-nav-menu.php
+++ b/wp-includes/class-walker-nav-menu.php
@@ -126,6 +126,7 @@ class Walker_Nav_Menu extends Walker {
* @since 4.4.0 The {@see 'nav_menu_item_args'} filter was added.
* @since 5.9.0 Renamed `$item` to `$data_object` and `$id` to `$current_object_id`
* to match parent class for PHP 8 named parameter support.
+ * @since 6.7.0 Removed redundant title attributes.
*
* @see Walker::start_el()
*
@@ -212,8 +213,25 @@ class Walker_Nav_Menu extends Walker {
$output .= $indent . '
';
+ /** This filter is documented in wp-includes/post-template.php */
+ $title = apply_filters( 'the_title', $menu_item->title, $menu_item->ID );
+
+ // Save filtered value before filtering again.
+ $the_title_filtered = $title;
+
+ /**
+ * Filters a menu item's title.
+ *
+ * @since 4.4.0
+ *
+ * @param string $title The menu item's title.
+ * @param WP_Post $menu_item The current menu item object.
+ * @param stdClass $args An object of wp_nav_menu() arguments.
+ * @param int $depth Depth of menu item. Used for padding.
+ */
+ $title = apply_filters( 'nav_menu_item_title', $title, $menu_item, $args, $depth );
+
$atts = array();
- $atts['title'] = ! empty( $menu_item->attr_title ) ? $menu_item->attr_title : '';
$atts['target'] = ! empty( $menu_item->target ) ? $menu_item->target : '';
$atts['rel'] = ! empty( $menu_item->xfn ) ? $menu_item->xfn : '';
@@ -229,6 +247,17 @@ class Walker_Nav_Menu extends Walker {
$atts['aria-current'] = $menu_item->current ? 'page' : '';
+ // Add title attribute only if it does not match the link text (before or after filtering).
+ if ( ! empty( $menu_item->attr_title )
+ && trim( strtolower( $menu_item->attr_title ) ) !== trim( strtolower( $menu_item->title ) )
+ && trim( strtolower( $menu_item->attr_title ) ) !== trim( strtolower( $the_title_filtered ) )
+ && trim( strtolower( $menu_item->attr_title ) ) !== trim( strtolower( $title ) )
+ ) {
+ $atts['title'] = $menu_item->attr_title;
+ } else {
+ $atts['title'] = '';
+ }
+
/**
* Filters the HTML attributes applied to a menu item's anchor element.
*
@@ -251,21 +280,6 @@ class Walker_Nav_Menu extends Walker {
$atts = apply_filters( 'nav_menu_link_attributes', $atts, $menu_item, $args, $depth );
$attributes = $this->build_atts( $atts );
- /** This filter is documented in wp-includes/post-template.php */
- $title = apply_filters( 'the_title', $menu_item->title, $menu_item->ID );
-
- /**
- * Filters a menu item's title.
- *
- * @since 4.4.0
- *
- * @param string $title The menu item's title.
- * @param WP_Post $menu_item The current menu item object.
- * @param stdClass $args An object of wp_nav_menu() arguments.
- * @param int $depth Depth of menu item. Used for padding.
- */
- $title = apply_filters( 'nav_menu_item_title', $title, $menu_item, $args, $depth );
-
$item_output = $args->before;
$item_output .= '';
$item_output .= $args->link_before . $title . $args->link_after;
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 5bd1efe87c..7eb4c0009b 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '6.7-beta1-59178';
+$wp_version = '6.7-beta1-59179';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.