PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 2.16.3
Translate and Go multilingual – Automatic AI translation – wpLingua v2.16.3
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 1.1.1 1.2.0 1.2.1 All 109 releases
wplingua / wplingua.php

wplingua.php in Translate and Go multilingual – Automatic AI translation – wpLingua 2.16.3, at wplingua.php

459 lines 16.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: wpLingua
4 * Plugin URI: https://wplingua.com/
5 * Description: An all-in-one solution that makes your websites multilingual and translates them automatically, without word or page limits. The highlights: a free first language, an on-page visual editor for editing translations, a customizable language switcher, search engine optimization (SEO), self-hosted data and more!
6 * Author: wpLingua Translation Service
7 * Author URI: https://wplingua.com/
8 * Text Domain: wplingua
9 * Domain Path: /languages/
10 * Version: 2.16.3
11 * Requires PHP: 7.4
12 * License: GPL v2 or later
13 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
14 */
15
16
17 // If this file is called directly, abort.
18 if ( ! defined( 'WPINC' ) ) {
19 die;
20 }
21
22
23 // Define wpLingua constants
24 define( 'WPLNG_API_URL', 'https://api.wplingua.com' );
25 define( 'WPLNG_API_VERSION', '3.0' );
26 define( 'WPLNG_API_SSLVERIFY', true );
27 define( 'WPLNG_PLUGIN_VERSION', '2.16.3' );
28 define( 'WPLNG_PLUGIN_FILE', plugin_basename( __FILE__ ) );
29 define( 'WPLNG_PLUGIN_DIR', __DIR__ );
30 define( 'WPLNG_CACHE_DIR', WP_CONTENT_DIR . '/wplingua-cache' );
31 define( 'WPLNG_PHP_MIN_VERSION', '7.4' );
32 define( 'WPLNG_MAX_TRANSLATIONS_STR', 220 );
33 define( 'WPLNG_MAX_TRANSLATIONS_CHAR', 4200 );
34 define( 'WPLNG_MAX_FILE_SIZE', 5000000 );
35
36
37 // Define debug constants
38 defined( 'WPLNG_DEBUG_JSON' ) || define( 'WPLNG_DEBUG_JSON', false );
39 defined( 'WPLNG_DEBUG_AJAX' ) || define( 'WPLNG_DEBUG_AJAX', false );
40 defined( 'WPLNG_DEBUG_REST' ) || define( 'WPLNG_DEBUG_REST', false );
41 defined( 'WPLNG_DEBUG_BEAT' ) || define( 'WPLNG_DEBUG_BEAT', false );
42 defined( 'WPLNG_DEBUG_XML' ) || define( 'WPLNG_DEBUG_XML', false );
43
44
45 // Load all needed PHP files
46 require_once WPLNG_PLUGIN_DIR . '/loader.php';
47
48
49 /**
50 * Loads wpLingua plugin's translated strings.
51 *
52 * @return void
53 */
54 function wplng_load_plugin_textdomain() {
55 load_plugin_textdomain(
56 'wplingua',
57 false,
58 'wplingua/languages'
59 );
60 }
61
62
63 /**
64 * Register all wpLingua Hook
65 *
66 * @return void
67 */
68 function wplng_start() {
69
70 // Setup $wplng_class_reload
71 global $wplng_class_reload;
72 $wplng_class_reload = false;
73
74 // Setup $wplng_request_uri
75 if ( isset( $_SERVER['REQUEST_URI'] ) ) {
76
77 $request_uri = wp_unslash( (string) $_SERVER['REQUEST_URI'] );
78 $request_uri = wplng_normalize_request_path( $request_uri );
79 $decoded_uri = urldecode( $request_uri );
80
81 // Check if the request URI is clean
82 if ( strtolower( esc_url_raw( $request_uri ) ) !== strtolower( $request_uri )
83 || wplng_str_is_malicious( $request_uri )
84 || wplng_str_is_malicious( $decoded_uri )
85 ) {
86 return;
87 }
88
89 // Also check query string for double-encoded attacks
90 if ( isset( $_SERVER['QUERY_STRING'] ) ) {
91 $query_string = sanitize_text_field( $_SERVER['QUERY_STRING'] );
92 $decoded_query = urldecode( urldecode( $query_string ) );
93
94 if ( wplng_str_is_malicious( $decoded_query ) ) {
95 return;
96 }
97 }
98
99 global $wplng_request_uri;
100 $wplng_request_uri = $request_uri;
101 }
102
103 // The plugin version has changed
104 if ( get_option( 'wplng_version' ) !== WPLNG_PLUGIN_VERSION ) {
105 // Update version number in DB
106 update_option( 'wplng_version', WPLNG_PLUGIN_VERSION, true );
107
108 // Clear all wpLingua cache
109 delete_option( 'wplng_cached_translations' );
110 delete_option( 'wplng_cached_slugs' );
111 delete_option( 'wplng_api_key_data' );
112 wplng_clear_folder_cache();
113 wplng_clear_website_cache();
114
115 // Clear old cache method (version <= 2.12.3)
116 delete_transient( 'wplng_cached_translations' );
117 delete_transient( 'wplng_cached_slugs' );
118 }
119
120 // Load plugin text domain /languages/
121 add_action( 'init', 'wplng_load_plugin_textdomain' );
122
123 // Do not cache page for connected editor
124 add_action( 'init', 'wplng_init_manage_cache', 1 );
125
126 // Display a notice if incompatibility is detected
127 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_plugin', 1 );
128 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_multisite', 1 );
129 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_php_version', 1 );
130 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_htaccess', 1 );
131 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_plain_permalink', 1 );
132
133 // Return if incompatibility is detected
134 if ( ! empty( wplng_get_incompatible_plugins() )
135 || ( is_multisite()
136 && ! apply_filters( 'wplng_bypass_multisite_incompatibility', false )
137 )
138 || ( version_compare( PHP_VERSION, WPLNG_PHP_MIN_VERSION ) < 0 )
139 || ! wplng_htaccess_is_valid()
140 || empty( get_option( 'permalink_structure' ) )
141 ) {
142 return;
143 }
144
145 // Register plugin settings
146 add_action( 'admin_init', 'wplng_register_settings' );
147
148 // Add settings link in plugin list
149 add_filter( 'plugin_action_links_' . WPLNG_PLUGIN_FILE, 'wplng_settings_link' );
150
151 // Redirect to the settings page on plugin activation
152 add_action( 'activated_plugin', 'wplng_plugin_activation_redirect' );
153
154 // Set footer text for options pages
155 add_filter( 'admin_footer_text', 'wplng_admin_footer_text', 11 );
156 add_filter( 'update_footer', 'wplng_update_footer', 11 );
157
158 // Print head script (JSON with all languages informations)
159 add_action( 'toplevel_page_wplingua-settings', 'wplng_inline_script_languages' );
160
161 if ( empty( wplng_get_api_data() ) ) {
162
163 // Add Register option page in back office menu
164 add_action( 'admin_menu', 'wplng_create_menu_register' );
165
166 // Enqueue CSS and JS files for register option pages
167 add_action( 'admin_enqueue_scripts', 'wplng_option_page_register_assets' );
168
169 // Display a notice if the plugin is activate but not configured
170 add_action( 'admin_notices', 'wplng_admin_notice_no_key_set', 1 );
171
172 } else {
173
174 /**
175 * Back office
176 */
177
178 // Add menu in back office
179 add_action( 'admin_menu', 'wplng_create_menu' );
180 add_filter( 'parent_file', 'wplng_option_page_parent_file' );
181 add_filter( 'submenu_file', 'wplng_option_page_submenu_file' );
182 add_action( 'admin_head', 'wplng_option_page_hide_submenu' );
183
184 // Add admin Bar menu
185 add_action( 'admin_bar_menu', 'wplng_admin_bar_menu', 81 );
186 add_action( 'admin_bar_menu', 'wplng_admin_bar_edit', 81 );
187
188 // Switcher in nav menu options
189 add_action( 'admin_enqueue_scripts', 'wplng_switcher_nav_menu_inline_scripts' );
190 add_action( 'admin_head-nav-menus.php', 'wp_nav_menu_switcher_box_add_register' );
191 add_action( 'wp_nav_menu_item_custom_fields', 'wp_nav_menu_switcher_box_edit', 10, 2 );
192
193 // Enqueue CSS and JS files for option pages
194 add_action( 'admin_enqueue_scripts', 'wplng_option_page_settings_assets' );
195 add_action( 'admin_enqueue_scripts', 'wplng_option_page_switcher_assets' );
196 add_action( 'admin_enqueue_scripts', 'wplng_option_page_exclusions_assets' );
197 add_action( 'admin_enqueue_scripts', 'wplng_option_page_dictionary_assets' );
198 add_action( 'admin_enqueue_scripts', 'wplng_option_page_link_media_assets' );
199
200 // Update flags URL
201 add_action( 'update_option_wplng_flags_style', 'wplng_options_switcher_update_flags_style', 10, 2 );
202
203 // Update translations on dictionary changes
204 add_action( 'update_option_wplng_dictionary_entries', 'wplng_on_dictionary_entries_updated', 10, 2 );
205 add_action( 'wp_ajax_wplng_dictionary_update_translations', 'wplng_ajax_dictionary_update_translations' );
206
207 // Reset API data on API key changing
208 add_action( 'update_option_wplng_api_key', 'wplng_on_update_option_wplng_api_key', 10, 2 );
209
210 // Add edit link on page and post list
211 add_filter( 'page_row_actions', 'wplng_row_edit_translation_link', 10, 2 );
212 add_filter( 'post_row_actions', 'wplng_row_edit_translation_link', 10, 2 );
213
214 // Notice for obtaining the PRO version
215 // add_action( 'admin_notices', 'wplng_admin_notice_get_pro_version', 1 );
216
217 /**
218 * wplng_translation : CPT, taxo, meta
219 */
220
221 // Register wplng_translation CPT
222 add_action( 'init', 'wplng_register_post_type_translation' );
223
224 // Add metabox for wplng_translation
225 add_action( 'add_meta_boxes_wplng_translation', 'wplng_translation_add_meta_box' );
226
227 // Save metabox on posts saving
228 add_action( 'save_post_wplng_translation', 'wplng_translation_save_meta_boxes_data', 10, 2 );
229
230 // Clear translation cache on trash / untrash
231 add_action( 'trashed_post', 'wplng_clear_translations_cache_trash_untrash' );
232 add_action( 'untrash_post', 'wplng_clear_translations_cache_trash_untrash' );
233 add_action( 'delete_post', 'wplng_clear_translations_cache_trash_untrash' );
234
235 // Enqueue Script for wplng_translation admin: Edit
236 add_action( 'admin_print_scripts-post.php', 'wplng_translation_edit_assets' );
237
238 // Enqueue Script for wplng_translation admin: List
239 add_action( 'admin_print_scripts-edit.php', 'wplng_translation_list_assets' );
240
241 // Only show translations for the website languages
242 add_action( 'pre_get_posts', 'wplng_filter_wplng_translation_posts' );
243
244 // Remove Quick edit from translations list
245 add_filter( 'post_row_actions', 'wplng_translation_remove_quick_edit', 10, 2 );
246
247 // Ajax function for regenerate translation on edit page
248 add_action( 'wp_ajax_wplng_ajax_translation', 'wplng_ajax_generate_translation' );
249
250 // Ajax function for edit modal: Get HTML modal
251 add_action( 'wp_ajax_wplng_ajax_edit_modal', 'wplng_ajax_edit_modal' );
252
253 // Ajax function for edit modal: Save modal
254 add_action( 'wp_ajax_wplng_ajax_save_modal', 'wplng_ajax_save_modal' );
255
256 // Ajax function for edit modal: HeartBeat
257 add_action( 'wp_ajax_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
258 add_action( 'wp_ajax_nopriv_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
259
260 // Display 100 translation in admin area by default
261 add_filter( 'get_user_option_edit_wplng_translation_per_page', 'wplng_translation_per_page' );
262
263 // Filter translations by status
264 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_translation_status' );
265 add_filter( 'parse_query', 'wplng_posts_filter_translation_status' );
266
267 // Translation status on website translations list
268 add_filter( 'post_class', 'wplng_post_class_translation_status', 10, 3 );
269 add_filter( 'post_row_actions', 'wplng_post_row_actions_translation_status', 10, 2 );
270 add_filter( 'manage_wplng_translation_posts_columns', 'wplng_translation_status_columns' );
271 add_action( 'manage_wplng_translation_posts_custom_column', 'wplng_translation_status_item', 10, 2 );
272
273 /**
274 * wplng_slug : CPT, taxo, meta
275 */
276
277 // Register wplng_translation CPT
278 add_action( 'init', 'wplng_register_post_type_slug' );
279
280 // Add metabox for wplng_slug
281 add_action( 'add_meta_boxes_wplng_slug', 'wplng_slug_add_meta_box' );
282
283 // Save metabox on posts saving
284 add_action( 'save_post_wplng_slug', 'wplng_slug_save_meta_boxes_data', 10, 2 );
285
286 // Clear slugs cache on trash / untrash
287 add_action( 'trashed_post', 'wplng_clear_slugs_cache_trash_untrash' );
288 add_action( 'untrash_post', 'wplng_clear_slugs_cache_trash_untrash' );
289 add_action( 'delete_post', 'wplng_clear_slugs_cache_trash_untrash' );
290
291 // Enqueue Script for wplng_slug admin: Edit
292 add_action( 'admin_print_scripts-post.php', 'wplng_slug_edit_assets' );
293
294 // Enqueue Script for wplng_slug admin: List
295 add_action( 'admin_print_scripts-edit.php', 'wplng_slug_list_assets' );
296
297 // Only show slugs for the website languages
298 add_action( 'pre_get_posts', 'wplng_filter_wplng_slug_posts' );
299
300 // Remove Quick edit from slugs list
301 add_filter( 'post_row_actions', 'wplng_slug_remove_quick_edit', 10, 2 );
302
303 // Ajax function for regenerate slug on edit page
304 add_action( 'wp_ajax_wplng_ajax_slug', 'wplng_ajax_generate_slug' );
305
306 // Display 100 translation in admin area by default
307 add_filter( 'get_user_option_edit_wplng_slug_per_page', 'wplng_slug_per_page' );
308
309 // Filter slugs by status
310 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_slug_status' );
311 add_filter( 'parse_query', 'wplng_posts_filter_slug_status' );
312
313 // Translation status on website slugs list
314 add_filter( 'post_class', 'wplng_post_class_slug_status', 10, 3 );
315 add_filter( 'post_row_actions', 'wplng_post_row_actions_slug_status', 10, 2 );
316 add_filter( 'manage_wplng_slug_posts_columns', 'wplng_slug_status_columns' );
317 add_action( 'manage_wplng_slug_posts_custom_column', 'wplng_slug_status_item', 10, 2 );
318
319 /**
320 * Front
321 */
322
323 // Enqueue CSS and JS files
324 add_action( 'wp_enqueue_scripts', 'wplng_register_assets' );
325
326 // Add custom inline styles (option page: switcher)
327 add_action( 'wp_head', 'wplng_add_custom_inline_styles', 50 );
328
329 // Script JS in page
330 add_action( 'wp_footer', 'wplng_on_page_script' );
331
332 // Add languages switcher before </body>
333 add_action( 'wp_footer', 'wplng_switcher_wp_footer' );
334
335 // Add languages switcher in nav menu
336 add_filter( 'wp_nav_menu_objects', 'wplng_switcher_nav_menu_replace_items' );
337 add_filter( 'nav_menu_link_attributes', 'wplng_add_nav_menu_link_attributes_atts', 10, 2 );
338
339 // Set alternate links with hreflang parametters
340 add_action( 'wp_head', 'wplng_link_alternate_hreflang', 1 );
341
342 // Disable web browser automatic translation
343 add_action( 'language_attributes', 'wplng_disable_web_browser_auto_translate' );
344
345 // Ajax function for Load in progress
346 add_action( 'wp_ajax_wplng_load_in_progress', 'wplng_ajax_load_in_progress' );
347
348 /**
349 * OB and REQUEST_URI
350 */
351
352 // Manage URL with REQUEST_URI and start OB
353 add_action( 'init', 'wplng_ob_start', 1 );
354
355 // Redirect page if is called with an untranslate slug
356 add_action( 'template_redirect', 'wplng_redirect_translated_slug' );
357
358 // Translate WooCommerce cart URL
359 add_filter( 'woocommerce_get_cart_url', 'wplng_url_translate' );
360
361 /**
362 * Generate JSON translation on the fly for wp-i18n.js
363 */
364
365 // Generate JSON translation
366 add_filter( 'load_script_translation_file', 'wplng_load_script_translation_file', 20, 3 );
367
368 /**
369 * Clear wpLingua cache on updates
370 */
371
372 // Clear wpLingua cache on WordPress core, plugins, themes or translations update
373 add_action( 'upgrader_process_complete', 'wplng_clear_cache_on_update', 10, 2 );
374
375 // Clear wpLingua cache on plugin activation/deactivation
376 add_action( 'activated_plugin', 'wplng_clear_folder_cache' );
377 add_action( 'deactivated_plugin', 'wplng_clear_folder_cache' );
378
379 // Clear wpLingua cache on theme switch
380 add_action( 'switch_theme', 'wplng_clear_folder_cache' );
381
382 // Clear wpLingua cache on site language change
383 add_action( 'update_option_WPLANG', 'wplng_clear_folder_cache' );
384
385 // Clear wpLingua cache on wpLingua settings change
386 add_action( 'update_option_wplng_website_language', 'wplng_clear_folder_cache' );
387 add_action( 'update_option_wplng_target_languages', 'wplng_clear_folder_cache' );
388
389 /**
390 * Features
391 */
392
393 // Make multilingua Sitemap XML for All In One SEO plugin
394 // Il other case, multilingual Sitemap is make by output buffering
395 if ( get_option( 'wplng_sitemap_xml', true )
396 && function_exists( 'aioseo' )
397 ) {
398 add_filter( 'aioseo_sitemap_post', 'wplng_aioseo_filter_sitemap_post', 10, 2 );
399 add_filter( 'aioseo_sitemap_term', 'wplng_aioseo_filter_sitemap_term', 10, 2 );
400 }
401
402 // Search from translated languages
403 if ( ! empty( get_option( 'wplng_translate_search' ) )
404 && wplng_api_feature_is_allow( 'search' )
405 ) {
406 add_action( 'parse_query', 'wplng_translate_search_query' );
407 add_filter( 'get_search_query', 'wplng_search_put_tag' );
408 add_filter( 'wplng_translated_html', 'wplng_search_replace_tag', 5 );
409 } else {
410 add_filter( 'wplng_url_is_translatable', 'wplng_exclude_search', 20 );
411 }
412
413 // Redirect by browser language
414 $browser_language_redirect = get_option( 'wplng_browser_language_redirect' );
415 if ( $browser_language_redirect === 'js_only' ) {
416 add_action( 'wp_head', 'wplng_browser_language_redirect_js_only', 2 );
417 } elseif ( $browser_language_redirect === 'php_js' ) {
418 add_action( 'template_redirect', 'wplng_browser_language_redirect_php_js' );
419 }
420
421 /**
422 * Shortcode
423 */
424
425 add_shortcode( 'wplng_switcher', 'wplng_shortcode_switcher' );
426 add_shortcode( 'wplng_notranslate', 'wplng_shortcode_notranslate' );
427 add_shortcode( 'wplng_only', 'wplng_shortcode_only' );
428
429 /**
430 * Gutenberg
431 */
432
433 add_filter( 'block_categories_all', 'wplng_block_category' );
434 add_action( 'init', 'wplng_register_block' );
435 add_action( 'enqueue_block_editor_assets', 'wplng_register_block_assets' );
436
437 /**
438 * Do action after wpLingua fully initialized
439 */
440
441 do_action( 'wplng_initialized' );
442
443 }
444 }
445 wplng_start();
446
447
448 /**
449 * Delete translation and slug cache options on plugin deactivation.
450 *
451 * @return void
452 */
453 function wplng_deactivate() {
454 delete_option( 'wplng_cached_translations' );
455 delete_option( 'wplng_cached_slugs' );
456 delete_option( 'wplng_api_key_data' );
457 }
458 register_deactivation_hook( __FILE__, 'wplng_deactivate' );
459