12

Translate Maintenance mode per website in multi website-multi domain setup

What is the proper way of translating (localisation) Maintenance page in a multi-website and multi-domain environment?

Setup's made into:

  • MAGENTO_ROOT/index.php
  • MAGENTO_ROOT/uk/index.php
  • MAGENTO_ROOT/us/index.php
  • MAGENTO_ROOT/somecode/index.php

Let's assume that the stores are accesible through:

I can easily see few solutions for it but all of theem seems to be more of a workaround than actual nice, clean solutions.

How do you solve this issue?

10
+50

By default Magento doesn't support translation out-of-box for error pages, and requires some customizations to allow for such features. So technically there is no proper way to do such.

Since the full stack is NOT initialized during error generation, normal translation functionality $this->__('foobar'); won't work in the templates.

Some details on how the error pages are generated can be found on MageBase:

One option is to simply copy errors/ into each of your sub directories of your languages uk, us, etc. and modify the templates to reflect the languages of the website entry point of the end user.

Just note your index.php of each view to include the sub relative errors docs:

if (file_exists($maintenanceFile)) {
    include_once dirname(__FILE__) . '/errors/503.php';
    exit;
}

Also be aware there is a base template for all errors, including 404 in the page.html

There are probably more elegant solutions but since you are already duplicating index.php for different views, a few more files may not be too much clutter. You could also modify the templates to include the top level CSS and images to save some redundancy.

You could also create a language file the same as you do in Magento's standard localization and read the values in with the process.php file, as title and some other data that would need localization is being set there. A simple example of using Varien_File_Csv to read a language .CSV file:

$csvObject = new Varien_File_Csv();
$csvObject->getData($file);

Additional note: Since the stack at the current point of run time may not allow for the Varien_File_Csv class inclusion using the internal PHP function fgetcsv may be a better alternative.

And parse the language CSV file needed to populate the required data in the process.php file.

Another alternative would be to simply add Google translate or such 3rd party tool to automatically translate the error pages to the end users language.

References:

2

