class-wp-locale-switcher.php 4.9 KB

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