PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 2.5.7
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v2.5.7
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / inc / admin.php

admin.php in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 2.5.7, at inc/admin.php

866 lines 38.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Admin class.
4 *
5 * Author: Andrei Baicus <andrei@themeisle.com>
6 * Created on: 19/07/2018
7 *
8 * @soundtrack Somewhere Else - Marillion
9 * @package \Optimole\Inc
10 * @author Optimole <friends@optimole.com>
11 */
12
13 /**
14 * Class Optml_Admin
15 */
16 class Optml_Admin {
17
18 /**
19 * Hold the settings object.
20 *
21 * @var Optml_Settings Settings object.
22 */
23 public $settings;
24
25 /**
26 * Optml_Admin constructor.
27 */
28 public function __construct() {
29 $this->settings = new Optml_Settings();
30 add_action( 'plugin_action_links_' . plugin_basename( OPTML_BASEFILE ), [ $this, 'add_action_links' ] );
31 add_action( 'admin_menu', [ $this, 'add_dashboard_page' ] );
32 add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ], PHP_INT_MIN );
33 add_action( 'admin_notices', [ $this, 'add_notice' ] );
34 add_action( 'admin_notices', [ $this, 'add_notice_upgrade' ] );
35 add_filter( 'admin_body_class', [ $this, 'add_body_class' ] );
36 add_action( 'optml_daily_sync', [ $this, 'daily_sync' ] );
37 add_action( 'admin_init', [ $this, 'maybe_redirect' ] );
38 if ( ! is_admin() && $this->settings->is_connected() && ! wp_next_scheduled( 'optml_daily_sync' ) ) {
39 wp_schedule_event( time() + 10, 'daily', 'optml_daily_sync', [] );
40 }
41 add_action( 'optml_after_setup', [ $this, 'register_public_actions' ], 999999 );
42
43 }
44
45 /**
46 * Adds Optimole tag to admin bar
47 */
48 public function add_report_menu() {
49 global $wp_admin_bar;
50
51 $wp_admin_bar->add_node(
52 [
53 'id' => 'optml_report_script',
54 'href' => '#',
55 'title' => '<span class="ab-icon"></span>Optimole ' . __( 'debugger', 'optimole-wp' ),
56 ]
57 );
58 $wp_admin_bar->add_menu(
59 [
60 'id' => 'optml_status',
61 'title' => __( 'Troubleshoot this page', 'optimole-wp' ),
62 'parent' => 'optml_report_script',
63 ]
64 );
65 }
66
67 /**
68 * Adds Optimole css to admin bar
69 */
70 public function print_report_css() {
71 ?>
72 <style type="text/css">
73 li#wp-admin-bar-optml_report_script > div :hover {
74 cursor: pointer;
75 color: #00b9eb !important;
76 text-decoration: underline;
77 }
78
79 #wpadminbar #wp-admin-bar-optml_report_script .ab-icon:before {
80 content: "\f227";
81 top: 3px;
82 }
83
84 /* The Modal (background) */
85 .optml-modal {
86 display: none; /* Hidden by default */
87 position: fixed; /* Stay in place */
88 z-index: 2147483641; /* Sit on top */
89 padding-top: 100px; /* Location of the box */
90 left: 0;
91 top: 0;
92 width: 100%; /* Full width */
93 height: 100%; /* Full height */
94 overflow: auto; /* Enable scroll if needed */
95 background-color: rgb(0, 0, 0); /* Fallback color */
96 background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
97 }
98
99 /* Modal Content */
100 .optml-modal-content {
101 background-color: #fefefe;
102 margin: auto;
103 padding: 20px;
104 border: 1px solid #888;
105 width: 80%;
106 }
107
108 /* The Close Button */
109 .optml-close {
110 color: #aaaaaa;
111 float: right;
112 font-size: 28px;
113 font-weight: bold;
114 }
115
116 .optml-modal-content ul {
117 list-style: none;
118 font-size: 80%;
119 margin-top: 50px;
120 }
121
122 .optml-close:hover,
123 .optml-close:focus {
124 color: #000;
125 text-decoration: none;
126 cursor: pointer;
127 }
128 </style>
129 <?php
130 }
131
132 /**
133 * Register public actions.
134 */
135 public function register_public_actions() {
136 add_action( 'wp_head', [ $this, 'generator' ] );
137 add_filter( 'wp_resource_hints', [ $this, 'add_dns_prefetch' ], 10, 2 );
138
139 if ( Optml_Manager::should_ignore_image_tags() ) {
140 return;
141 }
142 if ( ! is_admin() && $this->settings->get( 'report_script' ) === 'enabled' && current_user_can( 'manage_options' ) ) {
143
144 add_action( 'wp_head', [ $this, 'print_report_css' ] );
145 add_action( 'wp_before_admin_bar_render', [ $this, 'add_report_menu' ] );
146 add_action( 'wp_enqueue_scripts', [ $this, 'add_diagnosis_script' ] );
147 }
148 if ( ! $this->settings->use_lazyload() ) {
149 return;
150 }
151 add_action( 'wp_enqueue_scripts', [ $this, 'frontend_scripts' ] );
152 add_action( 'wp_head', [ $this, 'inline_bootstrap_script' ] );
153
154 add_filter( 'optml_additional_html_classes', [ $this, 'add_no_js_class_to_html_tag' ], 10, 1 );
155 }
156
157 /**
158 * Use filter to add additional class to html tag.
159 *
160 * @param array $classes The classes to be added.
161 *
162 * @return array
163 */
164 public function add_no_js_class_to_html_tag( $classes ) {
165 return array_merge( $classes, [ 'optml_no_js' ] );
166 }
167
168 /**
169 * Adds script for lazyload/js replacement.
170 */
171 public function inline_bootstrap_script() {
172
173 $domain = 'https://' . OPTML_JS_CDN;
174
175 $min = ! OPTML_DEBUG ? '.min' : '';
176 $bgclasses = Optml_Lazyload_Replacer::get_lazyload_bg_classes();
177 $watcher_classes = Optml_Lazyload_Replacer::get_watcher_lz_classes();
178 $lazyload_bg_selectors = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
179 foreach ( $bgclasses as $key ) {
180 $lazyload_bg_selectors[] = '.' . $key;
181 }
182 $lazyload_bg_selectors = empty( $lazyload_bg_selectors ) ? '' : sprintf( '%s', implode( ', ', (array) $lazyload_bg_selectors ) );
183 $bgclasses = empty( $bgclasses ) ? '' : sprintf( '"%s"', implode( '","', (array) $bgclasses ) );
184 $watcher_classes = empty( $watcher_classes ) ? '' : sprintf( '"%s"', implode( '","', (array) $watcher_classes ) );
185 $default_network = ( $this->settings->get( 'network_optimization' ) === 'enabled' );
186 $retina_ready = ! ( $this->settings->get( 'retina_images' ) === 'enabled' );
187 $scale_is_disabled = ( $this->settings->get( 'scale' ) === 'enabled' );
188 $native_lazy_enabled = ( $this->settings->get( 'native_lazyload' ) === 'enabled' );
189 $output = sprintf(
190 '
191 <style type="text/css">
192 img[data-opt-src]:not([data-opt-lazy-loaded]) {
193 transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
194 -webkit-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
195 -moz-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
196 -o-transition: .2s filter linear, .2s opacity linear, .2s border-radius linear;
197 }
198 img[data-opt-src]:not([data-opt-lazy-loaded]) {
199 opacity: .75;
200 -webkit-filter: blur(8px);
201 -moz-filter: blur(8px);
202 -o-filter: blur(8px);
203 -ms-filter: blur(8px);
204 filter: blur(8px);
205 transform: scale(1.04);
206 animation: 0.1s ease-in;
207 -webkit-transform: translate3d(0, 0, 0);
208 }
209 %s
210 </style>
211 <script type="application/javascript">
212 document.documentElement.className = document.documentElement.className.replace(/\boptml_no_js\b/g, "");
213 (function(w, d){
214 var b = d.getElementsByTagName("head")[0];
215 var s = d.createElement("script");
216 var v = ("IntersectionObserver" in w && "isIntersecting" in w.IntersectionObserverEntry.prototype) ? "_no_poly" : "";
217 s.async = true;
218 s.src = "%s/v2/latest/optimole_lib" + v + "%s.js";
219 b.appendChild(s);
220 w.optimoleData = {
221 lazyloadOnly: "optimole-lazy-only",
222 backgroundReplaceClasses: [%s],
223 nativeLazyload : %s,
224 scalingDisabled: %s,
225 watchClasses: [%s],
226 backgroundLazySelectors: "%s",
227 network_optimizations: %s,
228 ignoreDpr: %s,
229 quality: %d
230 }
231 }(window, document));
232 document.addEventListener( "DOMContentLoaded", function() {
233
234 if ( "loading" in HTMLImageElement.prototype && Object.prototype.hasOwnProperty.call( optimoleData, "nativeLazyload" ) && optimoleData.nativeLazyload === true ) {
235 const images = document.querySelectorAll(\'img[loading="lazy"]\');
236 images.forEach( function (img) {
237 if ( !img.dataset.optSrc) {
238 return;
239 }
240 img.src = img.dataset.optSrc;
241 delete img.dataset.optSrc;
242 });
243 }
244 } );
245 </script>',
246 Optml_Lazyload_Replacer::IFRAME_TEMP_COMMENT,
247 esc_url( $domain ),
248 $min,
249 $bgclasses,
250 $native_lazy_enabled ? 'true' : 'false',
251 $scale_is_disabled ? 'true' : 'false',
252 $watcher_classes,
253 addcslashes( $lazyload_bg_selectors, '"' ),
254 defined( 'OPTML_NETWORK_ON' ) && constant( 'OPTML_NETWORK_ON' ) ? ( OPTML_NETWORK_ON ? 'true' : 'false' ) : ( $default_network ? 'true' : 'false' ),
255 $retina_ready ? 'true' : 'false',
256 $this->settings->get_numeric_quality()
257 );
258 echo $output;
259 }
260
261 /**
262 * Adds script for lazyload/js replacement.
263 */
264 public function add_diagnosis_script() {
265
266 wp_enqueue_script( 'optml-report', OPTML_URL . 'assets/js/report_script.js' );
267 $ignored_domains = [ 'gravatar.com', 'instagram.com', 'fbcdn' ];
268 $report_script = [
269 'optmlCdn' => $this->settings->get_cdn_url(),
270 'restUrl' => untrailingslashit( rest_url( OPTML_NAMESPACE . '/v1' ) ) . '/check_redirects',
271 'nonce' => wp_create_nonce( 'wp_rest' ),
272 'ignoredDomains' => $ignored_domains,
273 'wait' => __( 'We are checking the current page for any issues with optimized images ...', 'optimole-wp' ),
274 'description' => __( 'Optimole page analyzer', 'optimole-wp' ),
275 ];
276 wp_localize_script( 'optml-report', 'reportScript', $report_script );
277 }
278
279 /**
280 * Add settings links in the plugin listing page.
281 *
282 * @param array $links Old plugin links.
283 *
284 * @return array Altered links.
285 */
286 function add_action_links( $links ) {
287 if ( ! is_array( $links ) ) {
288 return $links;
289 }
290
291 return array_merge(
292 $links,
293 [
294 '<a href="' . admin_url( 'upload.php?page=optimole' ) . '">' . __( 'Settings', 'optimole-wp' ) . '</a>',
295 ]
296 );
297 }
298
299 /**
300 * Adds optimole optin class.
301 *
302 * @return string Optimole class.
303 */
304 public function add_body_class( $classes ) {
305
306 if ( ! $this->should_show_notice() ) {
307 return $classes;
308 }
309
310 return $classes . ' optimole-optin-show ';
311 }
312
313 /**
314 * Check if we should show the notice.
315 *
316 * @return bool Should show?
317 */
318 public function should_show_notice() {
319
320 $current_screen = get_current_screen();
321 if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
322 is_network_admin() ||
323 $this->settings->is_connected() ||
324 empty( $current_screen )
325 ) {
326 return false;
327 }
328
329 static $allowed_base = [
330 'plugins' => true,
331 'upload' => true,
332 'media' => true,
333 'themes' => true,
334 'appearance_page_tgmpa-install-plugins' => true,
335 ];
336
337 $screen_slug = '';
338 if ( isset( $current_screen->base ) ) {
339 $screen_slug = $current_screen->base;
340 }
341
342 if ( isset( $current_screen->parent_base ) ) {
343 $screen_slug = $current_screen->parent_base;
344 }
345
346 if ( empty( $screen_slug ) ||
347 ( ! isset( $allowed_base[ $screen_slug ] ) ) ||
348 ! current_user_can( 'manage_options' ) ||
349 ( get_option( 'optml_notice_optin', 'no' ) === 'yes' )
350 ) {
351 return false;
352 }
353
354 return true;
355 }
356
357 /**
358 * Show upgrade notice.
359 */
360 public function add_notice_upgrade() {
361 if ( ! $this->should_show_upgrade() ) {
362 return;
363 }
364 ?>
365 <div class="notice notice-warning optml-notice-optin">
366 <p> <?php printf( __( 'It seems your are close to the %1$s5.0000%2$s visits limit with %3$sOptiMole%4$s for this month. You might want to check the upgrade plans for a larger quota. %5$s %6$s What happens if i exceed the quota ?%7$s We will need to deliver back your original %8$sun-optimized%9$s images which might decrease your site speed perfomance.', 'optimole-wp' ), '<strong>', '</strong>', '<strong>', '</strong>', '<br/><br/>', '<i>', '</i >', '<strong>', '</strong>' ); ?></p>
367 <p>
368 <a href="https://optimole.com/pricing" target="_blank" class="button button-primary"><span
369 class="dashicons dashicons-external"></span><?php _e( 'Check upgrade plans', 'optimole-wp' ); ?>
370 </a>
371 <a class="button"
372 href="<?php echo wp_nonce_url( add_query_arg( [ 'optml_hide_upg' => 'yes' ] ), 'hide_nonce', 'optml_nonce' ); ?>"><?php _e( 'I\'ve done this', 'optimole-wp' ); ?></a>
373 </p>
374 </div>
375 <?php
376 }
377
378 /**
379 * Check if we should show the upgrade notice to users.
380 *
381 * @return bool Should we show it?
382 */
383 public function should_show_upgrade() {
384 $current_screen = get_current_screen();
385 if ( ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ||
386 is_network_admin() ||
387 ! current_user_can( 'manage_options' ) ||
388 ! $this->settings->is_connected() ||
389 empty( $current_screen )
390 ) {
391 return false;
392 }
393 if ( get_option( 'optml_notice_hide_upg', 'no' ) === 'yes' ) {
394 return false;
395 }
396 if ( isset( $current_screen->base ) && $current_screen->base !== 'upload' ) {
397 return false;
398 }
399 $service_data = $this->settings->get( 'service_data' );
400 if ( ! isset( $service_data['plan'] ) ) {
401 return false;
402 }
403 if ( $service_data['plan'] !== 'free' ) {
404 return false;
405 }
406 $visitors_limit = isset( $service_data['visitors_limit'] ) ? (int) $service_data['visitors_limit'] : 0;
407 $visitors_left = isset( $service_data['visitors_left'] ) ? (int) $service_data['visitors_left'] : 0;
408 if ( $visitors_limit === 0 ) {
409 return false;
410 }
411 if ( $visitors_left > 2000 ) {
412 return false;
413 }
414
415 return true;
416 }
417
418 /**
419 * Adds opt in notice.
420 */
421 public function add_notice() {
422 if ( ! $this->should_show_notice() ) {
423 return;
424 }
425 ?>
426 <div class="notice notice-success optml-notice-optin">
427 <p> <?php printf( __( 'Welcome to %1$sOptiMole%2$s, the easiest way to optimize your website images. Your users will enjoy a %3$sfaster%4$s website after you connect it with our service.', 'optimole-wp' ), '<strong>', '</strong>', '<strong>', '</strong>' ); ?></p>
428 <p>
429 <a href="<?php echo esc_url( admin_url( 'upload.php?page=optimole' ) ); ?>"
430 class="button button-primary"><?php _e( 'Connect to OptiMole', 'optimole-wp' ); ?></a>
431 <a class="button"
432 href="<?php echo wp_nonce_url( add_query_arg( [ 'optml_hide_optin' => 'yes' ] ), 'hide_nonce', 'optml_nonce' ); ?>"><?php _e( 'I will do it later', 'optimole-wp' ); ?></a>
433 </p>
434 </div>
435 <?php
436 }
437
438 /**
439 * Add style classes for lazy loading background images.
440 */
441 protected function get_background_lazy_css() {
442
443 $watchers = Optml_Lazyload_Replacer::get_background_lazyload_selectors();
444
445 $css = [];
446 foreach ( $watchers as $selector ) {
447 $css[] = 'html ' . $selector . ':not(.optml-bg-lazyloaded)';
448 }
449 if ( empty( $css ) ) {
450 return '';
451 }
452 $css = implode( ",\n", $css ) . ' { background-image: none !important; } ';
453
454 return strip_tags( $css );
455 }
456
457 /**
458 * Enqueue frontend scripts.
459 */
460 public function frontend_scripts() {
461
462 $bg_css = $this->get_background_lazy_css();
463
464 wp_register_style( 'optm_lazyload_noscript_style', false );
465 wp_enqueue_style( 'optm_lazyload_noscript_style' );
466 wp_add_inline_style( 'optm_lazyload_noscript_style', "html.optml_no_js img[data-opt-src] { display: none !important; } \n " . $bg_css );
467 }
468
469 /**
470 * Maybe redirect to dashboard page.
471 */
472 public function maybe_redirect() {
473
474 if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_optin'] ) && $_GET['optml_hide_optin'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
475 update_option( 'optml_notice_optin', 'yes' );
476 }
477
478 if ( isset( $_GET['optml_nonce'] ) && isset( $_GET['optml_hide_upg'] ) && $_GET['optml_hide_upg'] === 'yes' && wp_verify_nonce( $_GET['optml_nonce'], 'hide_nonce' ) ) {
479 update_option( 'optml_notice_hide_upg', 'yes' );
480 }
481
482 if ( ! get_transient( 'optml_fresh_install' ) ) {
483 return;
484 }
485
486 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
487 return;
488 }
489
490 delete_transient( 'optml_fresh_install' );
491
492 if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) {
493 return;
494 }
495
496 if ( $this->settings->is_connected() ) {
497 return;
498 }
499 wp_safe_redirect( admin_url( 'upload.php?page=optimole' ) );
500 exit;
501 }
502
503 /**
504 * Output Generator tag.
505 */
506 public function generator() {
507 if ( ! $this->settings->is_connected() ) {
508 return;
509 }
510 if ( ! $this->settings->is_enabled() ) {
511 return;
512 }
513 echo '<meta name="generator" content="Optimole ' . esc_attr( OPTML_VERSION ) . '">';
514 }
515
516 /**
517 * Update daily the quota routine.
518 */
519 function daily_sync() {
520
521 $api_key = $this->settings->get( 'api_key' );
522 if ( empty( $api_key ) ) {
523 return;
524 }
525
526 $request = new Optml_Api();
527 $data = $request->get_user_data( $api_key );
528 if ( $data === false || is_wp_error( $data ) ) {
529 return;
530 }
531
532 $this->settings->update( 'service_data', $data );
533
534 }
535
536 /**
537 * Adds cdn url for prefetch.
538 *
539 * @param array $hints Hints array.
540 * @param string $relation_type Type of relation.
541 *
542 * @return array Altered hints array.
543 */
544 public function add_dns_prefetch( $hints, $relation_type ) {
545 if ( 'dns-prefetch' !== $relation_type &&
546 'preconnect' !== $relation_type
547 ) {
548 return $hints;
549 }
550 if ( ! $this->settings->is_connected() ) {
551 return $hints;
552 }
553 if ( ! $this->settings->is_enabled() ) {
554 return $hints;
555 }
556 $hints[] = sprintf( 'https://%s', $this->settings->get_cdn_url() );
557
558 if ( ! $this->settings->use_lazyload() && ! Optml_Manager::should_ignore_image_tags() ) {
559 $hints[] = sprintf( 'https://%s', OPTML_JS_CDN );
560 }
561
562 return $hints;
563 }
564
565 /**
566 * Add the dashboard page.
567 */
568 public function add_dashboard_page() {
569 if ( defined( 'OPTIOMLE_HIDE_ADMIN_AREA' ) && OPTIOMLE_HIDE_ADMIN_AREA ) {
570 return;
571 }
572 add_media_page( 'Optimole', 'Optimole', 'manage_options', 'optimole', [ $this, 'render_dashboard_page' ] );
573 }
574
575 /**
576 * Render dashboard page.
577 */
578 public function render_dashboard_page() {
579 if ( get_option( 'optml_notice_optin', 'no' ) !== 'yes' ) {
580 update_option( 'optml_notice_optin', 'yes' );
581 }
582 ?>
583
584 <div id="optimole-app">
585 <app></app>
586 </div>
587 <?php
588 }
589
590 /**
591 * Enqueue scripts needed for admin functionality.
592 *
593 * @codeCoverageIgnore
594 */
595 public function enqueue() {
596
597 $current_screen = get_current_screen();
598 if ( ! isset( $current_screen->id ) ) {
599 return;
600 }
601 if ( $current_screen->id !== 'media_page_optimole' ) {
602 return;
603 }
604 wp_register_script( OPTML_NAMESPACE . '-admin', OPTML_URL . 'assets/js/bundle' . ( ! OPTML_DEBUG ? '.min' : '' ) . '.js', [], OPTML_VERSION );
605 wp_localize_script( OPTML_NAMESPACE . '-admin', 'optimoleDashboardApp', $this->localize_dashboard_app() );
606 wp_enqueue_script( OPTML_NAMESPACE . '-admin' );
607 }
608
609 /**
610 * Localize the dashboard app.
611 *
612 * @codeCoverageIgnore
613 * @return array
614 */
615 private function localize_dashboard_app() {
616 $api_key = $this->settings->get( 'api_key' );
617 $service_data = $this->settings->get( 'service_data' );
618 $user = get_userdata( get_current_user_id() );
619
620 return [
621 'strings' => $this->get_dashboard_strings(),
622 'assets_url' => OPTML_URL . 'assets/',
623 'connection_status' => empty( $service_data ) ? 'no' : 'yes',
624 'user_status' => isset( $service_data['status'] ) && $service_data['status'] === 'inactive' ? 'inactive' : 'active',
625 'api_key' => $api_key,
626 'root' => untrailingslashit( rest_url( OPTML_NAMESPACE . '/v1' ) ),
627 'nonce' => wp_create_nonce( 'wp_rest' ),
628 'user_data' => $service_data,
629 'remove_latest_images' => defined( 'OPTML_REMOVE_LATEST_IMAGES' ) && constant( 'OPTML_REMOVE_LATEST_IMAGES' ) ? ( OPTML_REMOVE_LATEST_IMAGES ? 'yes' : 'no' ) : 'no',
630 'current_user' => [
631 'email' => $user->user_email,
632 ],
633 'site_settings' => $this->settings->get_site_settings(),
634 'home_url' => home_url(),
635 ];
636 }
637
638 /**
639 * Get all dashboard strings.
640 *
641 * @codeCoverageIgnore
642 * @return array
643 */
644 private function get_dashboard_strings() {
645 return [
646 'optimole' => 'Optimole',
647 'version' => OPTML_VERSION,
648 'terms_menu' => __( 'Terms', 'optimole-wp' ),
649 'privacy_menu' => __( 'Privacy', 'optimole-wp' ),
650 'testdrive_menu' => __( 'Test Optimole', 'optimole-wp' ),
651 'service_details' => __( 'Image optimization service', 'optimole-wp' ),
652 'connect_btn' => __( 'Connect to OptiMole Service', 'optimole-wp' ),
653 'disconnect_btn' => __( 'Disconnect', 'optimole-wp' ),
654 'refresh_stats_cta' => __( 'Refresh stats', 'optimole-wp' ),
655 'updating_stats_cta' => __( 'Updating stats', 'optimole-wp' ),
656 'api_key_placeholder' => __( 'API Key', 'optimole-wp' ),
657 'account_needed_heading' => __( 'Sign-up for API key', 'optimole-wp' ),
658 'invalid_key' => __( 'Invalid API Key', 'optimole-wp' ),
659 'status' => __( 'Status', 'optimole-wp' ),
660 'email_address_label' => __( 'Your email address', 'optimole-wp' ),
661 'register_btn' => __( 'Register & Email API key', 'optimole-wp' ),
662 'step_one_api_title' => __( 'Enter your API key.', 'optimole-wp' ),
663 'step_one_api_desc' => sprintf( __( 'Copy the API key you have received via email or you can get it from %1$s Optimole dashboard%2$s. <br/>', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/" target="_blank"> ', '</a>' ),
664 'step_two_api_title' => __( 'Connect to Optimole.', 'optimole-wp' ),
665 'step_two_api_desc' => __( ' Fill in the upper API key field and connect to Optimole service.', 'optimole-wp' ),
666 'api_exists' => __( 'I already have an API key.', 'optimole-wp' ),
667 'back_to_register' => __( 'Register account', 'optimole-wp' ),
668 'back_to_connect' => __( 'Connect account', 'optimole-wp' ),
669 'error_register' => sprintf( __( 'Error registering account. You can try again %1$shere%2$s ', 'optimole-wp' ), '<a href="https://dashboard.optimole.com/register" target="_blank"> ', '</a>' ),
670 'connected' => __( 'Connected', 'optimole-wp' ),
671 'not_connected' => __( 'Not connected', 'optimole-wp' ),
672 'usage' => __( 'Monthly Usage', 'optimole-wp' ),
673 'quota' => __( 'Monthly Quota', 'optimole-wp' ),
674 'logged_in_as' => __( 'Logged in as', 'optimole-wp' ),
675 'private_cdn_url' => __( 'Images domain', 'optimole-wp' ),
676 'notification_message_register' => __( 'We have sent you an email with the API key. Please copy and paste the key in the field below.', 'optimole-wp' ),
677 'account_needed_title' => sprintf(
678 __( 'In order to get access to free image optimization service you will need an API key from %s.', 'optimole-wp' ),
679 ' <a href="https://dashboard.optimole.com/register" target="_blank">optimole.com</a>'
680 ),
681 'account_needed_subtitle_1' => sprintf(
682 __( 'You will get access to our image optimization service for %1$sFREE%2$s in the limit of %3$s5k%4$s %5$svisitors%6$s per month. ', 'optimole-wp' ),
683 '<strong>',
684 '</strong>',
685 '<strong>',
686 '</strong>',
687 '<a href="https://docs.optimole.com/article/1134-how-optimole-counts-the-number-of-visitors" target="_blank">',
688 '</a>'
689 ),
690 'account_needed_subtitle_3' => sprintf(
691 __( 'Here’s %1$show%2$s to install Optimole on your WordPress site in 3 steps.', 'optimole-wp' ),
692 '<a target="_blank" href="https://docs.optimole.com/article/1173-how-to-get-started-with-optimole-in-just-3-steps">',
693 '</a>'
694 ),
695 'account_needed_subtitle_2' => sprintf(
696 __( 'Bonus, if you dont use a CDN, we got you covered, we will serve the images using CloudFront CD from 200 locations.', 'optimole-wp' )
697 ),
698 'notice_just_activated' => ! $this->settings->is_connected() ?
699 sprintf( __( '%1$sImage optimisation is currently running.%2$s <br/> Your visitors will now view the best image for their device automatically, all served from the Optimole Cloud Service on the fly. You might see for the very first image request being redirected to the original URL while we do the optimization in the background.<br/> You can relax, we\'ll take it from here.', 'optimole-wp' ), '<strong>', '</strong>' )
700 : '',
701 'notice_api_not_working' => __(
702 'It seems there is an issue with your WordPress configuration and the core REST API functionality is not available. This is crucial as Optimole relies on this functionality in order to work.<br/>
703 The root cause might be either a security plugin which blocks this feature or some faulty server configuration which constrain this WordPress feature.You can try to disable any of the security plugins that you use in order to see if the issue persists or ask the hosting company to further investigate.',
704 'optimole-wp'
705 ),
706 'notice_disabled_account' => sprintf( __( 'Your account has been disabled due to exceeding quota. All images are being redirected to the original unoptimized URL. Please %1$supgrade%2$s to re-activate the account.', 'optimole-wp' ), '<a href="https://optimole.com/pricing">', '</a>' ),
707 'dashboard_menu_item' => __( 'Dashboard', 'optimole-wp' ),
708 'settings_menu_item' => __( 'Settings', 'optimole-wp' ),
709 'settings_exclusions_menu_item' => __( 'Exclusions', 'optimole-wp' ),
710 'settings_resize_menu_item' => __( 'Resize', 'optimole-wp' ),
711 'settings_compression_menu_item' => __( 'Compression', 'optimole-wp' ),
712 'advanced_settings_menu_item' => __( 'Advanced', 'optimole-wp' ),
713 'general_settings_menu_item' => __( 'General', 'optimole-wp' ),
714 'lazyload_settings_menu_item' => __( 'Lazyload', 'optimole-wp' ),
715 'watermarks_menu_item' => __( 'Watermark', 'optimole-wp' ),
716 'conflicts_menu_item' => __( 'Possible issues', 'optimole-wp' ),
717 'conflicts' => [
718 'title' => __( 'We might have some possible conflicts with the plugins that you use. In order to benefit from Optimole\'s full potential you will need to address this issues.', 'optimole-wp' ),
719 'message' => __( 'Details', 'optimole-wp' ),
720 'conflict_close' => __( 'I\'ve done this.', 'optimole-wp' ),
721 'no_conflicts_found' => __( 'No conflicts found. We are all peachy now. 🍑', 'optimole-wp' ),
722 ],
723 'upgrade' => [
724 'title' => __( 'Upgrade to Pro', 'optimole-wp' ),
725 'reason_1' => __( 'Priority & Live Chat support', 'optimole-wp' ),
726 'reason_2' => __( 'Extend visits limit', 'optimole-wp' ),
727 'reason_3' => __( 'Custom domain', 'optimole-wp' ),
728 'reason_4' => __( 'Site audit', 'optimole-wp' ),
729 'cta' => __( 'View plans', 'optimole-wp' ),
730 ],
731 'options_strings' => [
732 'add_filter' => __( 'Add filter', 'optimole-wp' ),
733 'admin_bar_desc' => __( 'Show in the WordPress admin bar the available quota from Optimole service.', 'optimole-wp' ),
734 'auto_q_title' => __( 'Auto', 'optimole-wp' ),
735 'cache_desc' => __( 'Clear all cached resources(images,js,css) by Optimole from this site. Useful if you updated them and Optimole shows the old version.', 'optimole-wp' ),
736 'cache_title' => __( 'Clear cached resources', 'optimole-wp' ),
737 'clear_cache' => __( 'Clear cached resources', 'optimole-wp' ),
738 'connect_step_0' => __( 'Connecting your site to the Optimole service.', 'optimole-wp' ),
739 'connect_step_1' => __( 'Checking for possible conflicts.', 'optimole-wp' ),
740 'connect_step_2' => __( 'Inspecting the images from your site.', 'optimole-wp' ),
741 'connect_step_3' => __( 'All done, Optimole is currently optimizing your site.', 'optimole-wp' ),
742 'disabled' => __( 'Disabled', 'optimole-wp' ),
743 'enable_bg_lazyload_desc' => __( 'Lazyload images used as CSS backgrounds.', 'optimole-wp' ),
744 'enable_bg_lazyload_title' => __( 'Enable lazyload for background images', 'optimole-wp' ),
745 'enable_video_lazyload_desc' => __( 'Lazyload iframes/videos', 'optimole-wp' ),
746 'enable_video_lazyload_title' => __( 'Enable lazyload for embedded videos and iframes.', 'optimole-wp' ),
747 'enable_gif_replace_title' => __( 'Enable Gif to Video conversion', 'optimole-wp' ),
748 'enable_report_title' => __( 'Enable error diagnosis tool' ),
749 'enable_report_desc' => __( 'Provides a troubleshooting mechanism which should help you identify any possible issues with your site using Optimole.' ),
750 'enable_image_replace' => __( 'Enable image replacement', 'optimole-wp' ),
751 'enable_lazyload_placeholder_desc' => __( 'Enabling this might affect the user experience in some cases, however it will reduce the number of total requests and page weight. Try it out and see how works best for you!', 'optimole-wp' ),
752 'enable_lazyload_placeholder_title' => __( 'Enable generic lazyload placeholder', 'optimole-wp' ),
753 'enable_network_opt_desc' => __( 'Optimole provides an option to automatically downgrade the image quality when it detects a slower network.', 'optimole-wp' ),
754 'enable_network_opt_title' => __( 'Enable network based optimizations', 'optimole-wp' ),
755 'enable_resize_smart_desc' => __( 'Detects the most interesting section of the image and considers it as the center of the resulting image.', 'optimole-wp' ),
756 'enable_resize_smart_title' => __( 'Enable Smart Cropping', 'optimole-wp' ),
757 'enable_retina_desc' => __( 'Deliver retina ready images to your visitors', 'optimole-wp' ),
758 'enable_retina_title' => __( 'Enable Retina images', 'optimole-wp' ),
759 'enabled' => __( 'Enabled', 'optimole-wp' ),
760 'exclude_class_desc' => __( 'Image tag contains class', 'optimole-wp' ),
761 'exclude_ext_desc' => __( 'Image extension is', 'optimole-wp' ),
762 'exclude_filename_desc' => __( 'Image filename contains', 'optimole-wp' ),
763 'exclude_title_lazyload' => __( 'Don\'t lazyload images if', 'optimole-wp' ),
764 'exclude_title_optimize' => __( 'Don\'t optimize images if', 'optimole-wp' ),
765 'exclude_url_desc' => __( 'Page url contains', 'optimole-wp' ),
766 'filter_class' => __( 'Image class', 'optimole-wp' ),
767 'filter_ext' => __( 'Image extension', 'optimole-wp' ),
768 'filter_filename' => __( 'Image filename', 'optimole-wp' ),
769 'filter_operator_contains' => __( 'contains', 'optimole-wp' ),
770 'filter_operator_is' => __( 'is', 'optimole-wp' ),
771 'filter_url' => __( 'Page URL', 'optimole-wp' ),
772 'gif_replacer_desc' => __( 'Automatically convert GIF images to Video files(MP4 and WebM)', 'optimole-wp' ),
773 'height_field' => __( 'Height', 'optimole-wp' ),
774 'hide' => __( 'Hide', 'optimole-wp' ),
775 'high_q_title' => __( 'High', 'optimole-wp' ),
776 'image_1_label' => __( 'Original', 'optimole-wp' ),
777 'image_2_label' => __( 'Optimized', 'optimole-wp' ),
778 'lazyload_desc' => __( 'We will generate images size based on your visitor\'s screen using javascript and render them without blocking the page execution via lazyload .', 'optimole-wp' ),
779 'scale_desc' => __( 'When this option is off, we disable the automatic scaling of images on lazyload.', 'optimole-wp' ),
780 'low_q_title' => __( 'Low', 'optimole-wp' ),
781 'medium_q_title' => __( 'Medium', 'optimole-wp' ),
782 'no_images_found' => __( 'You dont have any images in your Media Library. Add one and check how the Optimole will perform.', 'optimole-wp' ),
783 'native_desc' => __( 'Use browser native lazyload if supported, fallback to classic lazyload otherwise. When using browser native lazyload the auto scale feature is disabled', 'optimole-wp' ),
784 'option_saved' => __( 'Option saved.', 'optimole-wp' ),
785 'quality_desc' => __( 'Lower image quality might not always be perceived by users and would result in a boost of your loading speed by lowering the page size. Try experimenting with the setting, then click the View sample image link to see what option works best for you.', 'optimole-wp' ),
786 'quality_selected_value' => __( 'Selected value', 'optimole-wp' ),
787 'quality_slider_desc' => __( 'See one sample image which will help you choose the right quality of the compression.', 'optimole-wp' ),
788 'quality_title' => __( 'Image quality', 'optimole-wp' ),
789 'replacer_desc' => __( 'Replace all the image urls from your website with the ones optimized by Optimole.', 'optimole-wp' ),
790 'sample_image_loading' => __( 'Loading a sample image. ', 'optimole-wp' ),
791 'save_changes' => __( 'Save changes', 'optimole-wp' ),
792 'show' => __( 'Show', 'optimole-wp' ),
793 'size_desc' => __( 'We resize all images with sizes greater than the values defined here. Changing this option is not recommended unless large images are not being processed correctly. This does NOT affect the scaling of images on the frontend.', 'optimole-wp' ),
794 'size_title' => __( 'Resize large images original source.', 'optimole-wp' ),
795 'toggle_ab_item' => __( 'Admin bar status', 'optimole-wp' ),
796 'toggle_lazyload' => __( 'Scale images & Lazy load', 'optimole-wp' ),
797 'toggle_scale' => __( 'Scale Images', 'optimole-wp' ),
798 'toggle_native' => __( 'Use native lazyload', 'optimole-wp' ),
799 'on_toggle' => __( 'On', 'optimole-wp' ),
800 'off_toggle' => __( 'Off', 'optimole-wp' ),
801 'view_sample_image' => __( 'View sample image', 'optimole-wp' ),
802 'watch_desc_lazyload' => __( 'You can add each CSS selector on a new line or separated by comma(,).', 'optimole-wp' ),
803 'watch_title_lazyload' => __( 'Lazyload background images for selectors:', 'optimole-wp' ),
804 'width_field' => __( 'Width', 'optimole-wp' ),
805 'toggle_cdn' => __( 'Serve CSS & JS through Optimole', 'optimole-wp' ),
806 'cdn_desc' => __( 'Useful when you have images into CSS/JS files. Optimole wil optimize the images from them and serve the CSS/JS through the CDN.', 'optimole-wp' ),
807 'enable_css_minify_title' => __( 'Minify CSS files', 'optimole-wp' ),
808 'css_minify_desc' => __( 'Once Optimole will serve your CSS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
809 'enable_js_minify_title' => __( 'Minify JS files', 'optimole-wp' ),
810 'js_minify_desc' => __( 'Once Optimole will serve your JS files, it will also minify the files and serve them via CDN.', 'optimole-wp' ),
811 ],
812 'watermarks' => [
813 'image' => __( 'Image', 'optimole-wp' ),
814 'loading_remove_watermark' => __( 'Removing watermark resource ...', 'optimole-wp' ),
815 'max_allowed' => __( 'You are allowed to save maximum 5 images.', 'optimole-wp' ),
816 'list_header' => __( 'Possible watermarks', 'optimole-wp' ),
817 'settings_header' => __( 'Watermarks position settings', 'optimole-wp' ),
818 'no_images_found' => __( 'No images available for watermark. Please upload one.', 'optimole-wp' ),
819 'id' => __( 'ID', 'optimole-wp' ),
820 'name' => __( 'Name', 'optimole-wp' ),
821 'type' => __( 'Type', 'optimole-wp' ),
822 'action' => __( 'Action', 'optimole-wp' ),
823 'upload' => __( 'Upload', 'optimole-wp' ),
824 'add_desc' => __( 'Add new watermark', 'optimole-wp' ),
825 'wm_title' => __( 'Active watermark', 'optimole-wp' ),
826 'wm_desc' => __( 'The active watermark to use from the list of uploaded watermarks.', 'optimole-wp' ),
827 'opacity_field' => __( 'Opacity', 'optimole-wp' ),
828 'opacity_title' => __( 'Watermark opacity', 'optimole-wp' ),
829 'opacity_desc' => __( 'A value between 0 and 100 for the opacity level. If set to 0 it will disable the watermark.', 'optimole-wp' ),
830 'position_title' => __( 'Watermark position', 'optimole-wp' ),
831 'position_desc' => __( 'The place relative to the image where the watermark should be placed.', 'optimole-wp' ),
832 'pos_nowe_title' => __( 'North-West', 'optimole-wp' ),
833 'pos_no_title' => __( 'North', 'optimole-wp' ),
834 'pos_noea_title' => __( 'North-East', 'optimole-wp' ),
835 'pos_we_title' => __( 'West', 'optimole-wp' ),
836 'pos_ce_title' => __( 'Center', 'optimole-wp' ),
837 'pos_ea_title' => __( 'East', 'optimole-wp' ),
838 'pos_sowe_title' => __( 'South-West', 'optimole-wp' ),
839 'pos_so_title' => __( 'South', 'optimole-wp' ),
840 'pos_soea_title' => __( 'South-East', 'optimole-wp' ),
841 'offset_x_field' => __( 'Offset X', 'optimole-wp' ),
842 'offset_y_field' => __( 'Offset Y', 'optimole-wp' ),
843 'offset_title' => __( 'Watermark offset', 'optimole-wp' ),
844 'offset_desc' => __( 'Offset the watermark from set position on X and Y axis. Values can be positive or negative.', 'optimole-wp' ),
845 'scale_field' => __( 'Scale', 'optimole-wp' ),
846 'scale_title' => __( 'Watermark scale', 'optimole-wp' ),
847 'scale_desc' => __( 'A value between 0 and 300 for the scale of the watermark (100 is the original size and 300 is 3x the size) relative to the resulting image size. If set to 0 it will default to the original size.', 'optimole-wp' ),
848 'save_changes' => __( 'Save changes', 'optimole-wp' ),
849 ],
850 'latest_images' => [
851 'image' => __( 'Image', 'optimole-wp' ),
852 'no_images_found' => sprintf( __( 'We are currently optimizing your images. Meanwhile you can visit your %1$shomepage%2$s and check how our plugin performs. ', 'optimole-wp' ), '<a href="' . esc_url( home_url() ) . '" target="_blank" >', '</a>' ),
853 'compression' => __( 'Optimization', 'optimole-wp' ),
854 'loading_latest_images' => __( 'Loading your optimized images...', 'optimole-wp' ),
855 'last' => __( 'Last', 'optimole-wp' ),
856 'optimized_images' => __( 'optimized images', 'optimole-wp' ),
857 'same_size' => __( '🙉 We couldn\'t do better, this image is already optimized at maximum. ', 'optimole-wp' ),
858 'small_optimization' => __( '😬 Not that much, just <strong>{ratio}</strong> smaller.', 'optimole-wp' ),
859 'medium_optimization' => __( '🤓 We are on the right track, <strong>{ratio}</strong> squeezed.', 'optimole-wp' ),
860 'big_optimization' => __( '❤️❤️❤️ Our moles just nailed it, this one is <strong>{ratio}</strong> smaller. ', 'optimole-wp' ),
861 ],
862 ];
863 }
864
865 }
866