As mentioned before there's no easy way to translate maintenance page. There's one workaround for it however (which has it's own number of advantages/disadvantages) -- use some of the maintenance mode extensions, such as this one:

http://www.magentocommerce.com/magento-connect/store-maintenance.html

It displays maintenance mode page AFTER Magento stack has been loaded, which means that you need to have database connection and few other things. Because of that it's also slower and requires more resources. But if it's not an issue for you, it renders the maintenance page fully customisable.

  • What will be the output if i.e. the connection to database will be interrupted? – versedi Nov 9 '15 at 6:24
  • 1
    I said, it's workaround and not suitable for every case. If the database is not there Magento will display an error message. – Pronto Nov 9 '15 at 18:59
2

Update:

Found another way for translated maintenance page:

https://github.com/OpenMage/magento-lts/blob/1.9.3.x/errors/processor.php#L160-L162

    if (isset($_GET['skin'])) {
        $this->_setSkin($_GET['skin']);
    }

The maintenance page constructor accecpts a skin POST parameter to change layout. It seems to be the intentional way, but it not documentated (yet) ...

  1. Add some rewrite rules to your .htaccess that appends a skin parameter to your URL. Eg.

    RewriteCond %{HTTP_HOST} ^french.example.com$
    RewriteCond %{DOCUMENT_ROOT}/.maintenance.flag -f
    RewriteCond %{QUERY_STRING} !(^|&)skin=french(&|$) [NC]
    RewriteRule ^ %{REQUEST_URI}?skin=french[L]
    
  2. Copy errors/default to errors/french

  3. Change/translate template files to your needs

Maybe bit late, but a good working solution, without copying error directory to every subfolder ...

"Downsides":

  • you have to edit three core files. To avoid edits in core as much as possible I just changed include path of error/report pages and extended processor.php to read a modified local.xml.
  • it still requires template files for every language (no translation at the moment - maybe later)

Basic setup

Multi-website multi-store set-up like this, only differnce is that I've set MAGE_RUN_CODE in .htaccess instead of index.php. For 1st domain I use no RUN_CODE all others it looks like ...

RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule .* - [E=MAGE_RUN_CODE:website1]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule .* - [E=MAGE_RUN_TYPE:website]

In addition to the linked answer I had to set RewriteBase in .htaccess to match locale directory and edit index.php in en, fr and change

$maintenanceFile = 'maintenance.flag';
...
if (file_exists($maintenanceFile)) {
    include_once dirname(__FILE__) . '/errors/503.php';
    exit;
}

to

$maintenanceFile = '../maintenance.flag';
...
if (file_exists($maintenanceFile)) {
    include_once '../errors/503.php';
    exit;
}

Edit errors/404.php, 503.php and report.php

Replace

require_once 'processor.php';
$processor = new Error_Processor();

with

require_once 'processor_multiwebsite.php';
$processor = new Error_Processor_Multiwebsite();

And add this to errors/processor_multiwebsite.php

<?php
require_once 'processor.php';
class Error_Processor_Multiwebsite extends Error_Processor
{
    const DEFAULT_RUNCODE = 'default';
    const DEFAULT_LOCALE = 'default';

    /**
     * Magento run code
     *
     * @var string
    */
    protected $_runCode;

    /**
     * Magento run code
     *
     * @var string
    */
    protected $_locale;

    public function __construct()
    {
        $this->_runCode = self::DEFAULT_RUNCODE;
        if (isset($_SERVER['MAGE_RUN_CODE'])) {
            $this->_runCode = $_SERVER['MAGE_RUN_CODE'];
        }

        $this->_locale = self::DEFAULT_LOCALE;
        $path = array_filter(explode('/', str_replace('index.php', '', $_SERVER['SCRIPT_NAME'])));
        if (end($path)) {
            $this->_locale = end($path);
        }

        parent::__construct();
    }

    /**
     * Retrieve skin URL
     *
     * @return string
     */
    public function getSkinUrl()
    {
        $baseUrl = str_replace($this->_locale . '/', '', $this->getBaseUrl());
        return $baseUrl . self::ERROR_DIR. '/' . $this->_config->skin . '/';
    }


    /**
     * Retrieve skin base URL
     *
     * @return string
     */
    public function getSkinBaseUrl($file)
    {
        return $this->_config->skin_base ? "../{$this->_config->skin_base}/{$file}" : $file;
    }

    /**
     * Prepare config data
     */
    protected function _prepareConfig()
    {
        parent::_prepareConfig();

        $local  = $this->_loadXml(self::MAGE_ERRORS_LOCAL_XML);
        if (!is_null($local)) {
            if ((string)$local->{$this->_runCode}->{$this->_locale}->skin) {
                $this->_config->skin = (string)$local->{$this->_runCode}->{$this->_locale}->skin;
            }
            # add skin base URL
            if ((string)$local->{$this->_runCode}->{$this->_locale}->skin_base) {
                $this->_config->skin_base = (string)$local->{$this->_runCode}->{$this->_locale}->skin_base;
            }
        }
    }
}

New local.xml structure

Instead of setting<skin> at the first level look for websites runcode/locale first

<?xml version="1.0"?>
<config>
    <!-- 1st domain w/o runcode -->
    <default>
        <!-- no locale sub dir -->
        <default>
            <skin>default-default</skin>
            ...
        </default>
        <en>
            <skin>default-en</skin>
            <skin_base>default-default</skin_base>
            ...
        </en>
        <fr>
            <skin>default-fr</skin>
            <skin_base>default-default</skin_base>
            ...
        </fr>
    </default>
    <!-- runcode website1 -->
    <website1>
        <!-- no locale sub dir -->
        <default>
            <skin>website1-default</skin>
            ...
        </default>
        ...
    </website1>
</config>

Templates

Add 503.phtml, ... , CSS to directories matching <runcode>-<locale>

  • default-default (1st domain default language)
  • default-en
  • default-fr
  • website1-default (2nd domain default language)
  • ...

No duplicate CSS/images

  • put your website specific CSS/images files into one directory and add <skin_base> node to local.xml
  • change ALL static links in page.phtml files from i.e. href="css/styles.css" to <?php echo $this->getSkinBaseUrl('css/styles.css')?>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.