You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

241 lines
5.0 KiB

  1. <?php
  2. /**
  3. * Locale API: WP_Locale_Switcher class
  4. *
  5. * @package WordPress
  6. * @subpackage i18n
  7. * @since 4.7.0
  8. */
  9. /**
  10. * Core class used for switching locales.
  11. *
  12. * @since 4.7.0
  13. */
  14. class WP_Locale_Switcher {
  15. /**
  16. * Locale stack.
  17. *
  18. * @since 4.7.0
  19. * @access private
  20. * @var string[]
  21. */
  22. private $locales = array();
  23. /**
  24. * Original locale.
  25. *
  26. * @since 4.7.0
  27. * @access private
  28. * @var string
  29. */
  30. private $original_locale;
  31. /**
  32. * Holds all available languages.
  33. *
  34. * @since 4.7.0
  35. * @access private
  36. * @var array An array of language codes (file names without the .mo extension).
  37. */
  38. private $available_languages = array();
  39. /**
  40. * Constructor.
  41. *
  42. * Stores the original locale as well as a list of all available languages.
  43. *
  44. * @since 4.7.0
  45. */
  46. public function __construct() {
  47. $this->original_locale = is_admin() ? get_user_locale() : get_locale();
  48. $this->available_languages = array_merge( array( 'en_US' ), get_available_languages() );
  49. }
  50. /**
  51. * Initializes the locale switcher.
  52. *
  53. * Hooks into the {@see 'locale'} filter to change the locale on the fly.
  54. */
  55. public function init() {
  56. add_filter( 'locale', array( $this, 'filter_locale' ) );
  57. }
  58. /**
  59. * Switches the translations according to the given locale.
  60. *
  61. * @since 4.7.0
  62. *
  63. * @param string $locale The locale to switch to.
  64. * @return bool True on success, false on failure.
  65. */
  66. public function switch_to_locale( $locale ) {
  67. $current_locale = is_admin() ? get_user_locale() : get_locale();
  68. if ( $current_locale === $locale ) {
  69. return false;
  70. }
  71. if ( ! in_array( $locale, $this->available_languages, true ) ) {
  72. return false;
  73. }
  74. $this->locales[] = $locale;
  75. $this->change_locale( $locale );
  76. /**
  77. * Fires when the locale is switched.
  78. *
  79. * @since 4.7.0
  80. *
  81. * @param string $locale The new locale.
  82. */
  83. do_action( 'switch_locale', $locale );
  84. return true;
  85. }
  86. /**
  87. * Restores the translations according to the previous locale.
  88. *
  89. * @since 4.7.0
  90. *
  91. * @return string|false Locale on success, false on failure.
  92. */
  93. public function restore_previous_locale() {
  94. $previous_locale = array_pop( $this->locales );
  95. if ( null === $previous_locale ) {
  96. // The stack is empty, bail.
  97. return false;
  98. }
  99. $locale = end( $this->locales );
  100. if ( ! $locale ) {
  101. // There's nothing left in the stack: go back to the original locale.
  102. $locale = $this->original_locale;
  103. }
  104. $this->change_locale( $locale );
  105. /**
  106. * Fires when the locale is restored to the previous one.
  107. *
  108. * @since 4.7.0
  109. *
  110. * @param string $locale The new locale.
  111. * @param string $previous_locale The previous locale.
  112. */
  113. do_action( 'restore_previous_locale', $locale, $previous_locale );
  114. return $locale;
  115. }
  116. /**
  117. * Restores the translations according to the original locale.
  118. *
  119. * @since 4.7.0
  120. *
  121. * @return string|false Locale on success, false on failure.
  122. */
  123. public function restore_current_locale() {
  124. if ( empty( $this->locales ) ) {
  125. return false;
  126. }
  127. $this->locales = array( $this->original_locale );
  128. return $this->restore_previous_locale();
  129. }
  130. /**
  131. * Whether switch_to_locale() is in effect.
  132. *
  133. * @since 4.7.0
  134. *
  135. * @return bool True if the locale has been switched, false otherwise.
  136. */
  137. public function is_switched() {
  138. return ! empty( $this->locales );
  139. }
  140. /**
  141. * Filters the WordPress install's locale.
  142. *
  143. * @since 4.7.0
  144. *
  145. * @param string $locale The WordPress install's locale.
  146. * @return string The locale currently being switched to.
  147. */
  148. public function filter_locale( $locale ) {
  149. $switched_locale = end( $this->locales );
  150. if ( $switched_locale ) {
  151. return $switched_locale;
  152. }
  153. return $locale;
  154. }
  155. /**
  156. * Load translations for a given locale.
  157. *
  158. * When switching to a locale, translations for this locale must be loaded from scratch.
  159. *
  160. * @since 4.7.0
  161. * @access private
  162. *
  163. * @global Mo[] $l10n An array of all currently loaded text domains.
  164. *
  165. * @param string $locale The locale to load translations for.
  166. */
  167. private function load_translations( $locale ) {
  168. global $l10n;
  169. $domains = $l10n ? array_keys( $l10n ) : array();
  170. load_default_textdomain( $locale );
  171. foreach ( $domains as $domain ) {
  172. if ( 'default' === $domain ) {
  173. continue;
  174. }
  175. unload_textdomain( $domain );
  176. get_translations_for_domain( $domain );
  177. }
  178. }
  179. /**
  180. * Changes the site's locale to the given one.
  181. *
  182. * Loads the translations, changes the global `$wp_locale` object and updates
  183. * all post type labels.
  184. *
  185. * @since 4.7.0
  186. * @access private
  187. *
  188. * @global WP_Locale $wp_locale The WordPress date and time locale object.
  189. *
  190. * @param string $locale The locale to change to.
  191. */
  192. private function change_locale( $locale ) {
  193. // Reset translation availability information.
  194. _get_path_to_translation( null, true );
  195. $this->load_translations( $locale );
  196. $GLOBALS['wp_locale'] = new WP_Locale();
  197. /**
  198. * Fires when the locale is switched to or restored.
  199. *
  200. * @since 4.7.0
  201. *
  202. * @param string $locale The new locale.
  203. */
  204. do_action( 'change_locale', $locale );
  205. }
  206. }