-
-
Save sebastian-marinescu/4b2991bc40dbbc405257ba5846adb1ef to your computer and use it in GitHub Desktop.
<?php | |
/** | |
* LanguageMatch | |
* | |
* Based on https://gist.github.com/christianseel/504302ce8ddfcde009c0 | |
* Original code by http://stackoverflow.com/a/3771447 | |
* | |
* Updated by Indigo74 & x-vance for prefix/suffix and default context | |
*/ | |
$snippetName = 'LanguageMatch'; | |
// Verify required parameters | |
if (!isset($scriptProperties['ctxDefault'])) { | |
$modx->log(modX::LOG_LEVEL_ERROR, '['.$snippetName.'] is missing required property &ctxDefault!'); | |
return; | |
} | |
// Store parameters | |
define('CONTEXT_PREFIX', $modx->getOption('ctxPrefix', $scriptProperties, '')); | |
define('CONTEXT_SUFFIX', $modx->getOption('ctxSuffix', $scriptProperties, '')); | |
define('DEFAULT_CONTEXT', $modx->getOption('ctxDefault', $scriptProperties, 'web')); | |
// 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); | |
$babelKeys = $modx->getOption('babel.contextKeys',null,'en'); | |
$patternCtx = '/' . CONTEXT_PREFIX . '(\w+)' . CONTEXT_SUFFIX . '/i'; | |
$languageKeys = preg_replace($patternCtx, '$1', $babelKeys); | |
$available = parseLanguageList($languageKeys); | |
//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(CONTEXT_PREFIX . $matched_lang . CONTEXT_SUFFIX); | |
if (!$context) { | |
$context = $modx->getContext(DEFAULT_CONTEXT); | |
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; |
In that case, you will have to adapt the script for your needs.
You could simplify the script drastically and just check manually if user/browser wants Russian, then send to "ru", if not, send to "web"; done.
Oh, hard work, I am not a developer)) Will try, thank you a lot.
Ahhhh, I remember :)
But I also remember, that you can change the key in the database.
Can you login to phpMyAdmin and change it there?(if for some reason you can't, another idea I have is: duplicate the contexts with all it's contents and give it a new key)
Is it right, that the snippet doesn't allow you to change language by babellinks? It will switch context every time, as I understand
It was intended to be used like this originally:
I have copied web context to "en" and now I have three of them, web (/), en (/en/) and ru (/ru/). This code on the mainpage of "Web":
[[!LanguageMatch?
&ctxDefault=`en`
&ctxPrefix=``
]]
Ru is opening good, but my english Firefox send this:
Array ( [0.5] => Array ( [0] => en ) ) CONTEXT NOT FOUND. (ERROR IN LANGUAGEMATCH SNIPPET)
Help me pls, I don't understand, why there is impossible to find "en" context. (babel.contextKeys is "en,ru", default_context is "en").
Error log
[2021-04-23 14:21:42] (ERROR @ /home/k/komatera/polustrade.com/public_html/core/model/modx/modx.class.php : 1031) `0` is not a valid integer and may not be passed to makeUrl()
[2021-04-23 14:21:42] (ERROR in resource 3 @ /home/k/komatera/polustrade.com/public_html/core/model/modx/modparser.class.php : 1373) Bad link tag `[[~0]]` encountered
I uncommented "print" commands and that, what I have got:
Array
(
[1.0] => Array
(
[0] => en-us
)
[0.5] => Array
(
[0] => en
)
)
Array
(
[1.0] => Array
(
[0] => en
[1] => ru
)
)
Array
(
[0.5] => Array
(
[0] => en
)
)
CONTEXT NOT FOUND. (ERROR IN LANGUAGEMATCH SNIPPET)
No resoursces after renaming)) Not good variant. It's doesn't work.
Copying context seems to be hard, bacause I have to chain every resource in babel :(
May be there is a variant to add some sort of parameter, where I can match "web" context to "en" cultureKey? Every next context will have the Key similar to it's cultureKey, but "web" is the problem...