1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace EventEspresso\core\services\assets; |
4
|
|
|
|
5
|
|
|
use EventEspresso\core\domain\DomainInterface; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* I18nRegistry |
9
|
|
|
* Handles registering translations for registered script handles. |
10
|
|
|
* |
11
|
|
|
* @package EventEspresso\core\services\assets |
12
|
|
|
* @author Darren Ethier |
13
|
|
|
* @since $VID:$ |
14
|
|
|
*/ |
15
|
|
|
class I18nRegistry |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* @var DomainInterface |
19
|
|
|
*/ |
20
|
|
|
private $domain; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Will hold all registered i18n scripts. |
24
|
|
|
* |
25
|
|
|
* @var array |
26
|
|
|
*/ |
27
|
|
|
private $registered_i18n = array(); |
28
|
|
|
|
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Used to hold queued translations for the chunks loading in a view. |
32
|
|
|
* |
33
|
|
|
* @var array |
34
|
|
|
*/ |
35
|
|
|
private $queued_handle_translations = array(); |
36
|
|
|
|
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* Obtained from the generated json file from the all javascript using wp.i18n with a map of script handle names to |
40
|
|
|
* translation strings. |
41
|
|
|
* |
42
|
|
|
* @var array |
43
|
|
|
*/ |
44
|
|
|
private $i18n_map; |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* I18nRegistry constructor. |
49
|
|
|
* |
50
|
|
|
* @param array() $i18n_map An array of script handle names and the strings translated for those handles. If not |
51
|
|
|
* provided, the class will look for map in root of plugin with filename of |
52
|
|
|
* 'translation-map.json'. |
53
|
|
|
* @param DomainInterface $domain |
54
|
|
|
*/ |
55
|
|
|
public function __construct(array $i18n_map = array(), DomainInterface $domain) |
56
|
|
|
{ |
57
|
|
|
$this->domain = $domain; |
58
|
|
|
$this->setI18nMap($i18n_map); |
59
|
|
|
add_filter('print_scripts_array', array($this, 'queueI18n')); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Used to register a script that has i18n strings for its $handle |
65
|
|
|
* |
66
|
|
|
* @param string $handle The script handle reference. |
67
|
|
|
* @param string $domain The i18n domain for the strings. |
68
|
|
|
*/ |
69
|
|
|
public function registerScriptI18n($handle, $domain = 'event_espresso') |
70
|
|
|
{ |
71
|
|
|
$this->registered_i18n[$handle] = $domain; |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
|
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* Callback on print_scripts_array to listen for scripts enqueued and handle setting up the localized data. |
78
|
|
|
* |
79
|
|
|
* @param array $handles Array of registered script handles. |
80
|
|
|
* @return array |
81
|
|
|
*/ |
82
|
|
|
public function queueI18n(array $handles) |
83
|
|
|
{ |
84
|
|
|
if (empty($this->registered_i18n) || empty($this->i18n_map)) { |
85
|
|
|
return $handles; |
86
|
|
|
} |
87
|
|
|
foreach ($handles as $handle) { |
88
|
|
|
$this->queueI18nTranslationsForHandle($handle); |
89
|
|
|
} |
90
|
|
|
if ($this->queued_handle_translations) { |
|
|
|
|
91
|
|
|
foreach ($this->queued_handle_translations as $handle => $translations_for_domain) { |
92
|
|
|
$this->registerInlineScript( |
93
|
|
|
$handle, |
94
|
|
|
$translations_for_domain['translations'], |
95
|
|
|
$translations_for_domain['domain'] |
96
|
|
|
); |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
return $handles; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Registers inline script with translations for given handle and domain. |
105
|
|
|
* |
106
|
|
|
* @param string $handle Handle used to register javascript file containing translations. |
107
|
|
|
* @param array $translations Array of string translations. |
108
|
|
|
* @param string $domain Domain for translations. If left empty then strings are registered with the default |
109
|
|
|
* domain for the javascript. |
110
|
|
|
*/ |
111
|
|
|
private function registerInlineScript($handle, array $translations, $domain) |
112
|
|
|
{ |
113
|
|
|
$script = $domain ? |
114
|
|
|
'wp.i18n.setLocaleData( ' . wp_json_encode($translations) . ', ' . $domain . ' );' : |
115
|
|
|
'wp.i18n.setLocaleData( ' . wp_json_encode($translations) . ' );'; |
116
|
|
|
wp_add_inline_script($handle, $script, 'before'); |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
|
120
|
|
|
/** |
121
|
|
|
* Queues up the translation strings for the given handle. |
122
|
|
|
* |
123
|
|
|
* @param string $handle The script handle being queued up. |
124
|
|
|
*/ |
125
|
|
|
private function queueI18nTranslationsForHandle($handle) |
126
|
|
|
{ |
127
|
|
|
if (isset($this->registered_i18n[$handle])) { |
128
|
|
|
$domain = $this->registered_i18n[$handle]; |
129
|
|
|
$translations = $this->getJedLocaleDataForDomainAndChunk($handle, $domain); |
130
|
|
|
if (count($translations) > 1) { |
131
|
|
|
$this->queued_handle_translations[$handle] = array( |
132
|
|
|
'domain' => $domain, |
133
|
|
|
'translations' => $translations, |
134
|
|
|
); |
135
|
|
|
} |
136
|
|
|
unset($this->registered_i18n[$handle]); |
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Sets the internal i18n_map property. |
143
|
|
|
* If $chunk_map is empty or not an array, will attempt to load a chunk map from a default named map. |
144
|
|
|
* |
145
|
|
|
* @param array $i18n_map If provided, an array of translation strings indexed by script handle names they |
146
|
|
|
* correspond to. |
147
|
|
|
*/ |
148
|
|
|
private function setI18nMap(array $i18n_map) |
149
|
|
|
{ |
150
|
|
|
if (empty($i18n_map)) { |
151
|
|
|
$i18n_map = file_exists($this->domain->pluginPath() . 'translation-map.json') |
152
|
|
|
? json_decode( |
153
|
|
|
file_get_contents($this->domain->pluginPath() . 'translation-map.json'), |
154
|
|
|
true |
155
|
|
|
) |
156
|
|
|
: array(); |
157
|
|
|
} |
158
|
|
|
$this->i18n_map = $i18n_map; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Get the jed locale data for a given $handle and domain |
164
|
|
|
* |
165
|
|
|
* @param string $handle The name for the script handle we want strings returned for. |
166
|
|
|
* @param string $domain The i18n domain. |
167
|
|
|
* @return array |
168
|
|
|
*/ |
169
|
|
|
protected function getJedLocaleDataForDomainAndChunk($handle, $domain) |
170
|
|
|
{ |
171
|
|
|
$translations = $this->getJedLocaleData($domain); |
172
|
|
|
// get index for adding back after extracting strings for this $chunk. |
173
|
|
|
$index = $translations['']; |
174
|
|
|
$translations = $this->getLocaleDataMatchingMap( |
175
|
|
|
$this->getOriginalStringsForHandleFromMap($handle), |
176
|
|
|
$translations |
177
|
|
|
); |
178
|
|
|
$translations[''] = $index; |
179
|
|
|
return $translations; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Get locale data for given strings from given translations |
185
|
|
|
* |
186
|
|
|
* @param array $string_set This is the subset of strings (msgIds) we want to extract from the translations array. |
187
|
|
|
* @param array $translations Translation data to extra strings from. |
188
|
|
|
* @return array |
189
|
|
|
*/ |
190
|
|
|
protected function getLocaleDataMatchingMap(array $string_set, array $translations) |
191
|
|
|
{ |
192
|
|
|
if (empty($string_set)) { |
193
|
|
|
return array(); |
194
|
|
|
} |
195
|
|
|
// some strings with quotes in them will break on the array_flip, so making sure quotes in the string are |
196
|
|
|
// slashed also filter falsey values. |
197
|
|
|
$string_set = array_unique(array_filter(wp_slash($string_set))); |
198
|
|
|
return array_intersect_key($translations, array_flip($string_set)); |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* Get original strings to translate for the given chunk from the map |
204
|
|
|
* |
205
|
|
|
* @param string $handle The script handle name to get strings from the map for. |
206
|
|
|
* @return array |
207
|
|
|
*/ |
208
|
|
|
protected function getOriginalStringsForHandleFromMap($handle) |
209
|
|
|
{ |
210
|
|
|
return isset($this->i18n_map[$handle]) ? $this->i18n_map[$handle] : array(); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Returns Jed-formatted localization data. |
216
|
|
|
* |
217
|
|
|
* @param string $domain Translation domain. |
218
|
|
|
* @return array |
219
|
|
|
*/ |
220
|
|
|
private function getJedLocaleData($domain) |
221
|
|
|
{ |
222
|
|
|
$translations = get_translations_for_domain($domain); |
223
|
|
|
|
224
|
|
|
$locale = array( |
225
|
|
|
'' => array( |
226
|
|
|
'domain' => $domain, |
227
|
|
|
'lang' => is_admin() ? get_user_locale() : get_locale(), |
228
|
|
|
), |
229
|
|
|
); |
230
|
|
|
|
231
|
|
|
if (! empty($translations->headers['Plural-Forms'])) { |
232
|
|
|
$locale['']['plural_forms'] = $translations->headers['Plural-Forms']; |
233
|
|
|
} |
234
|
|
|
|
235
|
|
|
foreach ($translations->entries as $msgid => $entry) { |
236
|
|
|
$locale[$msgid] = $entry->translations; |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
return $locale; |
240
|
|
|
} |
241
|
|
|
} |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.