class-wp-locale-switcher.php 4.9 KB

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