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 / browser-language.php

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

196 lines 6.1 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 * Outputs a JavaScript snippet to handle browser language-based redirection.
11 *
12 * This function is designed to inject a JavaScript script into the front-end
13 * for redirecting users based on their browser's language settings. It ensures
14 * that the script is only output under specific conditions:
15 * - The user is not logged in with editing permissions.
16 * - The user is not a bot.
17 * - The current page is the front page.
18 * - The current language matches the website's default language.
19 *
20 * If the JavaScript file is missing or empty, the function exits early.
21 *
22 * @return void
23 */
24 function wplng_browser_language_redirect_js_only() {
25
26 if ( current_user_can( 'edit_posts' )
27 || wplng_is_bot()
28 || ! is_front_page()
29 || ( wplng_get_language_website_id() !== wplng_get_language_current_id() )
30 ) {
31 return;
32 }
33
34 $script = file_get_contents( WPLNG_PLUGIN_PATH . '/assets/js/browser-redirect.js' );
35
36 if ( empty( $script ) ) {
37 return;
38 }
39
40 $script = str_replace(
41 '//# sourceMappingURL=browser-redirect.js.map',
42 '',
43 $script
44 );
45
46 echo '<script id="wplingue-browser-redirect-js">' . rtrim( $script ) . '</script>';
47 }
48
49
50 /**
51 * Redirects the user to the translated version of the page based on browser language or a user-defined cookie.
52 *
53 * This function is designed to run on the 'template_redirect' hook. It handles the logic for
54 * redirecting users to the appropriate language version of a page. The redirection is based on
55 * a stored cookie (if available) or the browser's 'Accept-Language' header.
56 *
57 * It prevents redirection for specific user types (e.g., logged-in users with 'edit_posts' capability)
58 * and for known web crawlers and bots.
59 *
60 * @return void
61 */
62 function wplng_browser_language_redirect_php_js() {
63
64 // Exit early for users with editing permissions or for bots to prevent redirection loops.
65 if ( current_user_can( 'edit_posts' )
66 || wplng_is_bot()
67 ) {
68 return;
69 }
70
71 $language_website_id = wplng_get_language_website_id();
72 $language_current_id = wplng_get_language_current_id();
73 $is_translated_page = $language_website_id !== $language_current_id;
74 $cookie = wplng_browser_language_cookie_get();
75
76 // If the user is on a translated page.
77 if ( $is_translated_page ) {
78 // Update the cookie with the selected language code.
79 // This is a voluntary choice by the user.
80 wplng_browser_language_cookie_set( $language_current_id );
81 return;
82 }
83
84 // The user is on the original language page (no language prefix).
85
86 // Determine the language to redirect to.
87 $redirect_language_id = false;
88
89 if ( $cookie !== false ) {
90 // If the cookie contains a valid language code, use it for redirection.
91 // This honors the user's last choice.
92 if ( wplng_is_valid_language_id( $cookie ) ) {
93
94 if ( $cookie === $language_website_id ) {
95 return;
96 } else {
97 $redirect_language_id = $cookie;
98 }
99 }
100 } else {
101 // This is the very first visit (no cookie). Use the browser's language.
102 if ( ! empty( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
103 $langs = explode( ',', sanitize_text_field( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) );
104 if ( ! empty( $langs ) ) {
105 $language_browser_id = strtolower( substr( trim( $langs[0] ), 0, 2 ) );
106 $redirect_language_id = $language_browser_id;
107 }
108 }
109 }
110
111 // Check if the determined language is a valid target language.
112 if ( empty( $redirect_language_id )
113 || ( $redirect_language_id === $language_website_id )
114 || ! in_array( $redirect_language_id, wplng_get_languages_target_ids(), true )
115 ) {
116 // If not, set the cookie to 'original' to prevent future redirects on the original page.
117 wplng_browser_language_cookie_set( $language_website_id );
118 return;
119 }
120
121 // Check if the URL to redirect is translatable.
122 $url_to_redirect = wplng_get_url_current_for_language( $redirect_language_id );
123
124 if ( $url_to_redirect === wplng_get_url_original() ) {
125 wplng_browser_language_cookie_set( $language_website_id );
126 return;
127 }
128
129 // Perform the redirection.
130 wplng_browser_language_cookie_set( $redirect_language_id );
131 wp_safe_redirect(
132 $url_to_redirect,
133 302
134 );
135 exit;
136 }
137
138
139 /**
140 * Retrieves the language code from the 'wplingua-lang' cookie.
141 *
142 * This function safely retrieves the language code stored in the user's cookie,
143 * sanitizing the value to prevent security issues. It returns the language code
144 * if it's valid ('original' or a known language ID), otherwise it returns false.
145 *
146 * @return string|false The language code from the cookie, or false if the cookie is not set or invalid.
147 */
148 function wplng_browser_language_cookie_get() {
149 $cookie = false;
150 if ( ! empty( $_COOKIE['wplingua-lang'] ) ) {
151 $cookie = sanitize_text_field( $_COOKIE['wplingua-lang'] );
152 if ( ! wplng_is_valid_language_id( $cookie ) ) {
153 $cookie = false;
154 }
155 }
156
157 return $cookie;
158 }
159
160
161 /**
162 * Sets the 'wplingua-lang' cookie with a specified language ID.
163 *
164 * This function creates or updates a cookie to store the user's preferred language choice.
165 * The cookie is set to expire in 30 days and is accessible across the site's domain.
166 *
167 * @param string $language_id The language code to be stored (e.g., 'en', 'fr', 'es', or 'original').
168 * @return void
169 */
170 function wplng_browser_language_cookie_set( $language_id ) {
171 setcookie(
172 'wplingua-lang',
173 $language_id,
174 time() + 30 * DAY_IN_SECONDS,
175 COOKIEPATH,
176 COOKIE_DOMAIN
177 );
178 }
179
180
181 /**
182 * Determines if the current user agent is a bot or a web crawler.
183 *
184 * This function checks the user agent string against a predefined list of known bots
185 * using a regular expression. The result is cached for the duration of the request
186 * to improve performance on multiple calls.
187 *
188 * @return bool True if the user agent is a bot, false otherwise.
189 */
190 function wplng_is_bot() {
191 return (bool) preg_match(
192 '/googlebot|bingbot|slurp|duckduckbot|baiduspider|yandex|semrushbot|ahrefsbot|mj12bot|dotbot|exabot|facebookexternalhit/i',
193 strtolower( $_SERVER['HTTP_USER_AGENT'] ?? '' )
194 );
195 }
196