Skip to content

Instantly share code, notes, and snippets.

@christianseel christianseel/LanguageMatch Secret
Last active Feb 19, 2018

Embed
What would you like to do?
LanguageMatch MODX Snippet – Redirects the visitor based on it's browser language (this snippets expects that your context_key is similar to the cultureKey)
<?php
// code by http://stackoverflow.com/a/3771447
// parse list of comma separated language tags and sort it by the quality value
function parseLanguageList($languageList) {
if (is_null($languageList)) {
if (!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
return array();
}
$languageList = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
}
$languages = array();
$languageRanges = explode(',', trim($languageList));
foreach ($languageRanges as $languageRange) {
if (preg_match('/(\*|[a-zA-Z0-9]{1,8}(?:-[a-zA-Z0-9]{1,8})*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?/', trim($languageRange), $match)) {
if (!isset($match[2])) {
$match[2] = '1.0';
} else {
$match[2] = (string) floatval($match[2]);
}
if (!isset($languages[$match[2]])) {
$languages[$match[2]] = array();
}
$languages[$match[2]][] = strtolower($match[1]);
}
}
krsort($languages);
return $languages;
}
// compare two parsed arrays of language tags and find the matches
function findMatches($accepted, $available) {
$matches = array();
$any = false;
foreach ($accepted as $acceptedQuality => $acceptedValues) {
$acceptedQuality = floatval($acceptedQuality);
if ($acceptedQuality === 0.0) continue;
foreach ($available as $availableQuality => $availableValues) {
$availableQuality = floatval($availableQuality);
if ($availableQuality === 0.0) continue;
foreach ($acceptedValues as $acceptedValue) {
if ($acceptedValue === '*') {
$any = true;
}
foreach ($availableValues as $availableValue) {
$matchingGrade = matchLanguage($acceptedValue, $availableValue);
if ($matchingGrade > 0) {
$q = (string) ($acceptedQuality * $availableQuality * $matchingGrade);
if (!isset($matches[$q])) {
$matches[$q] = array();
}
if (!in_array($availableValue, $matches[$q])) {
$matches[$q][] = $availableValue;
}
}
}
}
}
}
if (count($matches) === 0 && $any) {
$matches = $available;
}
krsort($matches);
return $matches;
}
// compare two language tags and distinguish the degree of matching
function matchLanguage($a, $b) {
$a = explode('-', $a);
$b = explode('-', $b);
for ($i=0, $n=min(count($a), count($b)); $i<$n; $i++) {
if ($a[$i] !== $b[$i]) break;
}
return $i === 0 ? 0 : (float) $i / count($a);
}
//echo '<pre>';
$accepted = parseLanguageList($_SERVER['HTTP_ACCEPT_LANGUAGE']);
//print_r($accepted);
$available = parseLanguageList($modx->getOption('babel.contextKeys',null,'en'));
//print_r($available);
$matches = findMatches($accepted, $available);
//print_r($matches);
if (!empty($matches)) {
$matched_lang = array_shift(array_values($matches));
$matched_lang = $matched_lang[0];
} else {
$matched_lang = 'en';
}
$context = $modx->getContext($matched_lang);
if (!$context) return 'CONTEXT NOT FOUND. (ERROR IN LANGUAGEMATCH SNIPPET)';
$site_start = $context->getOption('site_start',null,$modx->getOption('site_start',null,1));
$url = $modx->makeUrl($site_start);
$modx->sendRedirect($url, array('responseCode' => 'HTTP/1.1 302 Found'));
return;
@Indigo744

This comment has been minimized.

Copy link

commented Feb 19, 2018

My fork: https://gist.github.com/Indigo744/0ef52f95525b32b9da5dda738be55374
With context prefix/suffix and default context support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.