its own URL (/uk/); * - the posts page in a language it has no version in (/uk/journal/) -> its URL; * - the default language's prefix in the URL (/en/about/) -> without it (/about/). */ declare( strict_types = 1 ); namespace AddBlack\Lang\Routing; defined( 'ABSPATH' ) || exit; use AddBlack\Lang\Hookable; use AddBlack\Lang\Hooks; use AddBlack\Lang\Settings\SettingsRepository; use AddBlack\Lang\Translation\PostTranslations; use WP_Post; final class Redirects implements Hookable { public function __construct( private readonly CurrentLanguage $current, private readonly Urls $urls, private readonly SettingsRepository $settings, private readonly PostTranslations $posts ) {} public function register(): void { Hooks::action( 'template_redirect', array( $this, 'redirect' ), 2 ); } public function redirect(): void { $target = $this->target(); if ( '' !== $target ) { wp_safe_redirect( $target, 301 ); exit; } } /** Where the current request should go instead, or ''. */ public function target(): string { $lang = $this->current->get(); if ( ! $this->urls->pretty() || is_preview() || is_admin() || is_feed() || is_embed() || '' === $lang ) { return ''; } $settings = $this->settings->get(); // A page or post (also the posts page, e.g. /uk/journal/ when Journal has no UK version). if ( is_singular() || ( is_home() && ! is_front_page() ) ) { $post = get_queried_object(); if ( $post instanceof WP_Post && 'publish' === $post->post_status && $settings->is_translatable_type( $post->post_type ) ) { if ( $this->posts->language_of( $post->ID ) !== $lang ) { return (string) get_permalink( $post ); } } } // Prefix of the default language in the URL: drop it. $prefix_lang = $this->current->prefix_in_url(); if ( '' !== $prefix_lang && $settings->default_code() === $prefix_lang ) { $uri = Urls::request_uri(); $uri = '' !== $uri ? $uri : '/'; return $this->urls->raw_home() . $this->urls->strip_prefix( $uri, (string) $settings->language( $prefix_lang )?->slug ); } return ''; } }