@@ -0,0 +1,138 @@
<?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 ' ));
}
}