wp/wp-includes/class-wp-locale-switcher.php
changeset 21 48c4eec2b7e6
parent 16 a86126ab1dd4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    10 /**
    10 /**
    11  * Core class used for switching locales.
    11  * Core class used for switching locales.
    12  *
    12  *
    13  * @since 4.7.0
    13  * @since 4.7.0
    14  */
    14  */
       
    15 #[AllowDynamicProperties]
    15 class WP_Locale_Switcher {
    16 class WP_Locale_Switcher {
    16 	/**
    17 	/**
    17 	 * Locale stack.
    18 	 * Locale switching stack.
    18 	 *
    19 	 *
    19 	 * @since 4.7.0
    20 	 * @since 6.2.0
    20 	 * @var string[]
    21 	 * @var array
    21 	 */
    22 	 */
    22 	private $locales = array();
    23 	private $stack = array();
    23 
    24 
    24 	/**
    25 	/**
    25 	 * Original locale.
    26 	 * Original locale.
    26 	 *
    27 	 *
    27 	 * @since 4.7.0
    28 	 * @since 4.7.0
    31 
    32 
    32 	/**
    33 	/**
    33 	 * Holds all available languages.
    34 	 * Holds all available languages.
    34 	 *
    35 	 *
    35 	 * @since 4.7.0
    36 	 * @since 4.7.0
    36 	 * @var array An array of language codes (file names without the .mo extension).
    37 	 * @var string[] An array of language codes (file names without the .mo extension).
    37 	 */
    38 	 */
    38 	private $available_languages = array();
    39 	private $available_languages;
    39 
    40 
    40 	/**
    41 	/**
    41 	 * Constructor.
    42 	 * Constructor.
    42 	 *
    43 	 *
    43 	 * Stores the original locale as well as a list of all available languages.
    44 	 * Stores the original locale as well as a list of all available languages.
    50 	}
    51 	}
    51 
    52 
    52 	/**
    53 	/**
    53 	 * Initializes the locale switcher.
    54 	 * Initializes the locale switcher.
    54 	 *
    55 	 *
    55 	 * Hooks into the {@see 'locale'} filter to change the locale on the fly.
    56 	 * Hooks into the {@see 'locale'} and {@see 'determine_locale'} filters
       
    57 	 * to change the locale on the fly.
    56 	 *
    58 	 *
    57 	 * @since 4.7.0
    59 	 * @since 4.7.0
    58 	 */
    60 	 */
    59 	public function init() {
    61 	public function init() {
    60 		add_filter( 'locale', array( $this, 'filter_locale' ) );
    62 		add_filter( 'locale', array( $this, 'filter_locale' ) );
       
    63 		add_filter( 'determine_locale', array( $this, 'filter_locale' ) );
    61 	}
    64 	}
    62 
    65 
    63 	/**
    66 	/**
    64 	 * Switches the translations according to the given locale.
    67 	 * Switches the translations according to the given locale.
    65 	 *
    68 	 *
    66 	 * @since 4.7.0
    69 	 * @since 4.7.0
    67 	 *
    70 	 *
    68 	 * @param string $locale The locale to switch to.
    71 	 * @param string    $locale  The locale to switch to.
       
    72 	 * @param int|false $user_id Optional. User ID as context. Default false.
    69 	 * @return bool True on success, false on failure.
    73 	 * @return bool True on success, false on failure.
    70 	 */
    74 	 */
    71 	public function switch_to_locale( $locale ) {
    75 	public function switch_to_locale( $locale, $user_id = false ) {
    72 		$current_locale = determine_locale();
    76 		$current_locale = determine_locale();
    73 		if ( $current_locale === $locale ) {
    77 		if ( $current_locale === $locale ) {
    74 			return false;
    78 			return false;
    75 		}
    79 		}
    76 
    80 
    77 		if ( ! in_array( $locale, $this->available_languages, true ) ) {
    81 		if ( ! in_array( $locale, $this->available_languages, true ) ) {
    78 			return false;
    82 			return false;
    79 		}
    83 		}
    80 
    84 
    81 		$this->locales[] = $locale;
    85 		$this->stack[] = array( $locale, $user_id );
    82 
    86 
    83 		$this->change_locale( $locale );
    87 		$this->change_locale( $locale );
    84 
    88 
    85 		/**
    89 		/**
    86 		 * Fires when the locale is switched.
    90 		 * Fires when the locale is switched.
    87 		 *
    91 		 *
    88 		 * @since 4.7.0
    92 		 * @since 4.7.0
    89 		 *
    93 		 * @since 6.2.0 The `$user_id` parameter was added.
    90 		 * @param string $locale The new locale.
    94 		 *
       
    95 		 * @param string    $locale  The new locale.
       
    96 		 * @param false|int $user_id User ID for context if available.
    91 		 */
    97 		 */
    92 		do_action( 'switch_locale', $locale );
    98 		do_action( 'switch_locale', $locale, $user_id );
    93 
    99 
    94 		return true;
   100 		return true;
    95 	}
   101 	}
    96 
   102 
    97 	/**
   103 	/**
       
   104 	 * Switches the translations according to the given user's locale.
       
   105 	 *
       
   106 	 * @since 6.2.0
       
   107 	 *
       
   108 	 * @param int $user_id User ID.
       
   109 	 * @return bool True on success, false on failure.
       
   110 	 */
       
   111 	public function switch_to_user_locale( $user_id ) {
       
   112 		$locale = get_user_locale( $user_id );
       
   113 		return $this->switch_to_locale( $locale, $user_id );
       
   114 	}
       
   115 
       
   116 	/**
    98 	 * Restores the translations according to the previous locale.
   117 	 * Restores the translations according to the previous locale.
    99 	 *
   118 	 *
   100 	 * @since 4.7.0
   119 	 * @since 4.7.0
   101 	 *
   120 	 *
   102 	 * @return string|false Locale on success, false on failure.
   121 	 * @return string|false Locale on success, false on failure.
   103 	 */
   122 	 */
   104 	public function restore_previous_locale() {
   123 	public function restore_previous_locale() {
   105 		$previous_locale = array_pop( $this->locales );
   124 		$previous_locale = array_pop( $this->stack );
   106 
   125 
   107 		if ( null === $previous_locale ) {
   126 		if ( null === $previous_locale ) {
   108 			// The stack is empty, bail.
   127 			// The stack is empty, bail.
   109 			return false;
   128 			return false;
   110 		}
   129 		}
   111 
   130 
   112 		$locale = end( $this->locales );
   131 		$entry  = end( $this->stack );
       
   132 		$locale = is_array( $entry ) ? $entry[0] : false;
   113 
   133 
   114 		if ( ! $locale ) {
   134 		if ( ! $locale ) {
   115 			// There's nothing left in the stack: go back to the original locale.
   135 			// There's nothing left in the stack: go back to the original locale.
   116 			$locale = $this->original_locale;
   136 			$locale = $this->original_locale;
   117 		}
   137 		}
   124 		 * @since 4.7.0
   144 		 * @since 4.7.0
   125 		 *
   145 		 *
   126 		 * @param string $locale          The new locale.
   146 		 * @param string $locale          The new locale.
   127 		 * @param string $previous_locale The previous locale.
   147 		 * @param string $previous_locale The previous locale.
   128 		 */
   148 		 */
   129 		do_action( 'restore_previous_locale', $locale, $previous_locale );
   149 		do_action( 'restore_previous_locale', $locale, $previous_locale[0] );
   130 
   150 
   131 		return $locale;
   151 		return $locale;
   132 	}
   152 	}
   133 
   153 
   134 	/**
   154 	/**
   137 	 * @since 4.7.0
   157 	 * @since 4.7.0
   138 	 *
   158 	 *
   139 	 * @return string|false Locale on success, false on failure.
   159 	 * @return string|false Locale on success, false on failure.
   140 	 */
   160 	 */
   141 	public function restore_current_locale() {
   161 	public function restore_current_locale() {
   142 		if ( empty( $this->locales ) ) {
   162 		if ( empty( $this->stack ) ) {
   143 			return false;
   163 			return false;
   144 		}
   164 		}
   145 
   165 
   146 		$this->locales = array( $this->original_locale );
   166 		$this->stack = array( array( $this->original_locale, false ) );
   147 
   167 
   148 		return $this->restore_previous_locale();
   168 		return $this->restore_previous_locale();
   149 	}
   169 	}
   150 
   170 
   151 	/**
   171 	/**
   154 	 * @since 4.7.0
   174 	 * @since 4.7.0
   155 	 *
   175 	 *
   156 	 * @return bool True if the locale has been switched, false otherwise.
   176 	 * @return bool True if the locale has been switched, false otherwise.
   157 	 */
   177 	 */
   158 	public function is_switched() {
   178 	public function is_switched() {
   159 		return ! empty( $this->locales );
   179 		return ! empty( $this->stack );
       
   180 	}
       
   181 
       
   182 	/**
       
   183 	 * Returns the locale currently switched to.
       
   184 	 *
       
   185 	 * @since 6.2.0
       
   186 	 *
       
   187 	 * @return string|false Locale if the locale has been switched, false otherwise.
       
   188 	 */
       
   189 	public function get_switched_locale() {
       
   190 		$entry = end( $this->stack );
       
   191 
       
   192 		if ( $entry ) {
       
   193 			return $entry[0];
       
   194 		}
       
   195 
       
   196 		return false;
       
   197 	}
       
   198 
       
   199 	/**
       
   200 	 * Returns the user ID related to the currently switched locale.
       
   201 	 *
       
   202 	 * @since 6.2.0
       
   203 	 *
       
   204 	 * @return int|false User ID if set and if the locale has been switched, false otherwise.
       
   205 	 */
       
   206 	public function get_switched_user_id() {
       
   207 		$entry = end( $this->stack );
       
   208 
       
   209 		if ( $entry ) {
       
   210 			return $entry[1];
       
   211 		}
       
   212 
       
   213 		return false;
   160 	}
   214 	}
   161 
   215 
   162 	/**
   216 	/**
   163 	 * Filters the locale of the WordPress installation.
   217 	 * Filters the locale of the WordPress installation.
   164 	 *
   218 	 *
   166 	 *
   220 	 *
   167 	 * @param string $locale The locale of the WordPress installation.
   221 	 * @param string $locale The locale of the WordPress installation.
   168 	 * @return string The locale currently being switched to.
   222 	 * @return string The locale currently being switched to.
   169 	 */
   223 	 */
   170 	public function filter_locale( $locale ) {
   224 	public function filter_locale( $locale ) {
   171 		$switched_locale = end( $this->locales );
   225 		$switched_locale = $this->get_switched_locale();
   172 
   226 
   173 		if ( $switched_locale ) {
   227 		if ( $switched_locale ) {
   174 			return $switched_locale;
   228 			return $switched_locale;
   175 		}
   229 		}
   176 
   230 
   194 		$domains = $l10n ? array_keys( $l10n ) : array();
   248 		$domains = $l10n ? array_keys( $l10n ) : array();
   195 
   249 
   196 		load_default_textdomain( $locale );
   250 		load_default_textdomain( $locale );
   197 
   251 
   198 		foreach ( $domains as $domain ) {
   252 		foreach ( $domains as $domain ) {
       
   253 			// The default text domain is handled by `load_default_textdomain()`.
   199 			if ( 'default' === $domain ) {
   254 			if ( 'default' === $domain ) {
   200 				continue;
   255 				continue;
   201 			}
   256 			}
   202 
   257 
   203 			unload_textdomain( $domain );
   258 			/*
       
   259 			 * Unload current text domain but allow them to be reloaded
       
   260 			 * after switching back or to another locale.
       
   261 			 */
       
   262 			unload_textdomain( $domain, true );
   204 			get_translations_for_domain( $domain );
   263 			get_translations_for_domain( $domain );
   205 		}
   264 		}
   206 	}
   265 	}
   207 
   266 
   208 	/**
   267 	/**
   216 	 * @global WP_Locale $wp_locale WordPress date and time locale object.
   275 	 * @global WP_Locale $wp_locale WordPress date and time locale object.
   217 	 *
   276 	 *
   218 	 * @param string $locale The locale to change to.
   277 	 * @param string $locale The locale to change to.
   219 	 */
   278 	 */
   220 	private function change_locale( $locale ) {
   279 	private function change_locale( $locale ) {
   221 		// Reset translation availability information.
   280 		global $wp_locale;
   222 		_get_path_to_translation( null, true );
       
   223 
   281 
   224 		$this->load_translations( $locale );
   282 		$this->load_translations( $locale );
   225 
   283 
   226 		$GLOBALS['wp_locale'] = new WP_Locale();
   284 		$wp_locale = new WP_Locale();
       
   285 
       
   286 		WP_Translation_Controller::get_instance()->set_locale( $locale );
   227 
   287 
   228 		/**
   288 		/**
   229 		 * Fires when the locale is switched to or restored.
   289 		 * Fires when the locale is switched to or restored.
   230 		 *
   290 		 *
   231 		 * @since 4.7.0
   291 		 * @since 4.7.0