Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check_language function - language settings are ignored #28

Closed
CyberFoundry opened this issue Feb 21, 2017 · 3 comments
Closed

check_language function - language settings are ignored #28

CyberFoundry opened this issue Feb 21, 2017 · 3 comments

Comments

@CyberFoundry
Copy link

When the browser doesn't supply the HTTP_ACCEPT_LANGUAGE header, language setting are ignored and postfixadmin always defaults to the $CONF['default_language'] setting.

IMO the desired behavior should not be dependent on the presence of the HTTP_ACCEPT_LANGUAGE header. Eg:

`
function check_language ($use_post = 1) {
global $supported_languages; # from languages/languages.php

$lang = Config::read('default_language');

$lang_array = array();

if (safecookie('lang')) {
    array_unshift($lang_array, safecookie('lang')); # prefer language from cookie
}
if ( $use_post && safepost('lang')) {
    array_unshift($lang_array, safepost('lang')); # but prefer $_POST['lang'] even more
}
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    array_merge($lang_array,preg_split ('/(\s*,\s*)/', $_SERVER['HTTP_ACCEPT_LANGUAGE']));
}

for($i = 0; $i < count($lang_array); $i++) {
    $lang_next = $lang_array[$i];
    $lang_next = strtolower(trim($lang_next));
    $lang_next = preg_replace('/;.*$/', '', $lang_next); # remove things like ";q=0.8"
    if(array_key_exists($lang_next, $supported_languages)) {
        $lang = $lang_next;
        break;
    }
}

return $lang;

}
`

@cboltz
Copy link
Member

cboltz commented Feb 23, 2017

Nice catch - you are right that the POST and COOKIE value should be honored even if HTTP_ACCEPT_LANGUAGE is not set.

I tend to do a slightly different fix - instead of making the function even more confusing with array_merge(), it should handle POST and COOKIE first.

--- a/functions.inc.php
+++ b/functions.inc.php
@@ -139,16 +139,22 @@ function _flash_string($type, $string) {
 function check_language ($use_post = 1) {
     global $supported_languages; # from languages/languages.php
 
+    if ( $use_post && safepost('lang')) {
+        if(array_key_exists(safepost('lang'), $supported_languages)) {
+            return safepost('lang'); # first preference: $_POST['lang']
+        }
+    }
+
+    if (safecookie('lang')) {
+        if(array_key_exists(safecookie('lang'), $supported_languages)) {
+            return safecookie('lang'); # second-best: $_COOKIE['lang']
+        }
+    }
+
     $lang = Config::read('default_language');
 
     if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
         $lang_array = preg_split ('/(\s*,\s*)/', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
-        if (safecookie('lang')) {
-            array_unshift($lang_array, safecookie('lang')); # prefer language from cookie
-        }
-        if ( $use_post && safepost('lang')) {
-            array_unshift($lang_array, safepost('lang')); # but prefer $_POST['lang'] even more
-        }
 
         for($i = 0; $i < count($lang_array); $i++) {
             $lang_next = $lang_array[$i];

I gave this patch only minimal testing (which is also the reason why I didn't commit it yet), so feel free to test and report back ;-)

@CyberFoundry
Copy link
Author

In the meantime I have replaced the function with my own version, that respects HTTP_ACCEPT_LANGUAGE priorities as well. I have also made some basic cleanup like the order of tests etc.

`
function check_language ($use_post = 1) {
global $supported_languages; # from languages/languages.php
$lang_array = array();
$lang = Config::read('default_language');

if ( $use_post && safepost('lang')) {
    $lang_array[strtolower(safepost('lang'))] = 1;
}
if (safecookie('lang')) {
    $lang_array[strtolower(safecookie('lang')] = 1;
}
if(!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
    $langtags = explode(',',strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
    for($i = 0; $i < count($langtags); $i++ )  {
    	$langcode = NULL;
        $langpriority = NULL;
		$langdef = explode(';',$langtags[$i]);
		if (isset($langdef[0])) {
			$langcode = trim($langdef[0]);
		}
        if (isset($langdef[1])) {
			$langpriority = trim($langdef[1]);
		}
		if (!empty($langcode)) {
			$langcode = substr($langcode,0,2);
			if (ctype_alpha($langcode)) {
				$xpriority = 1;
				if (!empty($langpriority) && strpos($langpriority,'q=') === 0) {
					$q = (float)trim(substr($langpriority,2));
					if (is_numeric($q) && $q >= 0 && $q <= 1) {
                    	$xpriority = $q;
					}
				}
				if (!isset($lang_array[$langcode])) {
					$lang_array[$langcode] = $xpriority;
				}
				elseif ($lang_array[$langcode] < $xpriority) {
                	$lang_array[$langcode] = $xpriority;
				}
			}
		}
	}
}

if (count($lang_array) > 0) {
    $bestpriority  = -1;
    foreach ($lang_array as $langcode => $langpriority) {
		if (array_key_exists($langcode, $supported_languages)) {
			if ($bestpriority < $langpriority) {
				$lang = $langcode;
    			$bestpriority = $langpriority;
			}
		}
	}
}

return $lang;

}
`

@cboltz
Copy link
Member

cboltz commented Feb 23, 2017

If $_POST['lang'] or $_COOKIE['lang'] is set, this means the user selected a language manually in the dropdown now ($_POST) or some days ago ($_COOKIE). Therefore $_POST and $_COOKIE should always win - if they contain a valid language, there's no need to check HTTP_ACCEPT_LANGUAGE.

Besides that - honoring the priorities is a nice addition, thanks!

It's clearly worth the additional CPU cycles, but it reminds me to
common.php: $language = check_language (); # TODO: storing the language only at login instead of calling check_language() on every page would save some processor cycles ;-)
;-) which should be doable by storing the language in the session.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants