WP_Locale_Switcher::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
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
/**
11
 * Core class used for switching locales.
12
 *
13
 * @since 4.7.0
14
 */
15
class WP_Locale_Switcher {
16
	/**
17
	 * Locale stack.
18
	 *
19
	 * @since 4.7.0
20
	 * @access private
21
	 * @var string[]
22
	 */
23
	private $locales = array();
24
25
	/**
26
	 * Original locale.
27
	 *
28
	 * @since 4.7.0
29
	 * @access private
30
	 * @var string
31
	 */
32
	private $original_locale;
33
34
	/**
35
	 * Holds all available languages.
36
	 *
37
	 * @since 4.7.0
38
	 * @access private
39
	 * @var array An array of language codes (file names without the .mo extension).
40
	 */
41
	private $available_languages = array();
42
43
	/**
44
	 * Constructor.
45
	 *
46
	 * Stores the original locale as well as a list of all available languages.
47
	 *
48
	 * @since 4.7.0
49
	 */
50
	public function __construct() {
51
		$this->original_locale     = is_admin() ? get_user_locale() : get_locale();
52
		$this->available_languages = array_merge( array( 'en_US' ), get_available_languages() );
53
	}
54
55
	/**
56
	 * Initializes the locale switcher.
57
	 *
58
	 * Hooks into the {@see 'locale'} filter to change the locale on the fly.
59
	 */
60
	public function init() {
61
		add_filter( 'locale', array( $this, 'filter_locale' ) );
62
	}
63
64
	/**
65
	 * Switches the translations according to the given locale.
66
	 *
67
	 * @since 4.7.0
68
	 *
69
	 * @param string $locale The locale to switch to.
70
	 * @return bool True on success, false on failure.
71
	 */
72
	public function switch_to_locale( $locale ) {
73
		$current_locale = is_admin() ? get_user_locale() : get_locale();
74
		if ( $current_locale === $locale ) {
75
			return false;
76
		}
77
78
		if ( ! in_array( $locale, $this->available_languages, true ) ) {
79
			return false;
80
		}
81
82
		$this->locales[] = $locale;
83
84
		$this->change_locale( $locale );
85
86
		/**
87
		 * Fires when the locale is switched.
88
		 *
89
		 * @since 4.7.0
90
		 *
91
		 * @param string $locale The new locale.
92
		 */
93
		do_action( 'switch_locale', $locale );
94
95
		return true;
96
	}
97
98
	/**
99
	 * Restores the translations according to the previous locale.
100
	 *
101
	 * @since 4.7.0
102
	 *
103
	 * @return string|false Locale on success, false on failure.
104
	 */
105
	public function restore_previous_locale() {
106
		$previous_locale = array_pop( $this->locales );
107
108
		if ( null === $previous_locale ) {
109
			// The stack is empty, bail.
110
			return false;
111
		}
112
113
		$locale = end( $this->locales );
114
115
		if ( ! $locale ) {
116
			// There's nothing left in the stack: go back to the original locale.
117
			$locale = $this->original_locale;
118
		}
119
120
		$this->change_locale( $locale );
121
122
		/**
123
		 * Fires when the locale is restored to the previous one.
124
		 *
125
		 * @since 4.7.0
126
		 *
127
		 * @param string $locale          The new locale.
128
		 * @param string $previous_locale The previous locale.
129
		 */
130
		do_action( 'restore_previous_locale', $locale, $previous_locale );
131
132
		return $locale;
133
	}
134
135
	/**
136
	 * Restores the translations according to the original locale.
137
	 *
138
	 * @since 4.7.0
139
	 *
140
	 * @return string|false Locale on success, false on failure.
141
	 */
142
	public function restore_current_locale() {
143
		if ( empty( $this->locales ) ) {
144
			return false;
145
		}
146
147
		$this->locales = array( $this->original_locale );
148
149
		return $this->restore_previous_locale();
150
	}
151
152
	/**
153
	 * Whether switch_to_locale() is in effect.
154
	 *
155
	 * @since 4.7.0
156
	 *
157
	 * @return bool True if the locale has been switched, false otherwise.
158
	 */
159
	public function is_switched() {
160
		return ! empty( $this->locales );
161
	}
162
163
	/**
164
	 * Filters the WordPress install's locale.
165
	 *
166
	 * @since 4.7.0
167
	 *
168
	 * @param string $locale The WordPress install's locale.
169
	 * @return string The locale currently being switched to.
170
	 */
171
	public function filter_locale( $locale ) {
172
		$switched_locale = end( $this->locales );
173
174
		if ( $switched_locale ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $switched_locale of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
175
			return $switched_locale;
176
		}
177
178
		return $locale;
179
	}
180
181
	/**
182
	 * Load translations for a given locale.
183
	 *
184
	 * When switching to a locale, translations for this locale must be loaded from scratch.
185
	 *
186
	 * @since 4.7.0
187
	 * @access private
188
	 *
189
	 * @global Mo[] $l10n An array of all currently loaded text domains.
190
	 *
191
	 * @param string $locale The locale to load translations for.
192
	 */
193
	private function load_translations( $locale ) {
194
		global $l10n;
195
196
		$domains = $l10n ? array_keys( $l10n ) : array();
197
198
		load_default_textdomain( $locale );
199
200
		foreach ( $domains as $domain ) {
201
			if ( 'default' === $domain ) {
202
				continue;
203
			}
204
205
			unload_textdomain( $domain );
206
			get_translations_for_domain( $domain );
207
		}
208
	}
209
210
	/**
211
	 * Changes the site's locale to the given one.
212
	 *
213
	 * Loads the translations, changes the global `$wp_locale` object and updates
214
	 * all post type labels.
215
	 *
216
	 * @since 4.7.0
217
	 * @access private
218
	 *
219
	 * @global WP_Locale $wp_locale The WordPress date and time locale object.
220
	 *
221
	 * @param string $locale The locale to change to.
222
	 */
223
	private function change_locale( $locale ) {
224
		// Reset translation availability information.
225
		_get_path_to_translation( null, true );
226
227
		$this->load_translations( $locale );
228
229
		$GLOBALS['wp_locale'] = new WP_Locale();
230
231
		/**
232
		 * Fires when the locale is switched to or restored.
233
		 *
234
		 * @since 4.7.0
235
		 *
236
		 * @param string $locale The new locale.
237
		 */
238
		do_action( 'change_locale', $locale );
239
	}
240
}
241