diff -r 7b1b88e27a20 -r 48c4eec2b7e6 wp/wp-includes/class-wp-locale-switcher.php --- a/wp/wp-includes/class-wp-locale-switcher.php Thu Sep 29 08:06:27 2022 +0200 +++ b/wp/wp-includes/class-wp-locale-switcher.php Fri Sep 05 18:40:08 2025 +0200 @@ -12,14 +12,15 @@ * * @since 4.7.0 */ +#[AllowDynamicProperties] class WP_Locale_Switcher { /** - * Locale stack. + * Locale switching stack. * - * @since 4.7.0 - * @var string[] + * @since 6.2.0 + * @var array */ - private $locales = array(); + private $stack = array(); /** * Original locale. @@ -33,9 +34,9 @@ * Holds all available languages. * * @since 4.7.0 - * @var array An array of language codes (file names without the .mo extension). + * @var string[] An array of language codes (file names without the .mo extension). */ - private $available_languages = array(); + private $available_languages; /** * Constructor. @@ -52,12 +53,14 @@ /** * Initializes the locale switcher. * - * Hooks into the {@see 'locale'} filter to change the locale on the fly. + * Hooks into the {@see 'locale'} and {@see 'determine_locale'} filters + * to change the locale on the fly. * * @since 4.7.0 */ public function init() { add_filter( 'locale', array( $this, 'filter_locale' ) ); + add_filter( 'determine_locale', array( $this, 'filter_locale' ) ); } /** @@ -65,10 +68,11 @@ * * @since 4.7.0 * - * @param string $locale The locale to switch to. + * @param string $locale The locale to switch to. + * @param int|false $user_id Optional. User ID as context. Default false. * @return bool True on success, false on failure. */ - public function switch_to_locale( $locale ) { + public function switch_to_locale( $locale, $user_id = false ) { $current_locale = determine_locale(); if ( $current_locale === $locale ) { return false; @@ -78,7 +82,7 @@ return false; } - $this->locales[] = $locale; + $this->stack[] = array( $locale, $user_id ); $this->change_locale( $locale ); @@ -86,15 +90,30 @@ * Fires when the locale is switched. * * @since 4.7.0 + * @since 6.2.0 The `$user_id` parameter was added. * - * @param string $locale The new locale. + * @param string $locale The new locale. + * @param false|int $user_id User ID for context if available. */ - do_action( 'switch_locale', $locale ); + do_action( 'switch_locale', $locale, $user_id ); return true; } /** + * Switches the translations according to the given user's locale. + * + * @since 6.2.0 + * + * @param int $user_id User ID. + * @return bool True on success, false on failure. + */ + public function switch_to_user_locale( $user_id ) { + $locale = get_user_locale( $user_id ); + return $this->switch_to_locale( $locale, $user_id ); + } + + /** * Restores the translations according to the previous locale. * * @since 4.7.0 @@ -102,14 +121,15 @@ * @return string|false Locale on success, false on failure. */ public function restore_previous_locale() { - $previous_locale = array_pop( $this->locales ); + $previous_locale = array_pop( $this->stack ); if ( null === $previous_locale ) { // The stack is empty, bail. return false; } - $locale = end( $this->locales ); + $entry = end( $this->stack ); + $locale = is_array( $entry ) ? $entry[0] : false; if ( ! $locale ) { // There's nothing left in the stack: go back to the original locale. @@ -126,7 +146,7 @@ * @param string $locale The new locale. * @param string $previous_locale The previous locale. */ - do_action( 'restore_previous_locale', $locale, $previous_locale ); + do_action( 'restore_previous_locale', $locale, $previous_locale[0] ); return $locale; } @@ -139,11 +159,11 @@ * @return string|false Locale on success, false on failure. */ public function restore_current_locale() { - if ( empty( $this->locales ) ) { + if ( empty( $this->stack ) ) { return false; } - $this->locales = array( $this->original_locale ); + $this->stack = array( array( $this->original_locale, false ) ); return $this->restore_previous_locale(); } @@ -156,7 +176,41 @@ * @return bool True if the locale has been switched, false otherwise. */ public function is_switched() { - return ! empty( $this->locales ); + return ! empty( $this->stack ); + } + + /** + * Returns the locale currently switched to. + * + * @since 6.2.0 + * + * @return string|false Locale if the locale has been switched, false otherwise. + */ + public function get_switched_locale() { + $entry = end( $this->stack ); + + if ( $entry ) { + return $entry[0]; + } + + return false; + } + + /** + * Returns the user ID related to the currently switched locale. + * + * @since 6.2.0 + * + * @return int|false User ID if set and if the locale has been switched, false otherwise. + */ + public function get_switched_user_id() { + $entry = end( $this->stack ); + + if ( $entry ) { + return $entry[1]; + } + + return false; } /** @@ -168,7 +222,7 @@ * @return string The locale currently being switched to. */ public function filter_locale( $locale ) { - $switched_locale = end( $this->locales ); + $switched_locale = $this->get_switched_locale(); if ( $switched_locale ) { return $switched_locale; @@ -196,11 +250,16 @@ load_default_textdomain( $locale ); foreach ( $domains as $domain ) { + // The default text domain is handled by `load_default_textdomain()`. if ( 'default' === $domain ) { continue; } - unload_textdomain( $domain ); + /* + * Unload current text domain but allow them to be reloaded + * after switching back or to another locale. + */ + unload_textdomain( $domain, true ); get_translations_for_domain( $domain ); } } @@ -218,12 +277,13 @@ * @param string $locale The locale to change to. */ private function change_locale( $locale ) { - // Reset translation availability information. - _get_path_to_translation( null, true ); + global $wp_locale; $this->load_translations( $locale ); - $GLOBALS['wp_locale'] = new WP_Locale(); + $wp_locale = new WP_Locale(); + + WP_Translation_Controller::get_instance()->set_locale( $locale ); /** * Fires when the locale is switched to or restored.