PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 2.16.1
Translate and Go multilingual – Automatic AI translation – wpLingua v2.16.1
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.1, at wplingua.php

456 lines 16.6 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.1
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.1' );
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 /**
215 * wplng_translation : CPT, taxo, meta
216 */
217
218 // Register wplng_translation CPT
219 add_action( 'init', 'wplng_register_post_type_translation' );
220
221 // Add metabox for wplng_translation
222 add_action( 'add_meta_boxes_wplng_translation', 'wplng_translation_add_meta_box' );
223
224 // Save metabox on posts saving
225 add_action( 'save_post_wplng_translation', 'wplng_translation_save_meta_boxes_data', 10, 2 );
226
227 // Clear translation cache on trash / untrash
228 add_action( 'trashed_post', 'wplng_clear_translations_cache_trash_untrash' );
229 add_action( 'untrash_post', 'wplng_clear_translations_cache_trash_untrash' );
230 add_action( 'delete_post', 'wplng_clear_translations_cache_trash_untrash' );
231
232 // Enqueue Script for wplng_translation admin: Edit
233 add_action( 'admin_print_scripts-post.php', 'wplng_translation_edit_assets' );
234
235 // Enqueue Script for wplng_translation admin: List
236 add_action( 'admin_print_scripts-edit.php', 'wplng_translation_list_assets' );
237
238 // Only show translations for the website languages
239 add_action( 'pre_get_posts', 'wplng_filter_wplng_translation_posts' );
240
241 // Remove Quick edit from translations list
242 add_filter( 'post_row_actions', 'wplng_translation_remove_quick_edit', 10, 2 );
243
244 // Ajax function for regenerate translation on edit page
245 add_action( 'wp_ajax_wplng_ajax_translation', 'wplng_ajax_generate_translation' );
246
247 // Ajax function for edit modal: Get HTML modal
248 add_action( 'wp_ajax_wplng_ajax_edit_modal', 'wplng_ajax_edit_modal' );
249
250 // Ajax function for edit modal: Save modal
251 add_action( 'wp_ajax_wplng_ajax_save_modal', 'wplng_ajax_save_modal' );
252
253 // Ajax function for edit modal: HeartBeat
254 add_action( 'wp_ajax_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
255 add_action( 'wp_ajax_nopriv_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
256
257 // Display 100 translation in admin area by default
258 add_filter( 'get_user_option_edit_wplng_translation_per_page', 'wplng_translation_per_page' );
259
260 // Filter translations by status
261 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_translation_status' );
262 add_filter( 'parse_query', 'wplng_posts_filter_translation_status' );
263
264 // Translation status on website translations list
265 add_filter( 'post_class', 'wplng_post_class_translation_status', 10, 3 );
266 add_filter( 'post_row_actions', 'wplng_post_row_actions_translation_status', 10, 2 );
267 add_filter( 'manage_wplng_translation_posts_columns', 'wplng_translation_status_columns' );
268 add_action( 'manage_wplng_translation_posts_custom_column', 'wplng_translation_status_item', 10, 2 );
269
270 /**
271 * wplng_slug : CPT, taxo, meta
272 */
273
274 // Register wplng_translation CPT
275 add_action( 'init', 'wplng_register_post_type_slug' );
276
277 // Add metabox for wplng_slug
278 add_action( 'add_meta_boxes_wplng_slug', 'wplng_slug_add_meta_box' );
279
280 // Save metabox on posts saving
281 add_action( 'save_post_wplng_slug', 'wplng_slug_save_meta_boxes_data', 10, 2 );
282
283 // Clear slugs cache on trash / untrash
284 add_action( 'trashed_post', 'wplng_clear_slugs_cache_trash_untrash' );
285 add_action( 'untrash_post', 'wplng_clear_slugs_cache_trash_untrash' );
286 add_action( 'delete_post', 'wplng_clear_slugs_cache_trash_untrash' );
287
288 // Enqueue Script for wplng_slug admin: Edit
289 add_action( 'admin_print_scripts-post.php', 'wplng_slug_edit_assets' );
290
291 // Enqueue Script for wplng_slug admin: List
292 add_action( 'admin_print_scripts-edit.php', 'wplng_slug_list_assets' );
293
294 // Only show slugs for the website languages
295 add_action( 'pre_get_posts', 'wplng_filter_wplng_slug_posts' );
296
297 // Remove Quick edit from slugs list
298 add_filter( 'post_row_actions', 'wplng_slug_remove_quick_edit', 10, 2 );
299
300 // Ajax function for regenerate slug on edit page
301 add_action( 'wp_ajax_wplng_ajax_slug', 'wplng_ajax_generate_slug' );
302
303 // Display 100 translation in admin area by default
304 add_filter( 'get_user_option_edit_wplng_slug_per_page', 'wplng_slug_per_page' );
305
306 // Filter slugs by status
307 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_slug_status' );
308 add_filter( 'parse_query', 'wplng_posts_filter_slug_status' );
309
310 // Translation status on website slugs list
311 add_filter( 'post_class', 'wplng_post_class_slug_status', 10, 3 );
312 add_filter( 'post_row_actions', 'wplng_post_row_actions_slug_status', 10, 2 );
313 add_filter( 'manage_wplng_slug_posts_columns', 'wplng_slug_status_columns' );
314 add_action( 'manage_wplng_slug_posts_custom_column', 'wplng_slug_status_item', 10, 2 );
315
316 /**
317 * Front
318 */
319
320 // Enqueue CSS and JS files
321 add_action( 'wp_enqueue_scripts', 'wplng_register_assets' );
322
323 // Add custom inline styles (option page: switcher)
324 add_action( 'wp_head', 'wplng_add_custom_inline_styles', 50 );
325
326 // Script JS in page
327 add_action( 'wp_footer', 'wplng_on_page_script' );
328
329 // Add languages switcher before </body>
330 add_action( 'wp_footer', 'wplng_switcher_wp_footer' );
331
332 // Add languages switcher in nav menu
333 add_filter( 'wp_nav_menu_objects', 'wplng_switcher_nav_menu_replace_items' );
334 add_filter( 'nav_menu_link_attributes', 'wplng_add_nav_menu_link_attributes_atts', 10, 2 );
335
336 // Set alternate links with hreflang parametters
337 add_action( 'wp_head', 'wplng_link_alternate_hreflang', 1 );
338
339 // Disable web browser automatic translation
340 add_action( 'language_attributes', 'wplng_disable_web_browser_auto_translate' );
341
342 // Ajax function for Load in progress
343 add_action( 'wp_ajax_wplng_load_in_progress', 'wplng_ajax_load_in_progress' );
344
345 /**
346 * OB and REQUEST_URI
347 */
348
349 // Manage URL with REQUEST_URI and start OB
350 add_action( 'init', 'wplng_ob_start', 1 );
351
352 // Redirect page if is called with an untranslate slug
353 add_action( 'template_redirect', 'wplng_redirect_translated_slug' );
354
355 // Translate WooCommerce cart URL
356 add_filter( 'woocommerce_get_cart_url', 'wplng_url_translate' );
357
358 /**
359 * Generate JSON translation on the fly for wp-i18n.js
360 */
361
362 // Generate JSON translation
363 add_filter( 'load_script_translation_file', 'wplng_load_script_translation_file', 20, 3 );
364
365 /**
366 * Clear wpLingua cache on updates
367 */
368
369 // Clear wpLingua cache on WordPress core, plugins, themes or translations update
370 add_action( 'upgrader_process_complete', 'wplng_clear_cache_on_update', 10, 2 );
371
372 // Clear wpLingua cache on plugin activation/deactivation
373 add_action( 'activated_plugin', 'wplng_clear_folder_cache' );
374 add_action( 'deactivated_plugin', 'wplng_clear_folder_cache' );
375
376 // Clear wpLingua cache on theme switch
377 add_action( 'switch_theme', 'wplng_clear_folder_cache' );
378
379 // Clear wpLingua cache on site language change
380 add_action( 'update_option_WPLANG', 'wplng_clear_folder_cache' );
381
382 // Clear wpLingua cache on wpLingua settings change
383 add_action( 'update_option_wplng_website_language', 'wplng_clear_folder_cache' );
384 add_action( 'update_option_wplng_target_languages', 'wplng_clear_folder_cache' );
385
386 /**
387 * Features
388 */
389
390 // Make multilingua Sitemap XML for All In One SEO plugin
391 // Il other case, multilingual Sitemap is make by output buffering
392 if ( get_option( 'wplng_sitemap_xml', true )
393 && function_exists( 'aioseo' )
394 ) {
395 add_filter( 'aioseo_sitemap_post', 'wplng_aioseo_filter_sitemap_post', 10, 2 );
396 add_filter( 'aioseo_sitemap_term', 'wplng_aioseo_filter_sitemap_term', 10, 2 );
397 }
398
399 // Search from translated languages
400 if ( ! empty( get_option( 'wplng_translate_search' ) )
401 && wplng_api_feature_is_allow( 'search' )
402 ) {
403 add_action( 'parse_query', 'wplng_translate_search_query' );
404 add_filter( 'get_search_query', 'wplng_search_put_tag' );
405 add_filter( 'wplng_translated_html', 'wplng_search_replace_tag', 5 );
406 } else {
407 add_filter( 'wplng_url_is_translatable', 'wplng_exclude_search', 20 );
408 }
409
410 // Redirect by browser language
411 $browser_language_redirect = get_option( 'wplng_browser_language_redirect' );
412 if ( $browser_language_redirect === 'js_only' ) {
413 add_action( 'wp_head', 'wplng_browser_language_redirect_js_only', 2 );
414 } elseif ( $browser_language_redirect === 'php_js' ) {
415 add_action( 'template_redirect', 'wplng_browser_language_redirect_php_js' );
416 }
417
418 /**
419 * Shortcode
420 */
421
422 add_shortcode( 'wplng_switcher', 'wplng_shortcode_switcher' );
423 add_shortcode( 'wplng_notranslate', 'wplng_shortcode_notranslate' );
424 add_shortcode( 'wplng_only', 'wplng_shortcode_only' );
425
426 /**
427 * Gutenberg
428 */
429
430 add_filter( 'block_categories_all', 'wplng_block_category' );
431 add_action( 'init', 'wplng_register_block' );
432 add_action( 'enqueue_block_editor_assets', 'wplng_register_block_assets' );
433
434 /**
435 * Do action after wpLingua fully initialized
436 */
437
438 do_action( 'wplng_initialized' );
439
440 }
441 }
442 wplng_start();
443
444
445 /**
446 * Delete translation and slug cache options on plugin deactivation.
447 *
448 * @return void
449 */
450 function wplng_deactivate() {
451 delete_option( 'wplng_cached_translations' );
452 delete_option( 'wplng_cached_slugs' );
453 delete_option( 'wplng_api_key_data' );
454 }
455 register_deactivation_hook( __FILE__, 'wplng_deactivate' );
456