Setting up multiple contexts in Modx for a multi language site

Modx Revolution now has a feature which allows you to set up sites using contexts which map to sub domains.

The documentation for setting these up is currently here.

Once I had followed those instructions, I had multiple domains, one for each language. In this case, the client wanted one for Russia, Middle East and Asia.

There was an additional twist to the language domains. They wanted a news and casestudy domain which would contain a central repository of well, news and casestudies. The idea was that each language domain could create symlink to the case study they wanted. This would give editors the power to pick and choose which case study they wanted to appear on the relevant language site. Should be simple, right?

Unfortunately not. At the moment, the creators of Modx have locked down cross context symlinking and the only way to get around it is to edit the source code. Here’s the offending code in /core/model/modx/modrequest.class.php at line 180.

if ($resource->get('context_key') !== $this->modx->context->get('key')) {

       if (!$this->modx->getCount('modContextResource', 
      array($this->modx->context->get('key'), $resourceId))) {

       return null;

    }

}

A quick amend to comment those lines of code out and voila, symlinking across domains works fine. It’s not great to hack the core of any system, if I’ve time, I might find a way to extend the Request class.

When the user is viewing a case study on the casestudies domain, the client wanted the left hand menu to reflect the language they had initially selected. The menu was generated by Wayfinder and I quickly found that wayfinder doesn’t work across contexts. There’s a snippet called getResources which does but it would mean some extra work to get it to the menu highlight. How to get Wayfinder to work across contexts? I wrapped the Wayfinder call in a snippet.


$desired_context = isset($desired_context) ? $desired_context : 'casestudies';

  $fullLink = isset($fullLink ) ? $fullLink : '0'; 

  global $modx;


$cs_config =array(

  'startId' => $startId,

  'level' => $level,

  'lastClass' => $lastClass,

  'outerTpl' => $outerTpl,

  'rowTpl' => $rowTpl,

  'fullLink' => $fullLink,

  'debug' => isset($debug) ? $debug : FALSE

  );


if($desired_context == $wcontext ) {

  return $modx->runSnippet('wayfinder',$cs_config);


}


//Switch to desired context

  $modx->switchContext($desired_context);

  //Get the wayfinder output

  $output = $modx->runSnippet('wayfinder',$cs_config);

  //Switch back to the original context

  $modx->switchContext($wcontext);


//return the output

  return $output;

The wrapped call is now:

[[!caseStudiesWayfinder? &startId=`44` &level=`1` &lastClass=``
outerTpl=`ThumbOuterTpl` &rowTpl=`ThumbRowTpl` &wcontext=`web` ]]

There’s another important step to make sure that any cross context Wayfinder call or getResources call actually gets pages you want the user to see. You need to add the contexts to the anonymous user, otherwise your Modx error logs will show something like

[-- 13:02:21] (ERROR @ /index.php) Could not load context: mycontext

Go to Security -> Access Controls and then right click (anonymous). Click add context and this should allow your web users to view the different contexts.