Domain based localization in PyroCMS

Sometimes a project needs multiple domains. Perhaps it is for the SEO reasons, perhaps a company is using different business names in different countries or perhaps your client just thinks it is a cool idea. Also all these domains must have a different default locale. Usually it is pretty messy to achieve, but with PyroCMS it is a no-brainer.

For the demo purposes i created one PyroCMS 3.4 installation with following domains:

  • pyrocms.app
  • estonian.app
  • russian.app

All the domains may also have www prefix and they all point to a single PyroCMS installation.

For testing purposes i slightly modified the default page layout so it would always show the working locale.

Multilingual setup

Before the multidomain setup, you need to enable locales in PyroCMS. For this demo i checked english, estonian and russian. System default remained english.

Opposite to mainstream content management systems like Wordpress and Joomla, PyroCMS does not care about the domain it is using.

Hacking the kernel

One of the best features of PyroCMS is its Laravel foundation. Laravel is extremely hackable and extendable PHP framework and all that can be done in Laravel, can be done in PyroCMS. Well almost :P

To enable domain based default locales, you need to extend the streams kernel where you figure out which locale should be used for each domain.

You could place your customized kernel where ever you want, but following the Laravel convention the correct place is

app/Http/Kernel.php

<?php

namespace App\Http;

use Anomaly\Streams\Platform\Http\Kernel as StreamsKernel;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Routing\Router;

class Kernel extends StreamsKernel
{
    protected $domains = [
        'estonian.app' => 'et',
        'russian.app' => 'ru'
    ];

    public function __construct(Application $app, Router $router)
    {
        $hostname = preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']);

        if (isset($this->domains[$hostname])) {
            putenv('DEFAULT_LOCALE='.$this->domains[$hostname]);
        }

        parent::__construct($app, $router);
    }
}

For the final act you need to swap the streams kernel with your custom one in bootstrap/app.php

$app->singleton(
Illuminate\Contracts\Http\Kernel::class,
'App\Http\Kernel'
);

And now you can have a different default locale for each domain. If a domain is not described in Kernel.php the locale will fall back to what ever you have set it in your system. Have fun!