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

448 lines 16.2 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.15.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.15.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 wplng_clear_translations_cache();
110 wplng_clear_slugs_cache();
111 wplng_clear_folder_cache();
112
113 // Clear old cache method (version <= 2.12.3)
114 delete_transient( 'wplng_cached_translations' );
115 delete_transient( 'wplng_cached_slugs' );
116 }
117
118 // Load plugin text domain /languages/
119 add_action( 'init', 'wplng_load_plugin_textdomain' );
120
121 // Do not cache page for connected editor
122 add_action( 'init', 'wplng_init_manage_cache', 1 );
123
124 // Display a notice if incompatibility is detected
125 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_plugin', 1 );
126 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_multisite', 1 );
127 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_php_version', 1 );
128 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_htaccess', 1 );
129 add_action( 'admin_notices', 'wplng_admin_notice_incompatible_plain_permalink', 1 );
130
131 // Return if incompatibility is detected
132 if ( ! empty( wplng_get_incompatible_plugins() )
133 || ( is_multisite()
134 && ! apply_filters( 'wplng_bypass_multisite_incompatibility', false )
135 )
136 || ( version_compare( PHP_VERSION, WPLNG_PHP_MIN_VERSION ) < 0 )
137 || ! wplng_htaccess_is_valid()
138 || empty( get_option( 'permalink_structure' ) )
139 ) {
140 return;
141 }
142
143 // Register plugin settings
144 add_action( 'admin_init', 'wplng_register_settings' );
145
146 // Add settings link in plugin list
147 add_filter( 'plugin_action_links_' . WPLNG_PLUGIN_FILE, 'wplng_settings_link' );
148
149 // Redirect to the settings page on plugin activation
150 add_action( 'activated_plugin', 'wplng_plugin_activation_redirect' );
151
152 // Set footer text for options pages
153 add_filter( 'admin_footer_text', 'wplng_admin_footer_text', 11 );
154 add_filter( 'update_footer', 'wplng_update_footer', 11 );
155
156 // Print head script (JSON with all languages informations)
157 add_action( 'toplevel_page_wplingua-settings', 'wplng_inline_script_languages' );
158
159 if ( empty( wplng_get_api_data() ) ) {
160
161 // Add Register option page in back office menu
162 add_action( 'admin_menu', 'wplng_create_menu_register' );
163
164 // Enqueue CSS and JS files for register option pages
165 add_action( 'admin_enqueue_scripts', 'wplng_option_page_register_assets' );
166
167 // Display a notice if the plugin is activate but not configured
168 add_action( 'admin_notices', 'wplng_admin_notice_no_key_set', 1 );
169
170 } else {
171
172 /**
173 * Back office
174 */
175
176 // Add menu in back office
177 add_action( 'admin_menu', 'wplng_create_menu' );
178
179 // Add admin Bar menu
180 add_action( 'admin_bar_menu', 'wplng_admin_bar_menu', 81 );
181 add_action( 'admin_bar_menu', 'wplng_admin_bar_edit', 81 );
182
183 // Switcher in nav menu options
184 add_action( 'admin_enqueue_scripts', 'wplng_switcher_nav_menu_inline_scripts' );
185 add_action( 'admin_head-nav-menus.php', 'wp_nav_menu_switcher_box_add_register' );
186 add_action( 'wp_nav_menu_item_custom_fields', 'wp_nav_menu_switcher_box_edit', 10, 2 );
187
188 // Enqueue CSS and JS files for option pages
189 add_action( 'admin_enqueue_scripts', 'wplng_option_page_settings_assets' );
190 add_action( 'admin_enqueue_scripts', 'wplng_option_page_switcher_assets' );
191 add_action( 'admin_enqueue_scripts', 'wplng_option_page_exclusions_assets' );
192 add_action( 'admin_enqueue_scripts', 'wplng_option_page_dictionary_assets' );
193 add_action( 'admin_enqueue_scripts', 'wplng_option_page_link_media_assets' );
194
195 // Update flags URL
196 add_action( 'update_option_wplng_flags_style', 'wplng_options_switcher_update_flags_style', 10, 2 );
197
198 // Update translations on dictionary changes
199 add_action( 'update_option_wplng_dictionary_entries', 'wplng_on_dictionary_entries_updated', 10, 2 );
200 add_action( 'wp_ajax_wplng_dictionary_update_translations', 'wplng_ajax_dictionary_update_translations' );
201
202 // Reset API data on API key changing
203 add_action( 'update_option_wplng_api_key', 'wplng_on_update_option_wplng_api_key', 10, 2 );
204
205 // Add edit link on page and post list
206 add_filter( 'page_row_actions', 'wplng_row_edit_translation_link', 10, 2 );
207 add_filter( 'post_row_actions', 'wplng_row_edit_translation_link', 10, 2 );
208
209 /**
210 * wplng_translation : CPT, taxo, meta
211 */
212
213 // Register wplng_translation CPT
214 add_action( 'init', 'wplng_register_post_type_translation' );
215
216 // Add metabox for wplng_translation
217 add_action( 'add_meta_boxes_wplng_translation', 'wplng_translation_add_meta_box' );
218
219 // Save metabox on posts saving
220 add_action( 'save_post_wplng_translation', 'wplng_translation_save_meta_boxes_data', 10, 2 );
221
222 // Clear translation cache on trash / untrash
223 add_action( 'trashed_post', 'wplng_clear_translations_cache_trash_untrash' );
224 add_action( 'untrash_post', 'wplng_clear_translations_cache_trash_untrash' );
225 add_action( 'delete_post', 'wplng_clear_translations_cache_trash_untrash' );
226
227 // Enqueue Script for wplng_translation admin: Edit
228 add_action( 'admin_print_scripts-post.php', 'wplng_translation_edit_assets' );
229
230 // Enqueue Script for wplng_translation admin: List
231 add_action( 'admin_print_scripts-edit.php', 'wplng_translation_list_assets' );
232
233 // Only show translations for the website languages
234 add_action( 'pre_get_posts', 'wplng_filter_wplng_translation_posts' );
235
236 // Remove Quick edit from translations list
237 add_filter( 'post_row_actions', 'wplng_translation_remove_quick_edit', 10, 2 );
238
239 // Ajax function for regenerate translation on edit page
240 add_action( 'wp_ajax_wplng_ajax_translation', 'wplng_ajax_generate_translation' );
241
242 // Ajax function for edit modal: Get HTML modal
243 add_action( 'wp_ajax_wplng_ajax_edit_modal', 'wplng_ajax_edit_modal' );
244
245 // Ajax function for edit modal: Save modal
246 add_action( 'wp_ajax_wplng_ajax_save_modal', 'wplng_ajax_save_modal' );
247
248 // Ajax function for edit modal: HeartBeat
249 add_action( 'wp_ajax_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
250 add_action( 'wp_ajax_nopriv_wplng_ajax_heartbeat', 'wplng_ajax_heartbeat' );
251
252 // Display 100 translation in admin area by default
253 add_filter( 'get_user_option_edit_wplng_translation_per_page', 'wplng_translation_per_page' );
254
255 // Filter translations by status
256 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_translation_status' );
257 add_filter( 'parse_query', 'wplng_posts_filter_translation_status' );
258
259 // Translation status on website translations list
260 add_filter( 'post_class', 'wplng_post_class_translation_status', 10, 3 );
261 add_filter( 'post_row_actions', 'wplng_post_row_actions_translation_status', 10, 2 );
262 add_filter( 'manage_wplng_translation_posts_columns', 'wplng_translation_status_columns' );
263 add_action( 'manage_wplng_translation_posts_custom_column', 'wplng_translation_status_item', 10, 2 );
264
265 /**
266 * wplng_slug : CPT, taxo, meta
267 */
268
269 // Register wplng_translation CPT
270 add_action( 'init', 'wplng_register_post_type_slug' );
271
272 // Add metabox for wplng_slug
273 add_action( 'add_meta_boxes_wplng_slug', 'wplng_slug_add_meta_box' );
274
275 // Save metabox on posts saving
276 add_action( 'save_post_wplng_slug', 'wplng_slug_save_meta_boxes_data', 10, 2 );
277
278 // Clear slugs cache on trash / untrash
279 add_action( 'trashed_post', 'wplng_clear_slugs_cache_trash_untrash' );
280 add_action( 'untrash_post', 'wplng_clear_slugs_cache_trash_untrash' );
281 add_action( 'delete_post', 'wplng_clear_slugs_cache_trash_untrash' );
282
283 // Enqueue Script for wplng_slug admin: Edit
284 add_action( 'admin_print_scripts-post.php', 'wplng_slug_edit_assets' );
285
286 // Enqueue Script for wplng_slug admin: List
287 add_action( 'admin_print_scripts-edit.php', 'wplng_slug_list_assets' );
288
289 // Only show slugs for the website languages
290 add_action( 'pre_get_posts', 'wplng_filter_wplng_slug_posts' );
291
292 // Remove Quick edit from slugs list
293 add_filter( 'post_row_actions', 'wplng_slug_remove_quick_edit', 10, 2 );
294
295 // Ajax function for regenerate slug on edit page
296 add_action( 'wp_ajax_wplng_ajax_slug', 'wplng_ajax_generate_slug' );
297
298 // Display 100 translation in admin area by default
299 add_filter( 'get_user_option_edit_wplng_slug_per_page', 'wplng_slug_per_page' );
300
301 // Filter slugs by status
302 add_action( 'restrict_manage_posts', 'wplng_restrict_manage_posts_slug_status' );
303 add_filter( 'parse_query', 'wplng_posts_filter_slug_status' );
304
305 // Translation status on website slugs list
306 add_filter( 'post_class', 'wplng_post_class_slug_status', 10, 3 );
307 add_filter( 'post_row_actions', 'wplng_post_row_actions_slug_status', 10, 2 );
308 add_filter( 'manage_wplng_slug_posts_columns', 'wplng_slug_status_columns' );
309 add_action( 'manage_wplng_slug_posts_custom_column', 'wplng_slug_status_item', 10, 2 );
310
311 /**
312 * Front
313 */
314
315 // Enqueue CSS and JS files
316 add_action( 'wp_enqueue_scripts', 'wplng_register_assets' );
317
318 // Add custom inline styles (option page: switcher)
319 add_action( 'wp_head', 'wplng_add_custom_inline_styles', 50 );
320
321 // Script JS in page
322 add_action( 'wp_footer', 'wplng_on_page_script' );
323
324 // Add languages switcher before </body>
325 add_action( 'wp_footer', 'wplng_switcher_wp_footer' );
326
327 // Add languages switcher in nav menu
328 add_filter( 'wp_nav_menu_objects', 'wplng_switcher_nav_menu_replace_items' );
329 add_filter( 'nav_menu_link_attributes', 'wplng_add_nav_menu_link_attributes_atts', 10, 2 );
330
331 // Set alternate links with hreflang parametters
332 add_action( 'wp_head', 'wplng_link_alternate_hreflang', 1 );
333
334 // Disable web browser automatic translation
335 add_action( 'language_attributes', 'wplng_disable_web_browser_auto_translate' );
336
337 // Ajax function for Load in progress
338 add_action( 'wp_ajax_wplng_load_in_progress', 'wplng_ajax_load_in_progress' );
339
340 /**
341 * OB and REQUEST_URI
342 */
343
344 // Manage URL with REQUEST_URI and start OB
345 add_action( 'init', 'wplng_ob_start', 1 );
346
347 // Redirect page if is called with an untranslate slug
348 add_action( 'template_redirect', 'wplng_redirect_translated_slug' );
349
350 /**
351 * Generate JSON translation on the fly for wp-i18n.js
352 */
353
354 // Generate JSON translation
355 add_filter( 'load_script_translation_file', 'wplng_load_script_translation_file', 20, 3 );
356
357 /**
358 * Clear wpLingua cache on updates
359 */
360
361 // Clear wpLingua cache on WordPress core, plugins, themes or translations update
362 add_action( 'upgrader_process_complete', 'wplng_clear_cache_on_update', 10, 2 );
363
364 // Clear wpLingua cache on plugin activation/deactivation
365 add_action( 'activated_plugin', 'wplng_clear_folder_cache' );
366 add_action( 'deactivated_plugin', 'wplng_clear_folder_cache' );
367
368 // Clear wpLingua cache on theme switch
369 add_action( 'switch_theme', 'wplng_clear_folder_cache' );
370
371 // Clear wpLingua cache on site language change
372 add_action( 'update_option_WPLANG', 'wplng_clear_folder_cache' );
373
374 // Clear wpLingua cache on wpLingua settings change
375 add_action( 'update_option_wplng_website_language', 'wplng_clear_folder_cache' );
376 add_action( 'update_option_wplng_target_languages', 'wplng_clear_folder_cache' );
377
378 /**
379 * Features
380 */
381
382 // Make multilingua Sitemap XML for All In One SEO plugin
383 // Il other case, multilingual Sitemap is make by output buffering
384 if ( get_option( 'wplng_sitemap_xml', true )
385 && function_exists( 'aioseo' )
386 ) {
387 add_filter( 'aioseo_sitemap_post', 'wplng_aioseo_filter_sitemap_post', 10, 2 );
388 add_filter( 'aioseo_sitemap_term', 'wplng_aioseo_filter_sitemap_term', 10, 2 );
389 }
390
391 // Search from translated languages
392 if ( ! empty( get_option( 'wplng_translate_search' ) )
393 && wplng_api_feature_is_allow( 'search' )
394 ) {
395 add_action( 'parse_query', 'wplng_translate_search_query' );
396 add_filter( 'get_search_query', 'wplng_search_put_tag' );
397 add_filter( 'wplng_translated_html', 'wplng_search_replace_tag', 5 );
398 } else {
399 add_filter( 'wplng_url_is_translatable', 'wplng_exclude_search', 20 );
400 }
401
402 // Redirect by browser language
403 $browser_language_redirect = get_option( 'wplng_browser_language_redirect' );
404 if ( $browser_language_redirect === 'js_only' ) {
405 add_action( 'wp_head', 'wplng_browser_language_redirect_js_only', 2 );
406 } elseif ( $browser_language_redirect === 'php_js' ) {
407 add_action( 'template_redirect', 'wplng_browser_language_redirect_php_js' );
408 }
409
410 /**
411 * Shortcode
412 */
413
414 add_shortcode( 'wplng_switcher', 'wplng_shortcode_switcher' );
415 add_shortcode( 'wplng_notranslate', 'wplng_shortcode_notranslate' );
416 add_shortcode( 'wplng_only', 'wplng_shortcode_only' );
417
418 /**
419 * Gutenberg
420 */
421
422 add_filter( 'block_categories_all', 'wplng_block_category' );
423 add_action( 'init', 'wplng_register_block' );
424 add_action( 'enqueue_block_editor_assets', 'wplng_register_block_assets' );
425
426 /**
427 * Do action after wpLingua fully initialized
428 */
429
430 do_action( 'wplng_initialized' );
431
432 }
433 }
434 wplng_start();
435
436
437 /**
438 * Delete translation and slug cache options on plugin deactivation.
439 *
440 * @return void
441 */
442 function wplng_deactivate() {
443 delete_option( 'wplng_cached_translations' );
444 delete_option( 'wplng_cached_slugs' );
445 delete_option( 'wplng_api_key_data' );
446 }
447 register_deactivation_hook( __FILE__, 'wplng_deactivate' );
448