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

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