There is bug in PrestaShop invoice multilingual feature when the invoice sent after order status is changed from backoffice. Here is a short tutorial on how to fix the issue.

All modified lines are marked as bold

1) The first file we need to change is /classes/Context.php

Find the function getTranslator($isInstaller = falseand replace the else statement with the following:

    if (Tools::getValue('id_order') && (Tools::getValue('sendStateEmail')) || Tools::isSubmit('submitState')) {
        $order = new Order((int)Tools::getValue('id_order'));
        $language = new Language((int) $order->id_lang);
    } else {
        $language = $this->language;
    }

    $this->translator = $sfContainer->get('translator');
    // We need to set the locale here because in legacy BO pages, the translator is used
    // before the TranslatorListener does its job of setting the locale according to the Request object
    $this->translator->setLocale($language->locale);

Before:

public function getTranslator($isInstaller = false)
{
    if (null !== $this->translator) {
        return $this->translator;
    }

    $sfContainer = SymfonyContainer::getInstance();

    if ($isInstaller || null === $sfContainer) {
        // symfony's container isn't available in front office, so we load and configure the translator component
        $this->translator = $this->getTranslatorFromLocale($this->language->locale);
    } else {
        $this->translator = $sfContainer->get('translator');
        // We need to set the locale here because in legacy BO pages, the translator is used
        // before the TranslatorListener does its job of setting the locale according to the Request object
        $this->translator->setLocale($this->language->locale);
    }

    return $this->translator;
}

After:

public function getTranslator($isInstaller = false)
{
    if (null !== $this->translator) {
        return $this->translator;
    }

    $sfContainer = SymfonyContainer::getInstance();

    if ($isInstaller || null === $sfContainer) {
        // symfony's container isn't available in front office, so we load and configure the translator component
        $this->translator = $this->getTranslatorFromLocale($this->language->locale);
    } else {
        if (Tools::getValue('id_order') && (Tools::getValue('sendStateEmail')) || Tools::isSubmit('submitState')) {
            $order = new Order((int)Tools::getValue('id_order'));
            $language = new Language((int) $order->id_lang);
        } else {
            $language = $this->language;
        }

        $this->translator = $sfContainer->get('translator');
        // We need to set the locale here because in legacy BO pages, the translator is used
        // before the TranslatorListener does its job of setting the locale according to the Request object
        $this->translator->setLocale($language->locale);
    }

    return $this->translator;

}

2) The next file need to change is /classes/order/OrderHistory.php Lines ~ 517 - 537

Before:

if (($result['pdf_invoice'] || $result['pdf_delivery'])) {
    $context = Context::getContext();
    $invoice = $order->getInvoicesCollection();
    $file_attachement = array();

    if ($result['pdf_invoice'] && (int) Configuration::get('PS_INVOICE') && $order->invoice_number) {
        Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $invoice));
        $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty);
        $file_attachement['invoice']['content'] = $pdf->render(false);
        $file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
        $file_attachement['invoice']['mime'] = 'application/pdf';
    }
    if ($result['pdf_delivery'] && $order->delivery_number) {
        $pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty);
        $file_attachement['delivery']['content'] = $pdf->render(false);
        $file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $order->id_shop) . sprintf('%06d', $order->delivery_number) . '.pdf';
        $file_attachement['delivery']['mime'] = 'application/pdf';
    }
} else {
    $file_attachement = null;
}

After:

if (($result['pdf_invoice'] || $result['pdf_delivery'])) {
    $context = Context::getContext();
    $invoice = $order->getInvoicesCollection();
    $file_attachement = array();
    $order_lang = new Language((int) $order->id_lang);

    if ($result['pdf_invoice'] && (int) Configuration::get('PS_INVOICE') && $order->invoice_number) {
        Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $invoice));
        $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty);
        $file_attachement['invoice']['content'] = $pdf->render(false, $order_lang->iso_code);
        $file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order_lang->id, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
        $file_attachement['invoice']['mime'] = 'application/pdf';
    }
    if ($result['pdf_delivery'] && $order->delivery_number) {
        $pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty);
        $file_attachement['delivery']['content'] = $pdf->render(false, $order_lang->iso_code);
        $file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', $order_lang->id, null, $order->id_shop) . sprintf('%06d', $order->delivery_number) . '.pdf';
        $file_attachement['delivery']['mime'] = 'application/pdf';
    }
} else {
    $file_attachement = null;
}

3) And finally the last file need to modify is: /classes/pdf/PDF.php ( the function render)

Before:

public function render($display = true)
{
    $render = false;
    $this->pdf_renderer->setFontForLang(Context::getContext()->language->iso_code);
    foreach ($this->objects as $object) {
        $this->pdf_renderer->startPageGroup();
        $template = $this->getTemplateObject($object);
        if (!$template) {
            continue;
        }

        if (empty($this->filename)) {
            $this->filename = $template->getFilename();
            if (count($this->objects) > 1) {
                $this->filename = $template->getBulkFilename();
            }
        }

        $template->assignHookData($object);

        $this->pdf_renderer->createHeader($template->getHeader());
        $this->pdf_renderer->createFooter($template->getFooter());
        $this->pdf_renderer->createPagination($template->getPagination());
        $this->pdf_renderer->createContent($template->getContent());
        $this->pdf_renderer->writePage();
        $render = true;

        unset($template);
    }

    if ($render) {
        // clean the output buffer
        if (ob_get_level() && ob_get_length() > 0) {
            ob_clean();
        }

        return $this->pdf_renderer->render($this->filename, $display);
    }
}

After:

public function render($display = true, $lang_iso = null)
{
    if (!$lang_iso) {
        $lang_iso = Context::getContext()->language->iso_code;
    }
    $render = false;
    $this->pdf_renderer->setFontForLang($lang_iso);
    foreach ($this->objects as $object) {
        $this->pdf_renderer->startPageGroup();
        $template = $this->getTemplateObject($object);
        if (!$template) {
            continue;
        }

        if (empty($this->filename)) {
            $this->filename = $template->getFilename();
            if (count($this->objects) > 1) {
                $this->filename = $template->getBulkFilename();
            }
        }

        $template->assignHookData($object);

        $this->pdf_renderer->createHeader($template->getHeader());
        $this->pdf_renderer->createFooter($template->getFooter());
        $this->pdf_renderer->createPagination($template->getPagination());
        $this->pdf_renderer->createContent($template->getContent());
        $this->pdf_renderer->writePage();
        $render = true;

        unset($template);
    }

    if ($render) {
        // clean the output buffer
        if (ob_get_level() && ob_get_length() > 0) {
            ob_clean();
        }

        return $this->pdf_renderer->render($this->filename, $display);
    }
}

Comments ()