Detect prefered language
The following is imho easier to read and should give you best performance.

&lt;?php

/**
 * Get a sorted list of client accepted languages.
 *
 * @staticvar array $examined
 *   Used to cache the sorted list for &lt;var&gt;$accept_languages&lt;/var&gt; strings.
 * @param boolean $list [optional]
 *   Whether to get a sorted list or the language with the highest preference, defaults to &lt;code&gt;FALSE&lt;/code&gt; and
 *   the language with the highest preference will be returned.
 * @param string $accept_languages [optional]
 *   The client submitted accept languages string in the format defined in RFC 2616.
 * @param string $default [optional]
 *   The default ISO 639-1 alpha-2 language code to use if no other language could be determined, defaults to
 *   &lt;code&gt;"en"&lt;/code&gt;.
 * @return array|string
 *   Associative array where the key is the language code or locale and the value the preference if &lt;var&gt;$list&lt;/var&gt;
 *   is set to &lt;code&gt;TRUE&lt;/code&gt;, otherwise the ISO 639-1 alpha-2 code or locale of the language with the highest
 *   preference.
 */
function get_client_preferred_language($list = false, $accept_languages = null, $default = "en") {
  static $examined = array();

  // Either use the supplied string or use the string from server input, this construct ensures highest performance
  // because a positive check is performed.
  $accept_languages || ($accept_languages = filter_input(INPUT_SERVER, "HTTP_ACCEPT_LANGUAGE", FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH));

  // Only examine this string if we haven't done so in the past.
  if (empty($examined[$accept_languages])) {
    // Prepare default fallback in our cache for this string.
    $examined[$accept_languages] = array($default =&gt; 1.0);

    // Only continue if we have a string to examine.
    if ($accept_languages) {
      // Prepare array for collecting the preferred languages.
      $languages = array();

      // Extract all languages from the accept languages string, the format is defined in RFC 2616.
      preg_match_all("/([a-z]+(?:-[a-z]+)?)\s*(?:;\s*q\s*=\s*(1|0?\.[0-9]+))?/i", $accept_languages, $matches);

      // Only go through all extracted languages if we have any.
      if (!empty($matches[1])) {
        foreach ($matches[1] as $delta =&gt; $code) {
          // Empty means highest preference.
          $languages[$code] = empty($matches[2][$delta]) ? 1.0 : (float) $matches[2][$delta];
        }

        // Sort the accepted languages by preference, if sorting fails use default.
        if (arsort($languages, SORT_NUMERIC) === true) {
          $examined[$accept_languages] = $languages;
        }
      }
    }
  }

  return $list ? $examined[$accept_languages] : array_values($examined[$accept_languages])[0];
}


// ----------------------------------------------------------------------------------------------------------------- Test


function get_client_preferred_language_test() {
  assert(array(
    "en-US" =&gt; 1.0,
    "en"    =&gt; 1.0,
    "en-AU" =&gt; 0.8,
    "fr"    =&gt; 0.6,
    "en-GB" =&gt; 0.4,
  ) === get_client_preferred_language(true, "en,en-US,en-AU;q=0.8,fr;q=0.6,en-GB;q=0.4"));
}

get_client_preferred_language_test();