Magento2: Translation does not work for email invoice_new template item layout

Created on 14 Nov 2016  路  3Comments  路  Source: magento/magento2


Preconditions


  1. OS: openSuSE 13.1
  2. Magento 2.1.2 php 5.6.27

Steps to reproduce

  1. create a customized email template by loading invoice_new
  2. create translation csv file in i.e. German under /srv/www/Magento-CE-2.1.1/vendor/magento/language-de_de/de_DE.csv
  3. create invoice and send email

Expected result

  1. All texts in the email are translated to German

Actual result

  1. The texts are translated except the items list in {{layout area="frontend" handle="sales_email_order_invoice_items" invoice=$invoice order=$order}}
  2. It is found that the texts i.e. "Items", "Qty" and "Subtotal" are fixed coded in /srv/www/Magento-CE-2.1.1/vendor/magento/module-sales/view/frontend/templates/email/invoice/items.phtml, which does not follow the translation routine.

Translation Cannot Reproduce Format is valid bug report

Most helpful comment

Hi there,
I debugged this issue and found out that this occurs if you have set your sales email to send in async mode. The problem here is, that the translation is not initialized.

In synchronous mode the translation gets initialized like that:
Magento\Framework\App\Action\Plugin\Design::beforeDispatch() triggers Magento\Framework\View\DesignLoader::load() which therefore inits the translation.
This happens because in synchronous mode a controller action gets executed and therefore beforeDispatch is triggered.

The async mode gets triggered by Magento cron. There is no controller action and therefore the translation is completely missing. As long as Magento does not provide a fix for that, we have to do it on our own. It is indeed a bit tricky to initialize it anyway.

  • The cron sets the area part to crontab and as there is (of course) no design theme for that area part, we have to pay attention to not initialize the complete design
  • Therefore we create a plugin for Magento\Sales\Model\EmailSenderHandler::sendEmails() which initializes the translation if emails get send in async mode

di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Model\EmailSenderHandler">
        <plugin name="sendSalesEmails" type="Vendor\Module\Plugin\EmailSenderHandler"/>
    </type>
</config>

Vendor\Module\Plugin\EmailSenderHandler.php:

<?php

namespace Vendor\Module\Plugin;

use \Magento\Framework\App\Config\ScopeConfigInterface;
use \Magento\Framework\App\AreaList;
use \Magento\Framework\App\State;
use \Magento\Framework\App\Area;

class EmailSenderHandler
{
    /**
     * @var ScopeConfigInterface
     */
    private $globalConfig;

    /**
     * @var AreaList
     */
    private $areaList;

    /**
     * @var State
     */
    private $appState;

    /**
     * EmailSenderHandler constructor.
     * @param ScopeConfigInterface $globalConfig
     * @param AreaList $areaList
     * @param State $appState
     */
    public function __construct(
        ScopeConfigInterface $globalConfig,
        AreaList $areaList,
        State $appState
    ){
        $this->globalConfig = $globalConfig;
        $this->areaList = $areaList;
        $this->appState = $appState;
    }

    /**
     * Initializes the translation if emails get send async by cron
     * This is a core bug and can be removed when this is solved:
     * https://github.com/magento/magento2/issues/7426
     */
    public function beforeSendEmails()
    {
        if ($this->globalConfig->getValue('sales_email/general/async_sending')) {
            $area = $this->areaList->getArea($this->appState->getAreaCode());
            $area->load(Area::PART_TRANSLATE);
        }
    }
}

All 3 comments

Hi there,
I debugged this issue and found out that this occurs if you have set your sales email to send in async mode. The problem here is, that the translation is not initialized.

In synchronous mode the translation gets initialized like that:
Magento\Framework\App\Action\Plugin\Design::beforeDispatch() triggers Magento\Framework\View\DesignLoader::load() which therefore inits the translation.
This happens because in synchronous mode a controller action gets executed and therefore beforeDispatch is triggered.

The async mode gets triggered by Magento cron. There is no controller action and therefore the translation is completely missing. As long as Magento does not provide a fix for that, we have to do it on our own. It is indeed a bit tricky to initialize it anyway.

  • The cron sets the area part to crontab and as there is (of course) no design theme for that area part, we have to pay attention to not initialize the complete design
  • Therefore we create a plugin for Magento\Sales\Model\EmailSenderHandler::sendEmails() which initializes the translation if emails get send in async mode

di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Sales\Model\EmailSenderHandler">
        <plugin name="sendSalesEmails" type="Vendor\Module\Plugin\EmailSenderHandler"/>
    </type>
</config>

Vendor\Module\Plugin\EmailSenderHandler.php:

<?php

namespace Vendor\Module\Plugin;

use \Magento\Framework\App\Config\ScopeConfigInterface;
use \Magento\Framework\App\AreaList;
use \Magento\Framework\App\State;
use \Magento\Framework\App\Area;

class EmailSenderHandler
{
    /**
     * @var ScopeConfigInterface
     */
    private $globalConfig;

    /**
     * @var AreaList
     */
    private $areaList;

    /**
     * @var State
     */
    private $appState;

    /**
     * EmailSenderHandler constructor.
     * @param ScopeConfigInterface $globalConfig
     * @param AreaList $areaList
     * @param State $appState
     */
    public function __construct(
        ScopeConfigInterface $globalConfig,
        AreaList $areaList,
        State $appState
    ){
        $this->globalConfig = $globalConfig;
        $this->areaList = $areaList;
        $this->appState = $appState;
    }

    /**
     * Initializes the translation if emails get send async by cron
     * This is a core bug and can be removed when this is solved:
     * https://github.com/magento/magento2/issues/7426
     */
    public function beforeSendEmails()
    {
        if ($this->globalConfig->getValue('sales_email/general/async_sending')) {
            $area = $this->areaList->getArea($this->appState->getAreaCode());
            $area->load(Area::PART_TRANSLATE);
        }
    }
}

Hi @ostmond @sydekumf
This should be solved in #8413 (already merged to develop) which covers Cron

@ostmond, thank you for your report.
We were not able to reproduce this issue by following the steps you provided. If you'd like to update it, please reopen the issue.
We tested the issue on 2.3.0-dev, 2.2.0, 2.1.9

Was this page helpful?
0 / 5 - 0 ratings