languages = $languages; $this->mapping = $mapping; $this->router = $router; } /** * Register hooks. * * @return void */ public function init() { add_action( 'wp_head', array( $this, 'output_hreflang' ), 2 ); add_action( 'wp_head', array( $this, 'output_canonical' ), 3 ); add_filter( 'wp_sitemaps_posts_query_args', array( $this, 'sitemap_query_args' ), 10, 2 ); } /** * Output hreflang alternates. * * @return void */ public function output_hreflang() { if ( is_admin() || ! is_singular() ) { return; } $post_id = get_queried_object_id(); $root_id = $this->mapping->get_root_id( $post_id ); $all = $this->languages->get_all(); $default = $this->languages->get_default_code(); $has_self = false; foreach ( $all as $code => $language ) { $url = ''; if ( $code === $default ) { $url = get_permalink( $root_id ); } else { $translation_id = $this->mapping->get_ready_translation_id( $root_id, $code ); if ( $translation_id ) { $url = get_permalink( $translation_id ); } } if ( ! $url ) { continue; } $has_self = true; printf( '' . "\n", esc_attr( str_replace( '_', '-', $code ) ), esc_url( $url ) ); } if ( $has_self ) { printf( '' . "\n", esc_url( get_permalink( $root_id ) ) ); } } /** * Output canonical for translated pages. * * @return void */ public function output_canonical() { if ( is_admin() || ! is_singular() ) { return; } $post_id = get_queried_object_id(); if ( ! $post_id ) { return; } printf( '' . "\n", esc_url( get_permalink( $post_id ) ) ); } /** * Keep default sitemap from listing translation drafts/private content. * * Published translations remain in the normal sitemap with their prefixed URLs * because permalink filters are applied by core sitemap generation. * * @param array $args Query args. * @param string $post_type Post type. * @return array */ public function sitemap_query_args( $args, $post_type ) { if ( ! in_array( $post_type, array( 'page', 'post', 'product' ), true ) ) { return $args; } $args['post_status'] = array( 'publish' ); return $args; } }