Created
October 1, 2012 16:31
-
-
Save gadamiak/3812853 to your computer and use it in GitHub Desktop.
Language context router for use with Babel extra for MODX Revolution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* LangRouter | |
* ========== | |
* | |
* This plugin is meant to be used with Babel extra for MODX Revolution. It | |
* takes care of switching contexts, which hold translations, depending on URL | |
* requested by client. LangRouter works with so called subfolder based setup, | |
* in which many languages are served under a single domain but are | |
* differentiated by a virtual subfolder indicating the language, eg. | |
* mydomain.com/pl/. | |
* | |
* The routing work as follows: | |
* - if URI contains cultureKey, which is defined in Babel configuration, then | |
* the matching context is served | |
* - if URI doesn't contain cultureKey (or one not defined in Babel | |
* configuration) AND at least one of the client's accepted languages is | |
* defined in Babel configuration, then the matching context is served | |
* - otherwise the default context is served | |
* | |
* LangRouter works out-of-the-box and doesn't require any changes to URL | |
* rewrite rules in the webserver configuration. All routing is handled | |
* internally by MODX. This greatly simplifies the setup and provides | |
* portability. LangRouter was tested with Apache and Lighttpd. | |
* | |
* Setup: | |
* 1. Prepare your contexts as you normally would for Babel. | |
* 2. For each context set `base_url` to `/`. | |
* 3. For each context set `site_url` to | |
* `{server_protocol}://{http_host}{base_url}{cultureKey}/` | |
* 4. Add new system setting `babel.contextDefault` and set it to the default | |
* context, which should be served when no language is specified in | |
* request, eg. `pl`. | |
* 5. Include static files from the assets folder with | |
* `[[++assets_url]]path/to/static_file`. | |
* 6. In template header use `<base href="[[++site_url]]" />`. | |
* 7. Use default URL generation scheme in MODX (ie. relative). | |
* | |
* This code is shared AS IS. Use at your own risk. | |
*/ | |
if($modx->context->get('key') != "mgr") { | |
/* | |
* Debugs request handling | |
*/ | |
function logRequest($message = 'Request') | |
{ | |
global $modx; | |
$modx->log(modX::LOG_LEVEL_ERROR, $message . ':' | |
. "\n REQUEST_URI: " . $_SERVER['REQUEST_URI'] | |
. "\n REDIRECT_URI: " . $_SERVER['REDIRECT_URI'] | |
. "\n QUERY_STRING: " . $_SERVER['QUERY_STRING'] | |
. "\n q: " . $_REQUEST['q'] | |
. "\n Context: " . $modx->context->get('key') | |
. "\n Site start: " . $modx->context->getOption('site_start') | |
); | |
} | |
/* | |
* Dumps variables to MODX log | |
*/ | |
function dump($var) { | |
ob_start(); | |
var_dump($var); | |
return ob_get_clean(); | |
} | |
/* | |
* Detects client language preferences and returns associative array sorted | |
* by importance (q factor) | |
*/ | |
function clientLangDetect() | |
{ | |
$langs = array(); | |
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { | |
# break up string into pieces (languages and q factors) | |
preg_match_all('/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*(1|0\.[0-9]+))?/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $lang_parse); | |
if (count($lang_parse[1])) { | |
# create a list like "en" => 0.8 | |
$langs = array_combine($lang_parse[1], $lang_parse[4]); | |
# set default to 1 for any without q factor | |
foreach ($langs as $lang => $val) { | |
if ($val === '') $langs[$lang] = 1; | |
} | |
# sort list based on value | |
arsort($langs, SORT_NUMERIC); | |
return $langs; | |
} | |
} | |
} | |
#logRequest('Unhandled request'); | |
# Get contexts and their cultureKeys | |
$babelContexts = explode(',', $modx->getOption('babel.contextKeys')); | |
$languages = array(); | |
foreach ($babelContexts as $context) { | |
$ctx = $modx->getContext($context); | |
$languages[$ctx->config['cultureKey']] = trim($context); | |
} | |
#$modx->log(modX::LOG_LEVEL_ERROR, dump($languages)); | |
# Determine language from request | |
$reqCultureKeyIdx = strpos($_REQUEST['q'], '/'); | |
$reqCultureKey = substr($_REQUEST['q'], 0, $reqCultureKeyIdx); | |
# Serve the proper context and language | |
if(array_key_exists( | |
strtolower($reqCultureKey), array_change_key_case($languages))) { | |
$modx->switchContext($reqCultureKey); | |
# Remove cultureKey from request | |
$_REQUEST['q'] = substr($_REQUEST['q'], $reqCultureKeyIdx+1); | |
#logRequest('Culture key found in URI'); | |
} else { | |
$clientCultureKey = array_flip( | |
array_intersect_key(clientLangDetect(), $languages)); | |
if($clientCultureKey) { | |
$contextDefault = current($clientCultureKey); | |
} else { | |
$contextDefault = trim($modx->getOption('babel.contextDefault')); | |
} | |
#$modx->log(modX::LOG_LEVEL_ERROR, dump($contextDefault)); | |
$modx->switchContext($contextDefault); | |
#logRequest('Culture key not found in URI'); | |
$modx->sendRedirect($modx->context->getOption('site_url')); | |
} | |
# Serve site_start when no resource is requested | |
if(empty($_REQUEST['q'])) { | |
#$modx->log(modX::LOG_LEVEL_ERROR, 'Query is empty'); | |
$modx->sendForward($modx->context->getOption('site_start')); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
OnHandleRequest, just like the standard plugins.
Another point; there are two places where the key used for the context switch needs to be modified, lines 114 and 127, just before the switchContext functions. Your requirements may be different if your default context is not the system default cultureKey. I added the babel.contextDefault System Setting, then used
if($reqCultureKey == $modx->getOption('cultureKey')) $reqCultureKey = $modx->getOption('babel.contextDefault');
for line 114, and
if($contextDefault == $modx->getOption('cultureKey')) $contextDefault = $modx->getOption('babel.contextDefault');
for line 127.