WP_Locale_Switcher
云策文档标注
概述
WP_Locale_Switcher 是 WordPress 核心类,用于动态切换站点区域设置(locale),支持多语言翻译管理。它通过堆栈机制管理区域设置切换,并集成到 'locale' 和 'determine_locale' 过滤器。
关键要点
- 核心功能:提供 switch_to_locale()、restore_previous_locale() 等方法,实现区域设置的切换、恢复和查询。
- 堆栈管理:使用私有属性 $stack 跟踪切换历史,支持嵌套切换和恢复操作。
- Hook 集成:通过 init() 方法挂载到 'locale' 和 'determine_locale' 过滤器,自动应用区域设置变更。
- 翻译加载:私有方法 load_translations() 和 change_locale() 负责加载翻译并更新全局对象如 $wp_locale。
- 用户上下文:支持基于用户 ID 的区域设置切换,如 switch_to_user_locale() 和 get_switched_user_id()。
代码示例
// 示例:切换区域设置并恢复
$locale_switcher = new WP_Locale_Switcher();
$locale_switcher->init();
// 切换到法语
$locale_switcher->switch_to_locale('fr_FR');
// 检查当前切换状态
if ($locale_switcher->is_switched()) {
echo '当前区域设置:' . $locale_switcher->get_switched_locale();
}
// 恢复到上一个区域设置
$locale_switcher->restore_previous_locale();注意事项
- 区域设置切换仅影响翻译和本地化对象,不修改数据库或站点设置。
- 使用前需确保目标区域设置在 $available_languages 列表中,否则切换可能失败。
- 私有方法如 change_locale() 和 load_translations() 不应直接调用,应通过公共方法操作。
- 切换操作会触发相关 Hook,如 'switch_locale' 和 'change_locale',便于扩展功能。
原文内容
Core class used for switching locales.
Methods
| Name | Description |
|---|---|
| WP_Locale_Switcher::__construct | Constructor. |
| WP_Locale_Switcher::change_locale | Changes the site’s locale to the given one. |
| WP_Locale_Switcher::filter_locale | Filters the locale of the WordPress installation. |
| WP_Locale_Switcher::get_switched_locale | Returns the locale currently switched to. |
| WP_Locale_Switcher::get_switched_user_id | Returns the user ID related to the currently switched locale. |
| WP_Locale_Switcher::init | Initializes the locale switcher. |
| WP_Locale_Switcher::is_switched | Whether switch_to_locale() is in effect. |
| WP_Locale_Switcher::load_translations | Load translations for a given locale. |
| WP_Locale_Switcher::restore_current_locale | Restores the translations according to the original locale. |
| WP_Locale_Switcher::restore_previous_locale | Restores the translations according to the previous locale. |
| WP_Locale_Switcher::switch_to_locale | Switches the translations according to the given locale. |
| WP_Locale_Switcher::switch_to_user_locale | Switches the translations according to the given user’s locale. |
Source
class WP_Locale_Switcher {
/**
* Locale switching stack.
*
* @since 6.2.0
* @var array
*/
private $stack = array();
/**
* Original locale.
*
* @since 4.7.0
* @var string
*/
private $original_locale;
/**
* Holds all available languages.
*
* @since 4.7.0
* @var string[] An array of language codes (file names without the .mo extension).
*/
private $available_languages;
/**
* Constructor.
*
* Stores the original locale as well as a list of all available languages.
*
* @since 4.7.0
*/
public function __construct() {
$this->original_locale = determine_locale();
$this->available_languages = array_merge( array( 'en_US' ), get_available_languages() );
}
/**
* Initializes the locale switcher.
*
* Hooks into the 'locale' and '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' ) );
}
/**
* Switches the translations according to the given locale.
*
* @since 4.7.0
*
* @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, $user_id = false ) {
$current_locale = determine_locale();
if ( $current_locale === $locale ) {
return false;
}
if ( ! in_array( $locale, $this->available_languages, true ) ) {
return false;
}
$this->stack[] = array( $locale, $user_id );
$this->change_locale( $locale );
/**
* 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 false|int $user_id User ID for context if available.
*/
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
*
* @return string|false Locale on success, false on failure.
*/
public function restore_previous_locale() {
$previous_locale = array_pop( $this->stack );
if ( null === $previous_locale ) {
// The stack is empty, bail.
return false;
}
$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.
$locale = $this->original_locale;
}
$this->change_locale( $locale );
/**
* Fires when the locale is restored to the previous one.
*
* @since 4.7.0
*
* @param string $locale The new locale.
* @param string $previous_locale The previous locale.
*/
do_action( 'restore_previous_locale', $locale, $previous_locale[0] );
return $locale;
}
/**
* Restores the translations according to the original locale.
*
* @since 4.7.0
*
* @return string|false Locale on success, false on failure.
*/
public function restore_current_locale() {
if ( empty( $this->stack ) ) {
return false;
}
$this->stack = array( array( $this->original_locale, false ) );
return $this->restore_previous_locale();
}
/**
* Whether switch_to_locale() is in effect.
*
* @since 4.7.0
*
* @return bool True if the locale has been switched, false otherwise.
*/
public function is_switched() {
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;
}
/**
* Filters the locale of the WordPress installation.
*
* @since 4.7.0
*
* @param string $locale The locale of the WordPress installation.
* @return string The locale currently being switched to.
*/
public function filter_locale( $locale ) {
$switched_locale = $this->get_switched_locale();
if ( $switched_locale ) {
return $switched_locale;
}
return $locale;
}
/**
* Load translations for a given locale.
*
* When switching to a locale, translations for this locale must be loaded from scratch.
*
* @since 4.7.0
*
* @global Mo[] $l10n An array of all currently loaded text domains.
*
* @param string $locale The locale to load translations for.
*/
private function load_translations( $locale ) {
global $l10n;
$domains = $l10n ? array_keys( $l10n ) : array();
load_default_textdomain( $locale );
foreach ( $domains as $domain ) {
// The default text domain is handled by `load_default_textdomain()`.
if ( 'default' === $domain ) {
continue;
}
/*
* 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 );
}
}
/**
* Changes the site's locale to the given one.
*
* Loads the translations, changes the global `$wp_locale` object and updates
* all post type labels.
*
* @since 4.7.0
*
* @global WP_Locale $wp_locale WordPress date and time locale object.
* @global PHPMailerPHPMailerPHPMailer $phpmailer
*
* @param string $locale The locale to change to.
*/
private function change_locale( $locale ) {
global $wp_locale, $phpmailer;
$this->load_translations( $locale );
$wp_locale = new WP_Locale();
WP_Translation_Controller::get_instance()->set_locale( $locale );
if ( $phpmailer instanceof WP_PHPMailer ) {
$phpmailer->setLanguage();
}
/**
* Fires when the locale is switched to or restored.
*
* @since 4.7.0
*
* @param string $locale The new locale.
*/
do_action( 'change_locale', $locale );
}
}
Changelog
| Version | Description |
|---|---|
| 4.7.0 | Introduced. |