PluginProbe
Translate and Go multilingual – Automatic AI translation – wpLingua / 2.10.0
Translate and Go multilingual – Automatic AI translation – wpLingua v2.10.0
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 1.1.1 All 111 releases
wplingua / inc / url.php

url.php in Translate and Go multilingual – Automatic AI translation – wpLingua 2.10.0, at inc/url.php

425 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // If this file is called directly, abort.
4 if ( ! defined( 'WPINC' ) ) {
5 die;
6 }
7
8
9 /**
10 * Get the translated URL
11 *
12 * @param string $url
13 * @param string $language_target_id
14 * @return string Translated URL
15 */
16 function wplng_url_translate( $url, $language_target_id = '' ) {
17 return apply_filters(
18 'wplng_url_translate',
19 wplng_url_translate_no_filter(
20 $url,
21 $language_target_id
22 )
23 );
24 }
25
26
27 /**
28 * Get the translated URL - No apply 'wplng_url_translate' filter
29 *
30 * @param string $url
31 * @param string $language_target_id
32 * @return string Translated URL
33 */
34 function wplng_url_translate_no_filter( $url, $language_target_id = '' ) {
35
36 // Check if URL is an empty string
37 if ( '' === $url ) {
38 return '';
39 }
40
41 // Get current target ID if not set
42 if ( '' === $language_target_id ) {
43 $language_target_id = wplng_get_language_current_id();
44 }
45
46 // Apply links / Medias rules
47 $url_link_media_applied = wplng_link_media_apply_rules(
48 $url,
49 $language_target_id
50 );
51
52 // Check if a links / Medias rules was applied
53 if ( $url_link_media_applied !== $url ) {
54 return $url_link_media_applied;
55 }
56
57 // Check if URL is not translatable (exclude /admin/, ...)
58 if ( ! wplng_url_is_translatable( $url ) ) {
59 return $url;
60 }
61
62 $languages_target = wplng_get_languages_target();
63 $preg_domain = '';
64 $parsed_url_home = wp_parse_url( home_url() );
65
66 if ( isset( $parsed_url_home['host'] )
67 && is_string( $parsed_url_home['host'] )
68 ) {
69 $preg_domain = preg_quote( $parsed_url_home['host'] );
70 }
71
72 if ( ! empty( $preg_domain )
73 && preg_match( '#^(http:\/\/|https:\/\/)?' . $preg_domain . '(.*)$#', $url )
74 ) {
75
76 /**
77 * It's an URL starting y a domain name
78 */
79
80 // Check if URL is already translated
81 foreach ( $languages_target as $language_target ) {
82 if ( wplng_str_contains( $url, '/' . $language_target['id'] . '/' ) ) {
83 return $url;
84 }
85 }
86
87 $parsed_url = wp_parse_url( $url );
88
89 if ( ! empty( $parsed_url['path'] ) ) {
90 $url = str_replace(
91 $parsed_url['path'],
92 wplng_slug_translate_path(
93 $parsed_url['path'],
94 $language_target_id
95 ),
96 $url
97 );
98 }
99
100 $url = preg_replace(
101 '#^(http:\/\/|https:\/\/)?' . $preg_domain . '(.*)$#',
102 '${1}' . $parsed_url_home['host'] . '/' . $language_target_id . '${2}',
103 $url
104 );
105
106 if ( empty( $parsed_url['fragment'] )
107 && empty( $parsed_url['query'] )
108 ) {
109 // Add slash at the end if is not an anchor link
110 $url = trailingslashit( $url );
111 }
112 } elseif ( preg_match( '#^[^\/]+\/[^\/].*$|^\/[^\/].*$#', $url ) ) {
113
114 /**
115 * It's a path
116 */
117
118 // Check if URL is already translated
119 foreach ( $languages_target as $language_target ) {
120 if ( substr( $url, 0, 4 ) == '/' . $language_target['id'] . '/'
121 || substr( $url, 0, 3 ) == $language_target['id'] . '/'
122 ) {
123 return $url;
124 }
125 }
126
127 $url = wplng_slug_translate_path(
128 $url,
129 $language_target_id
130 );
131
132 if ( wplng_str_starts_with( $url, '/' ) ) {
133 $url = '/' . $language_target_id . $url;
134 } else {
135 $url = $language_target_id . '/' . $url;
136 }
137 }
138
139 return $url;
140 }
141
142
143 /**
144 * Return true is $url is translatable
145 *
146 * @param string $url
147 * @return bool
148 */
149 function wplng_url_is_translatable( $url = '' ) {
150
151 global $wplng_request_uri;
152
153 // Get current URL if $url is empty
154 if ( '' === $url ) {
155 $url = sanitize_url( $wplng_request_uri );
156 }
157
158 $url = trailingslashit( $url );
159 $url = wp_make_link_relative( $url );
160 $url = strtolower( $url );
161
162 return apply_filters(
163 'wplng_url_is_translatable',
164 wplng_url_is_translatable_no_filter( $url ),
165 $url
166 );
167 }
168
169
170 /**
171 * Return true is $url is translatable - No apply 'wplng_url_translate' filter
172 *
173 * @param string $url
174 * @return bool
175 */
176 function wplng_url_is_translatable_no_filter( $url ) {
177
178 // Check if is an admin page
179 if ( wplng_str_contains( $url, wp_make_link_relative( get_admin_url() ) ) ) {
180 return false;
181 }
182
183 // Check if URL is an anchor link for the current page
184 if ( wplng_str_starts_with( $url, '#' ) ) {
185 return false;
186 }
187
188 // Don't translate some WordPress and WooCommerce URLs
189 // admin, REST API, rss and other special URLs
190 if ( wplng_str_contains( $url, 'wp-login.php' )
191 || wplng_str_contains( $url, 'wp-register.php' )
192 || wplng_str_contains( $url, 'wp-comments-post.php' )
193 || wplng_str_contains( $url, 'wp-cron.php' )
194 || wplng_str_contains( $url, 'xmlrpc.php' )
195 || wplng_str_ends_with( $url, '/feed/' )
196 || wplng_str_contains( $url, '/wp-json/' )
197 || wplng_str_contains( $url, '/wp-includes/' )
198 || wplng_str_contains( $url, '/oembed/' )
199 || wplng_str_contains( $url, '?wc-ajax=' )
200 || wplng_str_contains( $url, '?feed=' )
201 || wplng_str_contains( $url, '?embed=' )
202 || wplng_str_contains( $url, '&wc-ajax=' )
203 || wplng_str_contains( $url, '&feed=' )
204 || wplng_str_contains( $url, '&embed=' )
205 || wplng_str_contains( $url, 'builder=true&builder_id=' ) // Fusion builder
206 ) {
207 return false;
208 }
209
210 // Check if is Divi editor
211 if ( current_user_can( 'edit_posts' )
212 && (
213 wplng_str_contains( $url, '/?et_fb=1' )
214 || wplng_str_contains( $url, '&et_fb=1' )
215 )
216 ) {
217 return false;
218 }
219
220 // Check if is in wp-uploads
221 if ( wplng_str_contains( $url, wp_make_link_relative( content_url() ) ) ) {
222 return false;
223 }
224
225 // Exclude files URL
226 $regex_is_file = '#\.(avi|css|js|docx?|exe|gif|html?|jfif|jpe?g|webp|bmp|midi?|mp3|mpe?g|avif|mov|qt|pdf|png|ra?m|rar|tiff?|txt|wav|zip|ico|xml|rss|xls[x]?|ttf|otf|woff2?|eot|svg)?\/$#i';
227
228 if ( preg_match( $regex_is_file, $url ) ) {
229 return false;
230 }
231
232 // Check if URL is excluded in option page
233 $url_original = wplng_get_url_original( $url );
234 $url_exclude_regex = wplng_get_url_exclude_regex();
235
236 foreach ( $url_exclude_regex as $regex ) {
237 if ( preg_match( $regex, $url_original ) ) {
238 return false;
239 }
240 }
241
242 return true;
243 }
244
245
246 /**
247 * Get the REGEX list of excluded URLs
248 *
249 * @return array
250 */
251 function wplng_get_url_exclude_regex() {
252
253 global $wplng_url_exclude_regex;
254
255 if ( null !== $wplng_url_exclude_regex ) {
256 return $wplng_url_exclude_regex;
257 }
258
259 $url_exclude = array();
260
261 // Get, check and sanitize excluded URL REGEX as string
262 $option = get_option( 'wplng_excluded_url' );
263 if ( empty( $option ) || ! is_string( $option ) ) {
264 $option = '';
265 } else {
266 $option = sanitize_textarea_field( $option );
267 }
268
269 // Get exclude URL REGEX as array
270 $option = explode( PHP_EOL, $option );
271
272 // Check each URL REGEX
273 foreach ( $option as $regex ) {
274 $regex = trim( $regex );
275 if ( '' !== $regex ) {
276 $url_exclude[] = '#' . $regex . '#';
277 }
278 }
279
280 // Remove duplicate
281 $url_exclude = array_unique( $url_exclude );
282
283 // Apply wplng_url_exclude_regex filter
284 $url_exclude = apply_filters(
285 'wplng_url_exclude_regex',
286 $url_exclude
287 );
288
289 $wplng_url_exclude_regex = $url_exclude;
290
291 return $url_exclude;
292 }
293
294
295 /**
296 * Get the untranslated / original URL
297 *
298 * @param string $url
299 * @return string
300 */
301 function wplng_get_url_original( $url = '' ) {
302
303 if ( '' === $url ) {
304 $url = wplng_get_url_current();
305 }
306
307 $target = wplng_get_languages_target_ids();
308
309 foreach ( $target as $target_id ) {
310
311 if ( ! wplng_str_contains( $url, '/' . $target_id . '/' ) ) {
312 continue;
313 }
314
315 $url = str_replace(
316 '/' . $target_id . '/',
317 '/',
318 $url
319 );
320
321 $parsed_url = wp_parse_url( $url );
322
323 if ( isset( $parsed_url['path'] )
324 && $parsed_url['path'] !== ''
325 && $parsed_url['path'] !== '/'
326 ) {
327
328 $url = str_replace(
329 $parsed_url['path'],
330 wplng_slug_original_path(
331 $parsed_url['path'],
332 $target_id
333 ),
334 $url
335 );
336 }
337
338 break;
339 }
340
341 $url = apply_filters(
342 'wplng_url_original',
343 $url
344 );
345
346 return $url;
347 }
348
349
350 /**
351 * Get current path
352 *
353 * @return string
354 */
355 function wplng_get_path_current() {
356 global $wplng_request_uri;
357 return $wplng_request_uri;
358 }
359
360
361 /**
362 * Get current URL
363 *
364 * @return string
365 */
366 function wplng_get_url_current() {
367 return home_url( wplng_get_path_current() );
368 }
369
370
371 /**
372 * Get the URL translated in specified language
373 *
374 * @param string $language_id
375 * @return string
376 */
377 function wplng_get_url_current_for_language( $language_id ) {
378 return wplng_url_translate(
379 wplng_get_url_original(),
380 $language_id
381 );
382 }
383
384
385 /**
386 * Determines whether a given URL points to a sitemap XML file.
387 *
388 * This function checks if the URL matches common sitemap naming patterns such as:
389 * - sitemap.xml
390 * - sitemap_index.xml
391 * - sitemap-posts.xml
392 * - posts-sitemap.xml
393 * and similar variations.
394 *
395 * If no URL is provided, the current URL will be used.
396 * The check ignores query parameters and anchors.
397 *
398 * @param string $url The URL to check. Defaults to the current URL if empty.
399 * @return bool True if the URL is identified as a sitemap, false otherwise.
400 */
401 function wplng_url_is_sitemap_xml( $url = '' ) {
402
403 if ( '' === $url ) {
404 $url = wplng_get_url_current();
405 }
406
407 // Normalize the URL: convert to lowercase
408 $url = strtolower( $url );
409
410 // Remove GET parameters and anchors
411 $parsed_url = wp_parse_url( $url );
412 $url_path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '';
413
414 // Check if the URL matches common sitemap patterns
415 $is_sitemap = str_contains( $url_path, 'sitemap' ) && str_contains( $url_path, '.xml' );
416
417 /**
418 * Filter to allow customization of the sitemap detection logic
419 *
420 * @param bool $is_sitemap Whether the URL is a sitemap.
421 * @param string $url The URL being checked.
422 */
423 return apply_filters( 'wplng_url_is_sitemap_xml', $is_sitemap, $url );
424 }
425