Skip to content

Instantly share code, notes, and snippets.

@enminc
Forked from gadamiak/LangRouter.php
Created February 13, 2013 23:01

Revisions

  1. @gadamiak gadamiak created this gist Oct 1, 2012.
    138 changes: 138 additions & 0 deletions LangRouter.php
    Original file line number Diff line number Diff line change
    @@ -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'));
    }

    }