PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more / 4.4.7
EmbedPress – PDF Embedder, Embed PDF viewer, YouTube Videos, 3D FlipBook, Social feeds & more v4.4.7
4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / Core / LocalizationManager.php
embedpress / Core Last commit date
AssetManager.php 6 months ago LocalizationManager.php 6 months ago init.php 9 months ago
LocalizationManager.php
570 lines
1 <?php
2
3 namespace EmbedPress\Core;
4
5 use EmbedPress\Includes\Classes\Helper;
6
7 /**
8 * EmbedPress Localization Manager
9 *
10 * Handles all JavaScript localization for EmbedPress blocks, admin, and frontend
11 * Provides clean separation of concerns from AssetManager
12 */
13 class LocalizationManager
14 {
15 /**
16 * Setup admin localization scripts
17 *
18 * @param string $hook Current admin page hook
19 */
20 public static function setup_admin_localization($hook)
21 {
22 global $pagenow;
23
24 self::setup_license_localization();
25 self::setup_feature_notices_localization();
26
27 // Setup settings page localization if on EmbedPress settings page
28 if (strpos($hook, 'embedpress') !== false) {
29 self::setup_settings_localization();
30 self::setup_preview_localization();
31 }
32
33 // Only setup localization on post edit pages
34 if (!in_array($pagenow, ['post.php', 'post-new.php'])) {
35 return;
36 }
37 }
38
39 /**
40 * Setup editor localization scripts
41 */
42 public static function setup_editor_localization()
43 {
44 self::setup_frontend_script_localization();
45 self::setup_gutenberg_localization();
46 self::setup_new_blocks_localization();
47 self::setup_preview_localization();
48 }
49
50 /**
51 * Setup frontend localization scripts
52 */
53 public static function setup_frontend_localization()
54 {
55 self::setup_frontend_script_localization();
56 self::setup_gutenberg_localization();
57 self::setup_preview_localization();
58 self::setup_analytics_localization();
59 }
60
61 /**
62 * Setup Elementor widget localization
63 */
64 public static function setup_elementor_localization()
65 {
66 self::setup_frontend_script_localization();
67 self::setup_calendar_widget_localization();
68 self::setup_analytics_localization();
69 }
70
71 /**
72 * Setup preview localization (attached to preview script)
73 */
74 private static function setup_preview_localization()
75 {
76 // Try both admin and preview script handles
77 $script_handles = ['embedpress-admin', 'embedpress-preview'];
78
79 $url_schemes = apply_filters('embedpress:getAdditionalURLSchemes', self::get_url_schemes());
80
81 // Ensure required constants are defined with fallbacks
82 $version = defined('EMBEDPRESS_VERSION') ? EMBEDPRESS_VERSION : '1.0.0';
83 $shortcode = defined('EMBEDPRESS_SHORTCODE') ? EMBEDPRESS_SHORTCODE : 'embedpress';
84 $assets_url = defined('EMBEDPRESS_URL_ASSETS') ? EMBEDPRESS_URL_ASSETS : '';
85
86 $localization_data = [
87 'previewSettings' => [
88 'baseUrl' => get_site_url() . '/',
89 'versionUID' => $version,
90 'debug' => defined('WP_DEBUG') && WP_DEBUG,
91 ],
92 'shortcode' => $shortcode,
93 'assetsUrl' => $assets_url,
94 'urlSchemes' => $url_schemes,
95 ];
96
97 foreach ($script_handles as $script_handle) {
98 if (wp_script_is($script_handle, 'enqueued') || wp_script_is($script_handle, 'registered')) {
99 wp_localize_script($script_handle, 'embedpressPreviewData', $localization_data);
100 }
101 }
102
103 wp_localize_script($script_handle, 'embedpressAdminParams', [
104 'ajaxUrl' => admin_url('admin-ajax.php'),
105 'nonce' => wp_create_nonce('embedpress')
106 ]);
107 }
108
109 /**
110 * Setup license script localization
111 */
112 private static function setup_license_localization()
113 {
114 $script_handle = 'embedpress-admin';
115
116 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
117 return;
118 }
119
120 $item_id = defined('EMBEDPRESS_SL_ITEM_ID') ? EMBEDPRESS_SL_ITEM_ID : 'embedpress';
121
122 wp_localize_script($script_handle, 'embedpressLicenseData', [
123 'nonce' => wp_create_nonce('wpdeveloper_sl_' . $item_id . '_nonce')
124 ]);
125 }
126
127 /**
128 * Setup feature notices script localization
129 */
130 private static function setup_feature_notices_localization()
131 {
132 $script_handle = 'embedpress-feature-notices';
133
134 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
135 return;
136 }
137
138 wp_localize_script($script_handle, 'embedpressFeatureNotices', [
139 'ajaxurl' => admin_url('admin-ajax.php'),
140 'nonce' => wp_create_nonce('embedpress_feature_notice'),
141 ]);
142 }
143
144 /**
145 * Setup Gutenberg blocks localization (embedpressObj variable)
146 */
147 private static function setup_gutenberg_localization()
148 {
149 $script_handle = 'embedpress-blocks-editor';
150
151 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
152 return;
153 }
154
155 // Ensure required constants are defined
156 if (!defined('EMBEDPRESS_PLG_NAME')) {
157 return;
158 }
159
160 $elements = (array) get_option(EMBEDPRESS_PLG_NAME . ":elements", []);
161 $active_blocks = isset($elements['gutenberg']) ? (array) $elements['gutenberg'] : [];
162
163 $wistia_labels = self::get_wistia_labels();
164 $wistia_options = self::get_wistia_options();
165 $pars_url = wp_parse_url(get_site_url());
166 $documents_cta_options = (array) get_option(EMBEDPRESS_PLG_NAME . ':document');
167 $current_user = wp_get_current_user();
168 $assets_url = defined('EMBEDPRESS_URL_ASSETS') ? EMBEDPRESS_URL_ASSETS : '';
169 $static_url = defined('EMBEDPRESS_URL_STATIC') ? EMBEDPRESS_URL_STATIC : '';
170
171 // Get global powered_by setting
172 $g_settings = get_option(EMBEDPRESS_PLG_NAME, []);
173 $powered_by_default = isset($g_settings['embedpress_document_powered_by']) && $g_settings['embedpress_document_powered_by'] === 'yes';
174 $lazy_load_default = isset($g_settings['g_lazyload']) && $g_settings['g_lazyload'] == 1;
175
176 wp_localize_script($script_handle, 'embedpressGutenbergData', [
177
178
179 // Keep only the variables that are actually used in JavaScript
180 'wistiaLabels' => json_encode($wistia_labels),
181 'wistiaOptions' => $wistia_options,
182 'poweredBy' => apply_filters('embedpress_document_block_powered_by', $powered_by_default),
183 'isProVersion' => defined('EMBEDPRESS_PRO_PLUGIN_FILE'),
184 'twitchHost' => !empty($pars_url['host']) ? $pars_url['host'] : '',
185 'siteUrl' => site_url(),
186 'activeBlocks' => $active_blocks,
187 'documentCta' => $documents_cta_options,
188 'pdfRenderer' => Helper::get_pdf_renderer(),
189 'isProPluginActive' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
190 'ajaxUrl' => admin_url('admin-ajax.php'),
191 'adminUrl' => admin_url(),
192 'sourceNonce' => wp_create_nonce('source_nonce_embedpress'),
193 'canUploadMedia' => current_user_can('upload_files'),
194 'assetsUrl' => $assets_url,
195 'staticUrl' => $static_url,
196 // Use underscore naming for consistency with block attributes
197 'iframe_width' => Helper::get_options_value('enableEmbedResizeWidth', '600'),
198 'iframe_height' => Helper::get_options_value('enableEmbedResizeHeight', '400'),
199 'iframeWidth' => Helper::get_options_value('enableEmbedResizeWidth', '600'), // Keep camelCase for backward compatibility
200 'iframeHeight' => Helper::get_options_value('enableEmbedResizeHeight', '400'), // Keep camelCase for backward compatibility
201 'pdfCustomColor' => Helper::get_options_value('custom_color', '#403A81'),
202 'lazyLoad' => $lazy_load_default,
203 'brandingLogos' => [
204 'youtube' => Helper::get_branding_value('logo_url', 'youtube'),
205 'vimeo' => Helper::get_branding_value('logo_url', 'vimeo'),
206 'wistia' => Helper::get_branding_value('logo_url', 'wistia'),
207 'twitch' => Helper::get_branding_value('logo_url', 'twitch'),
208 'dailymotion' => Helper::get_branding_value('logo_url', 'dailymotion'),
209 'document' => Helper::get_branding_value('logo_url', 'document'),
210 ],
211 'userRoles' => Helper::get_user_roles(),
212 'currentUser' => $current_user->data,
213 'feedbackSubmitted' => get_option('embedpress_feedback_submited'),
214 'ratingHelpDisabled' => Helper::get_options_value('turn_off_rating_help', false),
215 'milestoneDisabled' => Helper::get_options_value('turn_off_milestone', false),
216
217 // Legacy support
218 'wistia_labels' => json_encode($wistia_labels),
219 'wisita_options' => $wistia_options,
220 'embedpress_powered_by' => apply_filters('embedpress_document_block_powered_by', $powered_by_default),
221 'embedpress_pro' => defined('EMBEDPRESS_PRO_PLUGIN_FILE'),
222 'twitch_host' => !empty($pars_url['host']) ? $pars_url['host'] : '',
223 'site_url' => site_url(),
224 'rest_url' => get_rest_url(),
225 'embedpress_rest_url' => get_rest_url(null, 'embedpress/v1/oembed/embedpress'),
226 'active_blocks' => $active_blocks,
227 'document_cta' => $documents_cta_options,
228 'pdf_renderer' => Helper::get_pdf_renderer(),
229 'is_pro_plugin_active' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
230 'ajaxurl' => admin_url('admin-ajax.php'),
231 'source_nonce' => wp_create_nonce('source_nonce_embedpress'),
232 'can_upload_media' => current_user_can('upload_files'),
233 'permalink_structure' => get_option('permalink_structure'),
234 'EMBEDPRESS_URL_ASSETS' => EMBEDPRESS_URL_ASSETS,
235 'iframe_width' => Helper::get_options_value('enableEmbedResizeWidth'),
236 'iframe_height' => Helper::get_options_value('enableEmbedResizeHeight'),
237 'pdf_custom_color' => Helper::get_options_value('custom_color'),
238 'pdf_custom_color' => Helper::get_options_value('custom_color'),
239 'youtube_brand_logo_url' => Helper::get_branding_value('logo_url', 'youtube'),
240 'vimeo_brand_logo_url' => Helper::get_branding_value('logo_url', 'vimeo'),
241 'wistia_brand_logo_url' => Helper::get_branding_value('logo_url', 'wistia'),
242 'twitch_brand_logo_url' => Helper::get_branding_value('logo_url', 'twitch'),
243 'dailymotion_brand_logo_url' => Helper::get_branding_value('logo_url', 'dailymotion'),
244 'user_roles' => Helper::get_user_roles(),
245 'current_user' => $current_user->data,
246 'is_embedpress_feedback_submited' => get_option('embedpress_feedback_submited'),
247 'turn_off_rating_help' => Helper::get_options_value('turn_off_rating_help'),
248 'turn_off_milestone' => Helper::get_options_value('turn_off_milestone'),
249 ]);
250 }
251
252 /**
253 * Setup frontend script localization (embedpressFrontendData variable)
254 */
255 private static function setup_frontend_script_localization()
256 {
257 // The embedpressFrontendData variable should be attached to multiple frontend scripts
258 $script_handles = ['embedpress-front', 'embedpress-ads'];
259
260 $localization_data = [
261 'ajaxurl' => admin_url('admin-ajax.php'),
262 'isProPluginActive' => defined('EMBEDPRESS_SL_ITEM_SLUG'),
263 'nonce' => wp_create_nonce('ep_nonce'),
264 ];
265
266 foreach ($script_handles as $script_handle) {
267 if (wp_script_is($script_handle, 'enqueued') || wp_script_is($script_handle, 'registered')) {
268 wp_localize_script($script_handle, 'embedpressFrontendData', $localization_data);
269 }
270 }
271 }
272
273 /**
274 * Setup settings page localization (attached to admin script)
275 */
276 private static function setup_settings_localization()
277 {
278 $script_handle = 'embedpress-admin';
279
280 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
281 return;
282 }
283
284 wp_localize_script($script_handle, 'embedpressSettingsData', [
285 'nonce' => wp_create_nonce('embedpress_elements_action'),
286 'ajaxNonce' => wp_create_nonce('embedpress_ajax_nonce'),
287 ]);
288 }
289
290 /**
291 * Setup new blocks localization (for new block system)
292 */
293 private static function setup_new_blocks_localization()
294 {
295 // Try multiple possible handles for new blocks
296 $possible_handles = [
297 'embedpress-blocks-editor', // Current handle from AssetManager
298 'embedpress-blocks', // Old handle
299 'embedpress_blocks-cgb-block-js', // Legacy handle
300 'embedpress-blocks-js', // Alternative handle
301 ];
302
303 $script_handle = null;
304 foreach ($possible_handles as $handle) {
305 if (wp_script_is($handle, 'enqueued') || wp_script_is($handle, 'registered')) {
306 $script_handle = $handle;
307 break;
308 }
309 }
310
311 if (!$script_handle) {
312 return;
313 }
314
315 // Ensure required constants are defined
316 if (!defined('EMBEDPRESS_PLG_NAME')) {
317 return;
318 }
319
320 $elements = (array) get_option(EMBEDPRESS_PLG_NAME . ":elements", []);
321 $active_blocks = isset($elements['gutenberg']) ? (array) $elements['gutenberg'] : [];
322
323 wp_localize_script($script_handle, 'embedpressNewBlocksData', [
324 'pluginDirPath' => defined('EMBEDPRESS_PATH_BASE') ? EMBEDPRESS_PATH_BASE : '',
325 'pluginDirUrl' => defined('EMBEDPRESS_URL_STATIC') ? EMBEDPRESS_URL_STATIC . '../' : '',
326 'activeBlocks' => $active_blocks,
327 'canUploadMedia' => current_user_can('upload_files'),
328 'ajaxUrl' => admin_url('admin-ajax.php'),
329 'nonce' => wp_create_nonce('embedpress_nonce'),
330 'restUrl' => rest_url('embedpress/v1/'),
331 'siteUrl' => site_url(),
332 ]);
333 }
334
335
336
337
338
339 /**
340 * Setup analytics tracker localization
341 */
342 private static function setup_analytics_localization()
343 {
344 $script_handle = 'embedpress-analytics-tracker';
345
346 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
347 return;
348 }
349
350 // Get analytics manager instance to check for embedded content
351 $has_embedded_content = false;
352 if (class_exists('EmbedPress\Includes\Classes\Analytics\Analytics_Manager')) {
353 $analytics_manager = \EmbedPress\Includes\Classes\Analytics\Analytics_Manager::get_instance();
354 $has_embedded_content = $analytics_manager->has_embedded_content();
355 }
356
357 // Get tracking enabled setting
358 $tracking_enabled = get_option('embedpress_analytics_tracking_enabled', true);
359
360 // Get original referrer if available
361 $original_referrer = '';
362 if (defined('EMBEDPRESS_ORIGINAL_REFERRER') && !empty(EMBEDPRESS_ORIGINAL_REFERRER)) {
363 $original_referrer = EMBEDPRESS_ORIGINAL_REFERRER;
364 }
365
366 // Get session ID safely
367 $session_id = self::get_analytics_session_id();
368
369 wp_localize_script($script_handle, 'embedpress_analytics', [
370 'ajax_url' => admin_url('admin-ajax.php'),
371 'rest_url' => rest_url('embedpress/v1/analytics/'),
372 'nonce' => wp_create_nonce('wp_rest'),
373 'session_id' => $session_id,
374 'page_url' => get_permalink(),
375 'post_id' => get_the_ID(),
376 'tracking_enabled' => (bool) $tracking_enabled,
377 'original_referrer' => $original_referrer,
378 'has_embedded_content' => $has_embedded_content
379 ]);
380 }
381
382 /**
383 * Setup Google Calendar widget localization
384 */
385 private static function setup_calendar_widget_localization()
386 {
387 $script_handle = 'epgc';
388
389 if (!wp_script_is($script_handle, 'enqueued') && !wp_script_is($script_handle, 'registered')) {
390 return;
391 }
392
393 $nonce = wp_create_nonce('epgc_nonce');
394 wp_localize_script($script_handle, 'embedpressCalendarData', [
395 'ajaxUrl' => admin_url('admin-ajax.php'),
396 'nonce' => $nonce,
397 'translations' => [
398 'allDay' => __('All day', 'embedpress'),
399 'createdBy' => __('Created by', 'embedpress'),
400 'goToEvent' => __('Go to event', 'embedpress'),
401 'unknownError' => __('Unknown error', 'embedpress'),
402 'requestError' => __('Request error', 'embedpress'),
403 'loading' => __('Loading', 'embedpress')
404 ]
405 ]);
406 }
407
408 /**
409 * Load plugin text domain for translations
410 */
411 public static function load_text_domain()
412 {
413 $locale = determine_locale();
414 $locale = apply_filters('plugin_locale', $locale, 'embedpress');
415
416 // Load from WordPress languages directory first
417 if (file_exists(WP_LANG_DIR . "/embedpress-" . $locale . '.mo')) {
418 unload_textdomain('embedpress');
419 load_textdomain('embedpress', WP_LANG_DIR . "/embedpress-" . $locale . '.mo');
420 }
421
422 // Load from plugin languages directory
423 load_plugin_textdomain('embedpress', false, plugin_basename(dirname(EMBEDPRESS_FILE)) . '/languages');
424 }
425
426 /**
427 * Get Wistia labels for localization
428 *
429 * @return array
430 */
431 private static function get_wistia_labels()
432 {
433 return [
434 'watch_from_beginning' => __('Watch from the beginning', 'embedpress'),
435 'skip_to_where_you_left_off' => __('Skip to where you left off', 'embedpress'),
436 'you_have_watched_it_before' => __('It looks like you\'ve watched<br />part of this video before!', 'embedpress'),
437 ];
438 }
439
440 /**
441 * Get Wistia options safely
442 *
443 * @return mixed|null
444 */
445 private static function get_wistia_options()
446 {
447 if (!function_exists('embedpress_wisita_pro_get_options')) {
448 return null;
449 }
450
451 try {
452 // return embedpress_wisita_pro_get_options();
453 } catch (\Exception $e) {
454 // Silently fail if function throws an error
455 return null;
456 }
457 }
458
459 /**
460 * Get branding value safely
461 *
462 * @param string $type
463 * @param string $provider
464 * @return string
465 */
466 private static function get_branding_value($type, $provider)
467 {
468 if (!function_exists('get_branding_value')) {
469 return '';
470 }
471
472 try {
473 return self::get_branding_value($type, $provider);
474 } catch (\Exception $e) {
475 return '';
476 }
477 }
478
479 /**
480 * Get analytics session ID safely
481 *
482 * @return string
483 */
484 private static function get_analytics_session_id()
485 {
486 // Prefer cookie-based session IDs to avoid server PHP session configuration issues
487 if (isset($_COOKIE['ep_session_id'])) {
488 $cookie = $_COOKIE['ep_session_id'];
489 // Allow only safe characters and a minimum length
490 if (is_string($cookie) && preg_match('/^[A-Za-z0-9._:-]{8,}$/', $cookie)) {
491 return sanitize_text_field($cookie);
492 }
493 }
494
495 // Generate a new ephemeral session ID
496 $id = 'ep-sess-' . time() . '-' . wp_generate_password(8, false);
497
498 // Set a session cookie (expires when the browser closes)
499 if (!headers_sent()) {
500 $path = defined('COOKIEPATH') ? COOKIEPATH : '/';
501 $domain = (defined('COOKIE_DOMAIN') && COOKIE_DOMAIN) ? COOKIE_DOMAIN : '';
502 $secure = is_ssl();
503 $httponly = true;
504 setcookie('ep_session_id', $id, 0, $path, $domain, $secure, $httponly);
505 }
506
507 return $id;
508 }
509
510 /**
511 * Get URL schemes for preview script
512 *
513 * @return array
514 */
515 private static function get_url_schemes()
516 {
517 return [
518 // Apple podcasts
519 'podcasts.apple.com/*',
520 // YouTube
521 'youtube.com/watch\\?*',
522 'youtube.com/playlist\\?*',
523 'youtube.com/channel/*',
524 'youtube.com/c/*',
525 'youtube.com/user/*',
526 'youtube.com/(\w+)[^?\/]*$',
527 // Vimeo
528 'vimeo.com/*',
529 'vimeo.com/groups/*/videos/*',
530 // Twitter
531 'twitter.com/*/status/*',
532 'twitter.com/i/moments/*',
533 'twitter.com/*/timelines/*',
534 // Facebook
535 'facebook.com/*',
536 'fb.watch/*',
537 // Instagram
538 'instagram.com/p/*',
539 'instagr.am/p/*',
540 // SoundCloud
541 'soundcloud.com/*',
542 // Twitch
543 '*.twitch.tv/*',
544 'twitch.tv/*',
545 // Wistia
546 '*.wistia.com/medias/*',
547 'fast.wistia.com/embed/medias/*.jsonp',
548 // Google services
549 'google.com/*',
550 'google.com.*/*',
551 'google.co.*/*',
552 'maps.google.com/*',
553 'docs.google.com/presentation/*',
554 'docs.google.com/document/*',
555 'docs.google.com/spreadsheets/*',
556 'docs.google.com/forms/*',
557 'docs.google.com/drawings/*',
558 ];
559 }
560
561 /**
562 * Initialize localization manager hooks
563 */
564 public static function init()
565 {
566 // Load text domain early
567 add_action('plugins_loaded', [__CLASS__, 'load_text_domain'], 1);
568 }
569 }
570