PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 2.16.7
Translate and Go multilingual – Automatic AI translation – wpLingua v2.16.7
2.16.7 2.16.6 2.16.5 2.16.4 2.16.3 2.16.2 2.16.1 2.16.0 2.15.2 2.15.1 2.15.0 2.14.3 2.14.2 2.14.1 2.14.0 2.13.1 2.13.0 2.12.3 2.12.2 2.12.1 trunk 1.0.3 1.0.4 1.0.5 1.1.0 All 112 releases
← All changes | inc/admin/option-page.php +882 -635 2.12.22.16.7 View file →
@@ -1,635 +1,882 @@
1 -<?php
2 -
3 -// If this file is called directly, abort.
4 -if ( ! defined( 'WPINC' ) ) {
5 - die;
6 -}
7 -
8 -
9 -/**
10 - * Add wpLingua admin menu when API Key is not registered
11 - *
12 - * @return void
13 - */
14 -function wplng_create_menu_register() {
15 -
16 - add_menu_page(
17 - __( 'wpLingua: Register', 'wplingua' ),
18 - __( 'wpLingua', 'wplingua' ),
19 - 'administrator',
20 - 'wplingua-settings',
21 - 'wplng_option_page_register',
22 - 'dashicons-translation',
23 - 31
24 - );
25 -}
26 -
27 -
28 -/**
29 - * Add wpLingua admin menu when key is registered
30 - *
31 - * @return void
32 - */
33 -function wplng_create_menu() {
34 -
35 - add_menu_page(
36 - __( 'wpLingua: Settings', 'wplingua' ),
37 - __( 'wpLingua', 'wplingua' ),
38 - 'administrator',
39 - 'wplingua-settings',
40 - '',
41 - 'dashicons-translation',
42 - 31
43 - );
44 -
45 - add_submenu_page(
46 - 'wplingua-settings',
47 - __( 'wpLingua: Settings', 'wplingua' ),
48 - __( 'General settings', 'wplingua' ),
49 - 'administrator',
50 - 'wplingua-settings',
51 - 'wplng_option_page_settings'
52 - );
53 -
54 - add_submenu_page(
55 - 'wplingua-settings',
56 - __( 'wpLingua: Switcher', 'wplingua' ),
57 - __( 'Switcher', 'wplingua' ),
58 - 'administrator',
59 - 'wplingua-switcher',
60 - 'wplng_option_page_switcher'
61 - );
62 -
63 - add_submenu_page(
64 - 'wplingua-settings',
65 - __( 'wpLingua: Exclusion', 'wplingua' ),
66 - __( 'Exclusion', 'wplingua' ),
67 - 'administrator',
68 - 'wplingua-exclusions',
69 - 'wplng_option_page_exclusions'
70 - );
71 -
72 - add_submenu_page(
73 - 'wplingua-settings',
74 - __( 'wpLingua: Dictionary', 'wplingua' ),
75 - __( 'Dictionary', 'wplingua' ),
76 - 'administrator',
77 - 'wplingua-dictionary',
78 - 'wplng_option_page_dictionary'
79 - );
80 -
81 - add_submenu_page(
82 - 'wplingua-settings',
83 - __( 'wplingua: Links & Medias', 'wplingua' ),
84 - __( 'Links & Medias', 'wplingua' ),
85 - 'administrator',
86 - 'wplingua-link-media',
87 - 'wplng_option_page_link_media'
88 - );
89 -
90 - add_submenu_page(
91 - 'wplingua-settings',
92 - __( 'wpLingua: Website slugs', 'wplingua' ),
93 - __( 'Website slugs', 'wplingua' ),
94 - 'administrator',
95 - 'edit.php?post_type=wplng_slug',
96 - false
97 - );
98 -
99 - add_submenu_page(
100 - 'wplingua-settings',
101 - __( 'wpLingua: Translations', 'wplingua' ),
102 - __( 'All translations', 'wplingua' ),
103 - 'administrator',
104 - 'edit.php?post_type=wplng_translation',
105 - false
106 - );
107 -}
108 -
109 -
110 -/**
111 - * Register wpLingua settings
112 - *
113 - * @return void
114 - */
115 -function wplng_register_settings() {
116 -
117 - // Option page : Settings and register
118 - register_setting( 'wplng_settings', 'wplng_website_language' );
119 - register_setting( 'wplng_settings', 'wplng_website_flag' );
120 - register_setting( 'wplng_settings', 'wplng_target_languages' );
121 - register_setting( 'wplng_settings', 'wplng_translate_search' );
122 - register_setting( 'wplng_settings', 'wplng_load_in_progress' );
123 - register_setting( 'wplng_settings', 'wplng_sitemap_xml' );
124 - register_setting( 'wplng_settings', 'wplng_sitemap_xsl_override' );
125 - register_setting( 'wplng_settings', 'wplng_hreflang' );
126 - register_setting( 'wplng_settings', 'wplng_browser_language_redirect' );
127 - register_setting( 'wplng_settings', 'wplng_api_key' );
128 - register_setting( 'wplng_settings', 'wplng_request_free_key' );
129 -
130 - // Option page : Exclusions
131 - register_setting( 'wplng_exclusions', 'wplng_excluded_selectors' );
132 - register_setting( 'wplng_exclusions', 'wplng_excluded_url' );
133 -
134 - // Option page : Switcher
135 - register_setting( 'wplng_switcher', 'wplng_insert' );
136 - register_setting( 'wplng_switcher', 'wplng_theme' );
137 - register_setting( 'wplng_switcher', 'wplng_style' );
138 - register_setting( 'wplng_switcher', 'wplng_name_format' );
139 - register_setting( 'wplng_switcher', 'wplng_flags_style' );
140 - register_setting( 'wplng_switcher', 'wplng_custom_css' );
141 -
142 - // Option page : Dictionary
143 - register_setting( 'wplng_dictionary', 'wplng_dictionary_entries' );
144 -
145 - // Option page : Links & Medias
146 - register_setting( 'wplng_link_media', 'wplng_link_media_entries' );
147 -}
148 -
149 -
150 -/**
151 - * Return true if is a wpLingua Admin page
152 - *
153 - * @return bool Is a wpLingua Admin page
154 - */
155 -function wplng_is_wplingua_admin_page() {
156 -
157 - global $pagenow;
158 - global $post;
159 -
160 - /**
161 - * Check if is a wpLingua option page
162 - */
163 -
164 - if ( 'admin.php' === $pagenow
165 - && isset( $_GET['page'] )
166 - && (
167 - $_GET['page'] === 'wplingua-settings'
168 - || $_GET['page'] === 'wplingua-switcher'
169 - || $_GET['page'] === 'wplingua-dictionary'
170 - || $_GET['page'] === 'wplingua-exclusions'
171 - || $_GET['page'] === 'wplingua-link-media'
172 - )
173 - ) {
174 - return true;
175 - }
176 -
177 - /**
178 - * Check if is a translations or slugs admin list
179 - */
180 -
181 - if (
182 - 'edit.php' === $pagenow
183 - && isset( $_GET['post_type'] )
184 - && (
185 - $_GET['post_type'] === 'wplng_translation'
186 - || $_GET['post_type'] === 'wplng_slug'
187 - )
188 - ) {
189 - return true;
190 - }
191 -
192 - /**
193 - * Check if is translations or slugs edition
194 - */
195 -
196 - if (
197 - 'post.php' === $pagenow
198 - && isset( $post->post_type )
199 - && (
200 - $post->post_type === 'wplng_translation'
201 - || $post->post_type === 'wplng_slug'
202 - )
203 - ) {
204 - return true;
205 - }
206 -
207 - return false;
208 -}
209 -
210 -
211 -/**
212 - * Customize the admin footer text displayed on wpLingua option pages.
213 - *
214 - * @param string $text The default footer text.
215 - * @return string The customized footer text for wpLingua pages.
216 - */
217 -function wplng_admin_footer_text( $text ) {
218 -
219 - if ( wplng_is_wplingua_admin_page() ) {
220 -
221 - $text = '<span class="dashicons dashicons-heart"></span> ';
222 -
223 - if ( empty( wplng_get_api_data() ) ) {
224 - $text .= esc_html__( 'Thank you for choosing wpLingua!', 'wplingua' );
225 - } else {
226 - $text .= sprintf(
227 - esc_html__( 'If you like wpLingua please leave us a %1$s rating. A huge thanks!', 'wplingua' ),
228 - '<a href="https://wordpress.org/support/plugin/wplingua/reviews/?filter=5" target="_blank" class="wc-rating-link" aria-label="' . esc_attr__( 'five stars', 'wplingua' ) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
229 - );
230 - }
231 - }
232 -
233 - return $text;
234 -}
235 -
236 -
237 -/**
238 - * Set custom update_footer text on wpLingua options pages
239 - *
240 - * @param string $text The default footer text to be modified.
241 - * @return string The customized footer text for wpLingua pages.
242 - */
243 -function wplng_update_footer( $text ) {
244 -
245 - if ( wplng_is_wplingua_admin_page() ) {
246 - $text = '<a href="https://wplingua.com/" target="_blank">';
247 - $text .= 'wplingua.com';
248 - $text .= '</a> | ';
249 - $text .= '<a href="https://github.com/julien-jacob/wplingua" target="_blank">';
250 - $text .= 'GitHub';
251 - $text .= '</a> | ';
252 - $text .= esc_html__( 'Version', 'wplingua' );
253 - $text .= ' ' . esc_html( WPLNG_PLUGIN_VERSION );
254 - }
255 -
256 - return $text;
257 -}
258 -
259 -
260 -/**
261 - * Add 'Settings' link on wpLingua in the plugin list
262 - *
263 - * @param array $settings
264 - * @return array
265 - */
266 -function wplng_settings_link( $settings ) {
267 -
268 - $url = add_query_arg(
269 - 'page',
270 - 'wplingua-settings',
271 - get_admin_url() . 'admin.php'
272 - );
273 -
274 - $link = '<a href="' . esc_url( $url ) . '">';
275 - $link .= esc_html__( 'Settings', 'wplingua' );
276 - $link .= '</a>';
277 -
278 - $settings[] = $link;
279 -
280 - return $settings;
281 -}
282 -
283 -
284 -/**
285 - * Redirect to the wpLingua settings page upon plugin activation.
286 - *
287 - * @param string $plugin The plugin file path that was activated.
288 - * @return void
289 - */
290 -function wplng_plugin_activation_redirect( $plugin ) {
291 -
292 - if ( ! wp_doing_ajax() && WPLNG_PLUGIN_FILE === $plugin ) {
293 - wp_safe_redirect(
294 - admin_url( 'admin.php?page=wplingua-settings' )
295 - );
296 - exit();
297 - }
298 -}
299 -
300 -
301 -/**
302 - * Display a notice if the plugin is activate but not configured
303 - *
304 - * @return void
305 - */
306 -function wplng_admin_notice_no_key_set() {
307 -
308 - $url = add_query_arg(
309 - 'page',
310 - 'wplingua-settings',
311 - get_admin_url() . 'admin.php'
312 - );
313 -
314 - $html = '<div class="notice notice-info is-dismissible">';
315 - $html .= '<p style="font-weight: 600;">';
316 - $html .= '<span class="dashicons dashicons-translation"></span> ';
317 - $html .= esc_html__( 'wpLingua - Translation solution for multilingual website', 'wplingua' );
318 - $html .= '</p>';
319 - $html .= '<p>';
320 - $html .= esc_html__( 'wpLingua is installed, but not yet configured. You are just a few clicks away from making your website multilingual!', 'wplingua' );
321 - $html .= '<br> ';
322 - $html .= '<a href="' . esc_url( $url ) . '">';
323 - $html .= esc_html__( 'Go to the configuration page', 'wplingua' );
324 - $html .= '</a>';
325 - $html .= '</p>';
326 - $html .= '</div>';
327 -
328 - echo $html;
329 -}
330 -
331 -
332 -/**
333 - * Get the list of activated incompatible plugins
334 - *
335 - * @return array [Plugin name => Plugin file]
336 - */
337 -function wplng_get_incompatible_plugins() {
338 -
339 - if ( ! function_exists( 'is_plugin_active' ) ) {
340 - require_once ABSPATH . '/wp-admin/includes/plugin.php';
341 - }
342 -
343 - /**
344 - * Get incompatible plugins
345 - */
346 -
347 - $incompatible_list = array(
348 - 'Automatic Translator' => 'auto-translate/auto-translate.php',
349 - 'Autoglot' => 'autoglot/autoglot.php',
350 - 'clonable' => 'clonable/clonable-wp.php',
351 - 'ConveyThis Translate' => 'conveythis-translate/index.php',
352 - 'Falang' => 'falang/falang.php',
353 - 'Google Translator' => 'google-language-translator/google-language-translator.php',
354 - 'Google Website Translator' => 'google-website-translator/google-website-translator.php',
355 - 'Gtranslate' => 'gtranslate/gtranslate.php',
356 - 'linguise' => 'linguise/linguise.php',
357 - 'Lokalise' => 'lokalise/lokalise.php',
358 - 'localizejs' => 'localizejs/localizejs.php',
359 - 'Multilanguage' => 'multilanguage/multilanguage.php',
360 - 'Polylang' => 'polylang/polylang.php',
361 - 'TranslatePress' => 'translatepress-multilingual/index.php',
362 - 'WEGLOT' => 'weglot/weglot.php',
363 - 'WPML' => 'sitepress-multilingual-cms/sitepress.php',
364 - 'WP Multilang' => 'wp-multilang/wp-multilang.php',
365 - );
366 -
367 - $incompatible_detected = array();
368 -
369 - foreach ( $incompatible_list as $name => $file ) {
370 - if ( is_plugin_active( $file ) ) {
371 - $incompatible_detected[ $name ] = $file;
372 - }
373 - }
374 -
375 - return $incompatible_detected;
376 -}
377 -
378 -
379 -/**
380 - * Display a notice if an incompatible plugin is detected.
381 - *
382 - * @return void|string Outputs the admin notice or returns nothing if no conflicts are found.
383 - */
384 -function wplng_admin_notice_incompatible_plugin() {
385 -
386 - $incompatible_plugins = wplng_get_incompatible_plugins();
387 -
388 - if ( empty( $incompatible_plugins ) ) {
389 - return;
390 - }
391 -
392 - $html = '<div ';
393 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
394 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
395 - $html .= '<p style="font-weight: 600;">';
396 - $html .= '<span class="dashicons dashicons-translation"></span> ';
397 - $html .= esc_html__( 'wpLingua - Incompatible plugin detected', 'wplingua' );
398 - $html .= '</p>';
399 - $html .= '<p>';
400 - $html .= esc_html__( 'You have several translation plugins. This may result in unpredictable or incorrect behavior. For best results, use only one translation plugin at a time. These plugins can cause problems with wpLingua: ', 'wplingua' );
401 -
402 - $html .= '<ul style="list-style: disc; margin-left: 15px;">';
403 - foreach ( $incompatible_plugins as $name => $file ) {
404 -
405 - $deactivate_url = wp_nonce_url(
406 - add_query_arg(
407 - array(
408 - 'action' => 'deactivate',
409 - 'plugin' => urlencode( $file ),
410 - ),
411 - get_admin_url() . 'plugins.php'
412 - ),
413 - 'deactivate-plugin_' . $file
414 - );
415 -
416 - $deactivate_title = sprintf(
417 - esc_html__( 'Deactivate plugin: %1$s', 'wplingua' ),
418 - $name
419 - );
420 -
421 - $html .= '<li>';
422 - $html .= '<strong>' . esc_html( $name ) . '</strong> | ';
423 - $html .= '<a ';
424 - $html .= 'href="' . esc_url( $deactivate_url ) . '" ';
425 - $html .= 'title="' . esc_attr( $deactivate_title ) . '">';
426 - $html .= esc_html__( 'Deactivate', 'wplingua' );
427 - $html .= '</a>';
428 - $html .= '</li>';
429 - }
430 - $html .= '</ul>';
431 - $html .= '</p>';
432 -
433 - $url_manage_plugins = add_query_arg(
434 - 'plugin_status',
435 - 'active',
436 - get_admin_url() . 'plugins.php'
437 - );
438 -
439 - $html .= '<a ';
440 - $html .= 'href="' . esc_url( $url_manage_plugins ) . '" ';
441 - $html .= 'class="button button-primary" ';
442 - $html .= 'style="margin-bottom: 10px;">';
443 - $html .= esc_html__( 'Manage active plugins', 'wplingua' );
444 - $html .= '</a>';
445 -
446 - $html .= '</div>'; // End .notice
447 -
448 - echo $html;
449 -}
450 -
451 -
452 -/**
453 - * Display a notice if is a multisite
454 - *
455 - * @return void|string Outputs the admin notice if applicable, or returns void if no action is needed.
456 - */
457 -function wplng_admin_notice_incompatible_multisite() {
458 -
459 - if ( ! is_multisite() ) {
460 - return;
461 - }
462 -
463 - $html = '<div ';
464 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
465 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
466 - $html .= '<p style="font-weight: 600;">';
467 - $html .= '<span class="dashicons dashicons-translation"></span> ';
468 - $html .= esc_html__( 'wpLingua - Incompatible with multisite', 'wplingua' );
469 - $html .= '</p>';
470 - $html .= '<p>';
471 - $html .= esc_html__( 'wpLingua is not compatible with multisite.', 'wplingua' );
472 - $html .= '</p>';
473 - $html .= '</div>'; // End .notice
474 -
475 - echo $html;
476 -}
477 -
478 -
479 -/**
480 - * Display a notice if the WordPress installed in a subfolder
481 - *
482 - * @return void|string Outputs the admin notice if applicable, or returns void if no notice is needed.
483 - */
484 -function wplng_admin_notice_incompatible_sub_folder() {
485 -
486 - if ( ! wplng_website_in_sub_folder() ) {
487 - return;
488 - }
489 -
490 - $html = '<div ';
491 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
492 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
493 - $html .= '<p style="font-weight: 600;">';
494 - $html .= '<span class="dashicons dashicons-translation"></span> ';
495 - $html .= esc_html__( 'wpLingua - Incompatible with WordPress installed in a subfolder', 'wplingua' );
496 - $html .= '</p>';
497 - $html .= '<p>';
498 - $html .= esc_html__( 'wpLingua is not compatible with WordPress installed in a subfolder.', 'wplingua' );
499 - $html .= '</p>';
500 - $html .= '</div>'; // End .notice
501 -
502 - echo $html;
503 -}
504 -
505 -
506 -/**
507 - * Display a notice if the PHP version is incompatible
508 - *
509 - * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
510 - */
511 -function wplng_admin_notice_incompatible_php_version() {
512 -
513 - if ( version_compare( PHP_VERSION, WPLNG_PHP_MIN_VERSION ) >= 0 ) {
514 - return;
515 - }
516 -
517 - $html = '<div ';
518 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
519 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
520 - $html .= '<p style="font-weight: 600;">';
521 - $html .= '<span class="dashicons dashicons-translation"></span> ';
522 - $html .= esc_html__( 'wpLingua - Incompatible PHP version', 'wplingua' );
523 - $html .= '</p>';
524 - $html .= '<p>';
525 - $html .= esc_html__( 'wpLingua is not compatible with your PHP version. wpLingua requires PHP 7.4 or higher.', 'wplingua' );
526 - $html .= '</p>';
527 - $html .= '</div>'; // End .notice
528 -
529 - echo $html;
530 -}
531 -
532 -
533 -/**
534 - * Check if the HTACCESS file contain code of another plugin who break translated pages
535 - *
536 - * @return bool HTACCESS file is valid for wpLingua
537 - */
538 -function wplng_htaccess_is_valid() {
539 -
540 - $htaccess_path = ABSPATH . '.htaccess';
541 -
542 - if ( ! file_exists( $htaccess_path ) ) {
543 - return true;
544 - }
545 -
546 - $htaccess_content = file_get_contents( $htaccess_path );
547 -
548 - return ! (
549 - strpos( $htaccess_content, 'GTranslate' ) !== false
550 - || strpos( $htaccess_content, 'LINGUISE' ) !== false
551 - );
552 -}
553 -
554 -
555 -/**
556 - * Display a notice if the HTACCESS file is incompatible
557 - *
558 - * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
559 - */
560 -function wplng_admin_notice_incompatible_htaccess() {
561 -
562 - $htaccess_path = ABSPATH . '.htaccess';
563 -
564 - if ( ! file_exists( $htaccess_path ) ) {
565 - return;
566 - }
567 -
568 - $htaccess_content = file_get_contents( $htaccess_path );
569 - $message = '';
570 -
571 - if ( strpos( $htaccess_content, 'GTranslate' ) !== false ) {
572 - $message .= '### BEGIN GTranslate config ###' . PHP_EOL;
573 - $message .= '...' . PHP_EOL;
574 - $message .= '### END GTranslate config ###';
575 - } elseif ( strpos( $htaccess_content, 'LINGUISE' ) !== false ) {
576 - $message .= '#### LINGUISE DO NOT EDIT ####' . PHP_EOL;
577 - $message .= '...' . PHP_EOL;
578 - $message .= '#### LINGUISE DO NOT EDIT END ####';
579 - }
580 -
581 - if ( ! empty( $message ) ) {
582 -
583 - $html = '<div ';
584 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
585 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
586 - $html .= '<p style="font-weight: 600;">';
587 - $html .= '<span class="dashicons dashicons-translation"></span> ';
588 - $html .= esc_html__( 'wpLingua - Incompatible HTACCESS file', 'wplingua' );
589 - $html .= '</p>';
590 - $html .= '<p>';
591 - $html .= esc_html__( 'It seems that a plugin was incorrectly deactivated and corrupted the site\'s HTACCESS file, preventing the correct redirection of translated pages. Please edit the ".htaccess" file located at the root of the site and delete the lines between :', 'wplingua' );
592 - $html .= '<pre style="border: 1px solid #c3c4c7; padding: 8px; background-color: rgba(0,0,0,.05);">';
593 - $html .= $message;
594 - $html .= '</pre>';
595 - $html .= '</p>';
596 - $html .= '</div>'; // End .notice
597 -
598 - echo $html;
599 - }
600 -}
601 -
602 -
603 -/**
604 - * Display a notice if the permalink structure is set to Plain
605 - *
606 - * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
607 - */
608 -function wplng_admin_notice_incompatible_plain_permalink() {
609 -
610 - if ( ! empty( get_option( 'permalink_structure' ) ) ) {
611 - return;
612 - }
613 -
614 - $url_permalinks = get_admin_url() . 'options-permalink.php';
615 -
616 - $html = '<div ';
617 - $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
618 - $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
619 - $html .= '<p style="font-weight: 600;">';
620 - $html .= '<span class="dashicons dashicons-translation"></span> ';
621 - $html .= esc_html__( 'wpLingua - Incompatible permalink structure', 'wplingua' );
622 - $html .= '</p>';
623 - $html .= '<p>';
624 - $html .= esc_html__( 'wpLingua is not compatible with the "Plain" permalink structure. Please update your permalink settings to use "Post name" or "Custom Structure".', 'wplingua' );
625 - $html .= '</p>';
626 - $html .= '<a ';
627 - $html .= 'href="' . esc_url( $url_permalinks ) . '" ';
628 - $html .= 'class="button button-primary" ';
629 - $html .= 'style="margin-bottom: 10px;">';
630 - $html .= esc_html__( 'Manage permalink settings', 'wplingua' );
631 - $html .= '</a>';
632 - $html .= '</div>'; // End .notice
633 -
634 - echo $html;
635 -}
1 +<?php
2 +
3 +// If this file is called directly, abort.
4 +if ( ! defined( 'WPINC' ) ) {
5 + die;
6 +}
7 +
8 +
9 +/**
10 + * Register wpLingua settings
11 + *
12 + * @return void
13 + */
14 +function wplng_register_settings() {
15 +
16 + // Option page : Settings and register
17 + register_setting( 'wplng_settings', 'wplng_website_language' );
18 + register_setting( 'wplng_settings', 'wplng_website_flag' );
19 + register_setting( 'wplng_settings', 'wplng_target_languages' );
20 + register_setting( 'wplng_settings', 'wplng_translate_search' );
21 + register_setting( 'wplng_settings', 'wplng_load_in_progress' );
22 + register_setting( 'wplng_settings', 'wplng_sitemap_xml' );
23 + register_setting( 'wplng_settings', 'wplng_sitemap_xsl_override' );
24 + register_setting( 'wplng_settings', 'wplng_hreflang' );
25 + register_setting( 'wplng_settings', 'wplng_browser_language_redirect' );
26 + register_setting( 'wplng_settings', 'wplng_api_key' );
27 + register_setting( 'wplng_settings', 'wplng_request_free_key' );
28 +
29 + // Option page : Exclusions
30 + register_setting( 'wplng_exclusions', 'wplng_excluded_selectors' );
31 + register_setting( 'wplng_exclusions', 'wplng_excluded_url' );
32 +
33 + // Option page : Switcher
34 + register_setting( 'wplng_switcher', 'wplng_insert' );
35 + register_setting( 'wplng_switcher', 'wplng_theme' );
36 + register_setting( 'wplng_switcher', 'wplng_style' );
37 + register_setting( 'wplng_switcher', 'wplng_name_format' );
38 + register_setting( 'wplng_switcher', 'wplng_flags_style' );
39 + register_setting( 'wplng_switcher', 'wplng_custom_css' );
40 +
41 + // Option page : Dictionary
42 + register_setting( 'wplng_dictionary', 'wplng_dictionary_entries' );
43 +
44 + // Option page : Links & Medias
45 + register_setting( 'wplng_link_media', 'wplng_link_media_entries' );
46 +}
47 +
48 +
49 +/**
50 + * Determine whether the current page is one of
51 + * wpLingua's hidden option pages.
52 + */
53 +function wplng_is_wplingua_settings_page() {
54 +
55 + if ( empty( $_GET['page'] ) ) {
56 + return false;
57 + }
58 +
59 + return in_array(
60 + sanitize_key( $_GET['page'] ),
61 + array(
62 + 'wplingua-settings',
63 + 'wplingua-switcher',
64 + 'wplingua-exclusions',
65 + 'wplingua-dictionary',
66 + 'wplingua-link-media',
67 + ),
68 + true
69 + );
70 +}
71 +
72 +
73 +/**
74 + * Return true if is a wpLingua Admin page
75 + *
76 + * @return bool Is a wpLingua Admin page
77 + */
78 +function wplng_is_wplingua_admin_page() {
79 +
80 + global $pagenow;
81 + global $post;
82 +
83 + /**
84 + * Check if is a wpLingua option page
85 + */
86 +
87 + if ( 'admin.php' === $pagenow
88 + && isset( $_GET['page'] )
89 + && (
90 + $_GET['page'] === 'wplingua-settings'
91 + || $_GET['page'] === 'wplingua-switcher'
92 + || $_GET['page'] === 'wplingua-dictionary'
93 + || $_GET['page'] === 'wplingua-exclusions'
94 + || $_GET['page'] === 'wplingua-link-media'
95 + )
96 + ) {
97 + return true;
98 + }
99 +
100 + /**
101 + * Check if is a translations or slugs admin list
102 + */
103 +
104 + if (
105 + 'edit.php' === $pagenow
106 + && isset( $_GET['post_type'] )
107 + && (
108 + $_GET['post_type'] === 'wplng_translation'
109 + || $_GET['post_type'] === 'wplng_slug'
110 + )
111 + ) {
112 + return true;
113 + }
114 +
115 + /**
116 + * Check if is translations or slugs edition
117 + */
118 +
119 + if (
120 + 'post.php' === $pagenow
121 + && isset( $post->post_type )
122 + && (
123 + $post->post_type === 'wplng_translation'
124 + || $post->post_type === 'wplng_slug'
125 + )
126 + ) {
127 + return true;
128 + }
129 +
130 + return false;
131 +}
132 +
133 +
134 +/**
135 + * Add wpLingua admin menu when API Key is not registered
136 + *
137 + * @return void
138 + */
139 +function wplng_create_menu_register() {
140 +
141 + add_menu_page(
142 + __( 'wpLingua: Register', 'wplingua' ),
143 + __( 'wpLingua', 'wplingua' ),
144 + 'edit_posts',
145 + 'wplingua-settings',
146 + 'wplng_option_page_register',
147 + 'dashicons-translation',
148 + 31
149 + );
150 +}
151 +
152 +
153 +/**
154 + * Create wpLingua admin menu.
155 + */
156 +function wplng_create_menu() {
157 +
158 + /*
159 + * Main wpLingua menu
160 + */
161 + add_menu_page(
162 + __( 'wpLingua: Settings', 'wplingua' ),
163 + __( 'wpLingua', 'wplingua' ),
164 + 'edit_posts',
165 + 'wplingua-settings',
166 + '',
167 + 'dashicons-translation',
168 + 31
169 + );
170 +
171 +
172 + /*
173 + * Settings
174 + *
175 + * This is the visible entry used as the parent
176 + * for all wpLingua option pages.
177 + */
178 + add_submenu_page(
179 + 'wplingua-settings',
180 + __( 'wpLingua: Settings', 'wplingua' ),
181 + __( 'Settings', 'wplingua' ),
182 + 'edit_posts',
183 + 'wplingua-settings',
184 + 'wplng_option_page_settings'
185 + );
186 +
187 +
188 + /*
189 + * Hidden option pages
190 + *
191 + * These pages remain registered as children of
192 + * wplingua-settings, but their menu entries are
193 + * hidden later with CSS.
194 + */
195 +
196 + add_submenu_page(
197 + 'wplingua-settings',
198 + __( 'wpLingua: Switcher', 'wplingua' ),
199 + __( 'Switcher', 'wplingua' ),
200 + 'edit_posts',
201 + 'wplingua-switcher',
202 + 'wplng_option_page_switcher'
203 + );
204 +
205 + add_submenu_page(
206 + 'wplingua-settings',
207 + __( 'wpLingua: Exclusion', 'wplingua' ),
208 + __( 'Exclusion', 'wplingua' ),
209 + 'edit_posts',
210 + 'wplingua-exclusions',
211 + 'wplng_option_page_exclusions'
212 + );
213 +
214 + add_submenu_page(
215 + 'wplingua-settings',
216 + __( 'wpLingua: Dictionary', 'wplingua' ),
217 + __( 'Dictionary', 'wplingua' ),
218 + 'edit_posts',
219 + 'wplingua-dictionary',
220 + 'wplng_option_page_dictionary'
221 + );
222 +
223 + add_submenu_page(
224 + 'wplingua-settings',
225 + __( 'wplingua: Links & Medias', 'wplingua' ),
226 + __( 'Links & Medias', 'wplingua' ),
227 + 'edit_posts',
228 + 'wplingua-link-media',
229 + 'wplng_option_page_link_media'
230 + );
231 +
232 +
233 + /*
234 + * Visible custom post type pages
235 + */
236 +
237 + add_submenu_page(
238 + 'wplingua-settings',
239 + __( 'wpLingua: Website slugs', 'wplingua' ),
240 + __( 'Website slugs', 'wplingua' ),
241 + 'edit_posts',
242 + 'edit.php?post_type=wplng_slug',
243 + false
244 + );
245 +
246 + add_submenu_page(
247 + 'wplingua-settings',
248 + __( 'wpLingua: Translations', 'wplingua' ),
249 + __( 'All translations', 'wplingua' ),
250 + 'edit_posts',
251 + 'edit.php?post_type=wplng_translation',
252 + false
253 + );
254 +}
255 +
256 +
257 +/**
258 + * Keep wpLingua as the active parent menu
259 + * on all wpLingua option pages.
260 + *
261 + * @param string $parent_file The current parent menu file.
262 + *
263 + * @return string The parent menu file.
264 + */
265 +function wplng_option_page_parent_file( $parent_file ) {
266 +
267 + if ( wplng_is_wplingua_settings_page() ) {
268 + return 'wplingua-settings';
269 + }
270 +
271 + return $parent_file;
272 +}
273 +
274 +
275 +/**
276 + * Keep "Settings" as the active submenu
277 + * on all wpLingua option pages.
278 + *
279 + * @param string $submenu_file The current submenu file.
280 + *
281 + * @return string The submenu file.
282 + */
283 +function wplng_option_page_submenu_file( $submenu_file ) {
284 +
285 + if ( wplng_is_wplingua_settings_page() ) {
286 + return 'wplingua-settings';
287 + }
288 +
289 + return $submenu_file;
290 +}
291 +
292 +
293 +/**
294 + * Hide the option pages from the wpLingua submenu.
295 + *
296 + * The pages themselves remain registered in WordPress.
297 + * Therefore, they are still accessible directly by URL
298 + * and remain correctly associated with the wpLingua menu.
299 + */
300 +function wplng_option_page_hide_submenu() {
301 +
302 + $css = '<style>';
303 + $css .= '#adminmenu .wp-submenu a[href*="page=wplingua-switcher"], ';
304 + $css .= '#adminmenu .wp-submenu a[href*="page=wplingua-exclusions"], ';
305 + $css .= '#adminmenu .wp-submenu a[href*="page=wplingua-dictionary"], ';
306 + $css .= '#adminmenu .wp-submenu a[href*="page=wplingua-link-media"] {';
307 + $css .= 'display: none;';
308 + $css .= '}';
309 + $css .= '</style>';
310 +
311 + echo $css;
312 +}
313 +
314 +
315 +
316 +/**
317 + * Generates the navigation menu for wpLingua option pages.
318 + *
319 + * Creates a list of links to the different wpLingua settings pages,
320 + * highlighting the current page with the `button-primary` class.
321 + *
322 + * @param bool $display_none Whether to hide the menu by default.
323 + *
324 + * @return string The HTML markup for the option pages navigation menu.
325 + */
326 +function wplng_option_page_settings_menu( $display_none = false ) {
327 +
328 + $data = array(
329 + array(
330 + 'page' => 'wplingua-settings',
331 + 'title' => __( 'General settings', 'wplingua' ),
332 + 'dashicon' => 'dashicons-admin-generic',
333 + ),
334 + array(
335 + 'page' => 'wplingua-switcher',
336 + 'title' => __( 'Language switcher', 'wplingua' ),
337 + 'dashicon' => 'dashicons-admin-settings',
338 + ),
339 + array(
340 + 'page' => 'wplingua-exclusions',
341 + 'title' => __( 'Exclusion', 'wplingua' ),
342 + 'dashicon' => 'dashicons-filter',
343 + ),
344 + array(
345 + 'page' => 'wplingua-dictionary',
346 + 'title' => __( 'Dictionary', 'wplingua' ),
347 + 'dashicon' => 'dashicons-book',
348 + ),
349 + array(
350 + 'page' => 'wplingua-link-media',
351 + 'title' => __( 'Links & Medias', 'wplingua' ),
352 + 'dashicon' => 'dashicons-format-gallery',
353 + ),
354 + );
355 +
356 + $style = '';
357 + if ( $display_none === true ) {
358 + $style = ' style="display: none;"';
359 + }
360 +
361 + $html = '<div class="wplng-option-page-menu"' . $style . '>';
362 + $html .= '<ul>';
363 +
364 + foreach ( $data as $value ) {
365 +
366 + $url = add_query_arg(
367 + 'page',
368 + $value['page'],
369 + admin_url( 'admin.php' )
370 + );
371 +
372 + $class_attr = '';
373 + if ( $_GET['page'] === $value['page'] ) {
374 + $class_attr = ' button-primary';
375 + }
376 +
377 + $html .= '<li>';
378 + $html .= '<a href="' . esc_url( $url ) . '" class="button' . $class_attr . '">';
379 + $html .= '<span class="dashicons ' . esc_attr( $value['dashicon'] ) . '">';
380 + $html .= '</span> ';
381 + $html .= esc_html( $value['title'] );
382 + $html .= '</a>';
383 + $html .= '</li>';
384 + }
385 +
386 + $html .= '</ul>';
387 + $html .= '</div>'; // End .wplng-option-page-menu
388 +
389 + return $html;
390 +}
391 +
392 +
393 +/**
394 + * Customize the admin footer text displayed on wpLingua option pages.
395 + *
396 + * @param string $text The default footer text.
397 + * @return string The customized footer text for wpLingua pages.
398 + */
399 +function wplng_admin_footer_text( $text ) {
400 +
401 + if ( wplng_is_wplingua_admin_page() ) {
402 +
403 + $text = '<span class="dashicons dashicons-heart"></span> ';
404 +
405 + if ( empty( wplng_get_api_data() ) ) {
406 + $text .= esc_html__( 'Thank you for choosing wpLingua!', 'wplingua' );
407 + } else {
408 + $text .= sprintf(
409 + esc_html__( 'If you like wpLingua please leave us a %1$s rating. A huge thanks!', 'wplingua' ),
410 + '<a href="https://wordpress.org/support/plugin/wplingua/reviews/?filter=5" target="_blank" rel="noopener noreferrer" aria-label="' . esc_attr__( 'five stars', 'wplingua' ) . '">&#9733;&#9733;&#9733;&#9733;&#9733;</a>'
411 + );
412 + }
413 + }
414 +
415 + return $text;
416 +}
417 +
418 +
419 +/**
420 + * Set custom update_footer text on wpLingua options pages
421 + *
422 + * @param string $text The default footer text to be modified.
423 + * @return string The customized footer text for wpLingua pages.
424 + */
425 +function wplng_update_footer( $text ) {
426 +
427 + if ( wplng_is_wplingua_admin_page() ) {
428 + $text = '<a href="https://wplingua.com/" target="_blank" rel="noopener noreferrer">';
429 + $text .= 'wplingua.com';
430 + $text .= '</a> | ';
431 + $text .= '<a href="https://github.com/julien-jacob/wplingua" target="_blank" rel="noopener noreferrer">';
432 + $text .= 'GitHub';
433 + $text .= '</a> | ';
434 + $text .= esc_html__( 'Version', 'wplingua' );
435 + $text .= ' ' . esc_html( WPLNG_PLUGIN_VERSION );
436 + }
437 +
438 + return $text;
439 +}
440 +
441 +
442 +/**
443 + * Add 'Settings' link on wpLingua in the plugin list
444 + *
445 + * @param array $settings
446 + * @return array
447 + */
448 +function wplng_settings_link( $settings ) {
449 +
450 + $url = add_query_arg(
451 + 'page',
452 + 'wplingua-settings',
453 + get_admin_url() . 'admin.php'
454 + );
455 +
456 + $link = '<a href="' . esc_url( $url ) . '">';
457 + $link .= esc_html__( 'Settings', 'wplingua' );
458 + $link .= '</a>';
459 +
460 + $settings[] = $link;
461 +
462 + return $settings;
463 +}
464 +
465 +
466 +/**
467 + * Redirect to the wpLingua settings page upon plugin activation.
468 + *
469 + * @param string $plugin The plugin file path that was activated.
470 + * @return void
471 + */
472 +function wplng_plugin_activation_redirect( $plugin ) {
473 +
474 + if ( ! wp_doing_ajax() && WPLNG_PLUGIN_FILE === $plugin ) {
475 + wp_safe_redirect(
476 + admin_url( 'admin.php?page=wplingua-settings' )
477 + );
478 + exit();
479 + }
480 +}
481 +
482 +
483 +/**
484 + * Display a notice if the plugin is activate but not configured
485 + *
486 + * @return void
487 + */
488 +function wplng_admin_notice_no_key_set() {
489 +
490 + $url = add_query_arg(
491 + 'page',
492 + 'wplingua-settings',
493 + get_admin_url() . 'admin.php'
494 + );
495 +
496 + $html = '<div class="notice notice-info is-dismissible">';
497 + $html .= '<p style="font-weight: 600;">';
498 + $html .= '<span class="dashicons dashicons-translation"></span> ';
499 + $html .= esc_html__( 'wpLingua - Translation solution for multilingual website', 'wplingua' );
500 + $html .= '</p>';
501 + $html .= '<p>';
502 + $html .= esc_html__( 'wpLingua is installed, but not yet configured. You are just a few clicks away from making your website multilingual!', 'wplingua' );
503 + $html .= '<br> ';
504 + $html .= '<a href="' . esc_url( $url ) . '">';
505 + $html .= esc_html__( 'Go to the configuration page', 'wplingua' );
506 + $html .= '</a>';
507 + $html .= '</p>';
508 + $html .= '</div>';
509 +
510 + echo $html;
511 +}
512 +
513 +
514 +/**
515 + * Get the list of activated incompatible plugins
516 + *
517 + * @return array [Plugin name => Plugin file]
518 + */
519 +function wplng_get_incompatible_plugins() {
520 +
521 + if ( ! function_exists( 'is_plugin_active' ) ) {
522 + require_once ABSPATH . '/wp-admin/includes/plugin.php';
523 + }
524 +
525 + /**
526 + * Get incompatible plugins
527 + */
528 +
529 + $incompatible_list = array(
530 + 'Automatic Translator' => 'auto-translate/auto-translate.php',
531 + 'Autoglot' => 'autoglot/autoglot.php',
532 + 'clonable' => 'clonable/clonable-wp.php',
533 + 'ConveyThis Translate' => 'conveythis-translate/index.php',
534 + 'Falang' => 'falang/falang.php',
535 + 'Google Translator' => 'google-language-translator/google-language-translator.php',
536 + 'Google Website Translator' => 'google-website-translator/google-website-translator.php',
537 + 'Gtranslate' => 'gtranslate/gtranslate.php',
538 + 'linguise' => 'linguise/linguise.php',
539 + 'Lokalise' => 'lokalise/lokalise.php',
540 + 'localizejs' => 'localizejs/localizejs.php',
541 + 'Multilanguage' => 'multilanguage/multilanguage.php',
542 + 'Polylang' => 'polylang/polylang.php',
543 + 'TranslatePress' => 'translatepress-multilingual/index.php',
544 + 'WEGLOT' => 'weglot/weglot.php',
545 + 'WPML' => 'sitepress-multilingual-cms/sitepress.php',
546 + 'WP Multilang' => 'wp-multilang/wp-multilang.php',
547 + );
548 +
549 + $incompatible_detected = array();
550 +
551 + foreach ( $incompatible_list as $name => $file ) {
552 + if ( is_plugin_active( $file ) ) {
553 + $incompatible_detected[ $name ] = $file;
554 + }
555 + }
556 +
557 + return $incompatible_detected;
558 +}
559 +
560 +
561 +/**
562 + * Display a notice if an incompatible plugin is detected.
563 + *
564 + * @return void|string Outputs the admin notice or returns nothing if no conflicts are found.
565 + */
566 +function wplng_admin_notice_incompatible_plugin() {
567 +
568 + $incompatible_plugins = wplng_get_incompatible_plugins();
569 +
570 + if ( empty( $incompatible_plugins ) ) {
571 + return;
572 + }
573 +
574 + $html = '<div ';
575 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
576 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
577 + $html .= '<p style="font-weight: 600;">';
578 + $html .= '<span class="dashicons dashicons-translation"></span> ';
579 + $html .= esc_html__( 'wpLingua - Incompatible plugin detected', 'wplingua' );
580 + $html .= '</p>';
581 + $html .= '<p>';
582 + $html .= esc_html__( 'You have several translation plugins. This may result in unpredictable or incorrect behavior. For best results, use only one translation plugin at a time. These plugins can cause problems with wpLingua: ', 'wplingua' );
583 +
584 + $html .= '<ul style="list-style: disc; margin-left: 15px;">';
585 + foreach ( $incompatible_plugins as $name => $file ) {
586 +
587 + $deactivate_url = wp_nonce_url(
588 + add_query_arg(
589 + array(
590 + 'action' => 'deactivate',
591 + 'plugin' => urlencode( $file ),
592 + ),
593 + get_admin_url() . 'plugins.php'
594 + ),
595 + 'deactivate-plugin_' . $file
596 + );
597 +
598 + $deactivate_title = sprintf(
599 + esc_html__( 'Deactivate plugin: %1$s', 'wplingua' ),
600 + $name
601 + );
602 +
603 + $html .= '<li>';
604 + $html .= '<strong>' . esc_html( $name ) . '</strong> | ';
605 + $html .= '<a ';
606 + $html .= 'href="' . esc_url( $deactivate_url ) . '" ';
607 + $html .= 'title="' . esc_attr( $deactivate_title ) . '">';
608 + $html .= esc_html__( 'Deactivate', 'wplingua' );
609 + $html .= '</a>';
610 + $html .= '</li>';
611 + }
612 + $html .= '</ul>';
613 + $html .= '</p>';
614 +
615 + $url_manage_plugins = add_query_arg(
616 + 'plugin_status',
617 + 'active',
618 + get_admin_url() . 'plugins.php'
619 + );
620 +
621 + $html .= '<a ';
622 + $html .= 'href="' . esc_url( $url_manage_plugins ) . '" ';
623 + $html .= 'class="button button-primary" ';
624 + $html .= 'style="margin-bottom: 10px;">';
625 + $html .= esc_html__( 'Manage active plugins', 'wplingua' );
626 + $html .= '</a>';
627 +
628 + $html .= '</div>'; // End .notice
629 +
630 + echo $html;
631 +}
632 +
633 +
634 +/**
635 + * Display a notice if is a multisite
636 + *
637 + * Note: wpLingua does not officially support multisite installations and
638 + * does not guarantee compatibility. Advanced users can bypass this
639 + * incompatibility check by returning true from the
640 + * `wplng_bypass_multisite_incompatibility` filter.
641 + *
642 + * @see apply_filters( 'wplng_bypass_multisite_incompatibility', false )
643 + *
644 + * @return void|string Outputs the admin notice if applicable, or returns void if no action is needed.
645 + */
646 +function wplng_admin_notice_incompatible_multisite() {
647 +
648 + // Advanced users can bypass the multisite incompatibility notice by
649 + // returning true to this filter. Note that bypassing does NOT make
650 + // wpLingua officially compatible with multisite installations.
651 + if ( ! is_multisite()
652 + || apply_filters( 'wplng_bypass_multisite_incompatibility', false )
653 + ) {
654 + return;
655 + }
656 +
657 + $html = '<div ';
658 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
659 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
660 + $html .= '<p style="font-weight: 600;">';
661 + $html .= '<span class="dashicons dashicons-translation"></span> ';
662 + $html .= esc_html__( 'wpLingua - Incompatible with multisite', 'wplingua' );
663 + $html .= '</p>';
664 + $html .= '<p>';
665 + $html .= esc_html__( 'wpLingua is not compatible with multisite.', 'wplingua' );
666 + $html .= '</p>';
667 + $html .= '</div>'; // End .notice
668 +
669 + echo $html;
670 +}
671 +
672 +
673 +/**
674 + * Display a notice if the WordPress installed in a subfolder
675 + *
676 + * @return void|string Outputs the admin notice if applicable, or returns void if no notice is needed.
677 + */
678 +function wplng_admin_notice_incompatible_sub_folder() {
679 +
680 + if ( ! wplng_website_in_sub_folder() ) {
681 + return;
682 + }
683 +
684 + $html = '<div ';
685 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
686 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
687 + $html .= '<p style="font-weight: 600;">';
688 + $html .= '<span class="dashicons dashicons-translation"></span> ';
689 + $html .= esc_html__( 'wpLingua - Incompatible with WordPress installed in a subfolder', 'wplingua' );
690 + $html .= '</p>';
691 + $html .= '<p>';
692 + $html .= esc_html__( 'wpLingua is not compatible with WordPress installed in a subfolder.', 'wplingua' );
693 + $html .= '</p>';
694 + $html .= '</div>'; // End .notice
695 +
696 + echo $html;
697 +}
698 +
699 +
700 +/**
701 + * Display a notice if the PHP version is incompatible
702 + *
703 + * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
704 + */
705 +function wplng_admin_notice_incompatible_php_version() {
706 +
707 + if ( version_compare( PHP_VERSION, WPLNG_PHP_MIN_VERSION ) >= 0 ) {
708 + return;
709 + }
710 +
711 + $html = '<div ';
712 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
713 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
714 + $html .= '<p style="font-weight: 600;">';
715 + $html .= '<span class="dashicons dashicons-translation"></span> ';
716 + $html .= esc_html__( 'wpLingua - Incompatible PHP version', 'wplingua' );
717 + $html .= '</p>';
718 + $html .= '<p>';
719 + $html .= esc_html__( 'wpLingua is not compatible with your PHP version. wpLingua requires PHP 7.4 or higher.', 'wplingua' );
720 + $html .= '</p>';
721 + $html .= '</div>'; // End .notice
722 +
723 + echo $html;
724 +}
725 +
726 +
727 +/**
728 + * Check if the HTACCESS file contain code of another plugin who break translated pages
729 + *
730 + * @return bool HTACCESS file is valid for wpLingua
731 + */
732 +function wplng_htaccess_is_valid() {
733 +
734 + $htaccess_path = ABSPATH . '.htaccess';
735 +
736 + if ( ! file_exists( $htaccess_path ) ) {
737 + return true;
738 + }
739 +
740 + $htaccess_content = file_get_contents( $htaccess_path );
741 +
742 + return ! (
743 + strpos( $htaccess_content, 'GTranslate' ) !== false
744 + || strpos( $htaccess_content, 'LINGUISE' ) !== false
745 + );
746 +}
747 +
748 +
749 +/**
750 + * Display a notice if the HTACCESS file is incompatible
751 + *
752 + * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
753 + */
754 +function wplng_admin_notice_incompatible_htaccess() {
755 +
756 + $htaccess_path = ABSPATH . '.htaccess';
757 +
758 + if ( ! file_exists( $htaccess_path ) ) {
759 + return;
760 + }
761 +
762 + $htaccess_content = file_get_contents( $htaccess_path );
763 + $message = '';
764 +
765 + if ( strpos( $htaccess_content, 'GTranslate' ) !== false ) {
766 + $message .= '### BEGIN GTranslate config ###' . PHP_EOL;
767 + $message .= '...' . PHP_EOL;
768 + $message .= '### END GTranslate config ###';
769 + } elseif ( strpos( $htaccess_content, 'LINGUISE' ) !== false ) {
770 + $message .= '#### LINGUISE DO NOT EDIT ####' . PHP_EOL;
771 + $message .= '...' . PHP_EOL;
772 + $message .= '#### LINGUISE DO NOT EDIT END ####';
773 + }
774 +
775 + if ( ! empty( $message ) ) {
776 +
777 + $html = '<div ';
778 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
779 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
780 + $html .= '<p style="font-weight: 600;">';
781 + $html .= '<span class="dashicons dashicons-translation"></span> ';
782 + $html .= esc_html__( 'wpLingua - Incompatible HTACCESS file', 'wplingua' );
783 + $html .= '</p>';
784 + $html .= '<p>';
785 + $html .= esc_html__( 'It seems that a plugin was incorrectly deactivated and corrupted the site\'s HTACCESS file, preventing the correct redirection of translated pages. Please edit the ".htaccess" file located at the root of the site and delete the lines between :', 'wplingua' );
786 + $html .= '<pre style="border: 1px solid #c3c4c7; padding: 8px; background-color: rgba(0,0,0,.05);">';
787 + $html .= $message;
788 + $html .= '</pre>';
789 + $html .= '</p>';
790 + $html .= '</div>'; // End .notice
791 +
792 + echo $html;
793 + }
794 +}
795 +
796 +
797 +/**
798 + * Display a notice if the permalink structure is set to Plain
799 + *
800 + * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
801 + */
802 +function wplng_admin_notice_incompatible_plain_permalink() {
803 +
804 + if ( ! empty( get_option( 'permalink_structure' ) ) ) {
805 + return;
806 + }
807 +
808 + $url_permalinks = get_admin_url() . 'options-permalink.php';
809 +
810 + $html = '<div ';
811 + $html .= 'class="wplng-notice notice notice-error is-dismissible" ';
812 + $html .= 'style="background-color: rgba(255, 0, 0, .1);">';
813 + $html .= '<p style="font-weight: 600;">';
814 + $html .= '<span class="dashicons dashicons-translation"></span> ';
815 + $html .= esc_html__( 'wpLingua - Incompatible permalink structure', 'wplingua' );
816 + $html .= '</p>';
817 + $html .= '<p>';
818 + $html .= esc_html__( 'wpLingua is not compatible with the "Plain" permalink structure. Please update your permalink settings to use "Post name" or "Custom Structure".', 'wplingua' );
819 + $html .= '</p>';
820 + $html .= '<a ';
821 + $html .= 'href="' . esc_url( $url_permalinks ) . '" ';
822 + $html .= 'class="button button-primary" ';
823 + $html .= 'style="margin-bottom: 10px;">';
824 + $html .= esc_html__( 'Manage permalink settings', 'wplingua' );
825 + $html .= '</a>';
826 + $html .= '</div>'; // End .notice
827 +
828 + echo $html;
829 +}
830 +
831 +
832 +/**
833 + * Display a notice for obtaining the PRO version of the plugin
834 + * - Only for non free user
835 + * - Only on wpLingua option's pages
836 + * - Only if PRO plugin not already activated
837 + *
838 + * @return void|string Outputs the admin notice if applicable, or returns void if no notice is required.
839 + */
840 +function wplng_admin_notice_get_pro_version() {
841 +
842 + if ( is_plugin_active( 'wplingua-pro/wplingua-pro.php' ) ) {
843 + return;
844 + }
845 +
846 + $data = wplng_get_api_data();
847 +
848 + if ( empty( $data['status'] )
849 + || $data['status'] === 'FREE'
850 + ) {
851 + return;
852 + }
853 +
854 + $html = '<div';
855 + $html .= ' class="wplng-notice notice notice-warning is-dismissible"';
856 + $html .= ' style="text-align: center;"';
857 + $html .= '>';
858 + $html .= '<p style="font-weight: 600;">';
859 + $html .= '<span class="dashicons dashicons-translation"></span> ';
860 + $html .= esc_html__( 'wpLingua - Unlock PRO Features', 'wplingua' );
861 + $html .= '</p>';
862 + $html .= '<hr>';
863 + $html .= '<p>';
864 + $html .= esc_html__( 'Extend wpLingua with additional features and advanced translation capabilities.', 'wplingua' );
865 + $html .= '</p>';
866 + $html .= '<p>';
867 + $html .= esc_html__( 'Download and install wpLingua PRO to access the features included with your wpLingua plan.', 'wplingua' );
868 + $html .= '</p>';
869 +
870 + $html .= '<br>';
871 + $html .= '<a';
872 + $html .= ' href="https://wplingua.com/download/"';
873 + $html .= ' target="_blank"';
874 + $html .= ' rel="noopener noreferrer"';
875 + $html .= ' class="button button-primary"';
876 + $html .= '>';
877 + $html .= esc_html__( 'wpLingua.com : Download PRO plugin', 'wplingua' );
878 + $html .= '</a>';
879 + $html .= '</div>'; // End .notice
880 +
881 + echo $html;
882 +}