Jump to content

[SOLVED] Mail subject translation not showing in BO - found workaround


Kunsthelden

Recommended Posts

Dear community,

We detected an odd behavior on Prestashop 1.7.2.4 that maybe somebody knows already. Pls let us know.

 

Issues as following:

- We cannot see the subject translations, although we translated it. Fields remain empty (pls see illustration below) for 3rd party and Prestashop modules.

- We use a child_theme: Therefore some of the translations are stored by Prestashop to /themes/classic_childtheme/mails/de/lang.php (3rd party module reading form here), /mails/de/lang.php (Prestashop seems not to use this anymore for own and 3rd party mail translation) and /app/Resources/translations/de-DE/EmailsSubject.de-DE.xlf. 3rd party modules cannot saved to EmailsSubject.de-DE.xlf indeed. If we send the mail, the data is working but we cannot amend it via BO or if we do, we delete the current translations.

- Also Umlaute seem not to work properly if used in old translation way through .txt file. Email is not being sent in this case. Without Umlaute it works fine.

 

Solution:

We have found a workaround for us but we believe that it could be a Prestashop 1.7.2.4 issue. Our workaround includes a programming change (override) of AdminTranslationsController.php to actually use the lang.php file (seems missing). To us, new translation file EmailsSubject.de-DE.xlf seems not to work for Prestashop modules and 3rd party modules either. It's just not in the code. We now changed to use lang file from /mails/yourLang/lang.php only and this works as a workaround to change the subject in the mail translation as well as to send the mail subject title in correct language.

 

image.thumb.png.a4db530164cda906e8fd371c8f2226df.png

 

Edited by Kunsthelden (see edit history)
Link to comment
Share on other sites

  • 1 year later...
<?php
    /*
    * 
    * date: 2018-09-17 23:15:00
    * version: 1.0.1
    */  

//use PrestaShop\PrestaShop\Core\Cldr\Update;
//use PrestaShop\PrestaShop\Core\Addon\Theme\ThemeManagerBuilder;
//use PrestaShop\PrestaShop\Core\Addon\Theme\Theme;

class AdminTranslationsController extends AdminTranslationsControllerCore
{
    /**
     * Display mails in html format.
     * This was create for factorize the html displaying
     * @since 1.4.0.14
     *
     * @param array       $mails
     * @param array       $all_subject_mail
     * @param Language    $obj_lang
     * @param string      $id_html          Use for set html id attribute for the block
     * @param string      $title            Set the title for the block
     * @param string|bool $name_for_module  Is not false define add a name for distinguish mails module
     *
     * @return string
     */
    protected function displayMailContent($mails, $all_subject_mail, $obj_lang, $id_html, $title, $name_for_module = false)
    {
        $str_return = '';
        $group_name = 'mail';
        if (array_key_exists('group_name', $mails)) {
            $group_name = $mails['group_name'];
        }

        if ($mails['empty_values'] == 0) {
            $translation_missing_badge_type = 'badge-success';
        } else {
            $translation_missing_badge_type = 'badge-danger';
        }
        $str_return .= '<div class="mails_field">
            <h4>
            <span class="badge">'.((int)$mails['empty_values'] + (int)$mails['total_filled']).' <i class="icon-envelope-o"></i></span>
            <a href="javascript:void(0);" onclick="$(\'#'.$id_html.'\').slideToggle();">'.$title.'</a>
            <span class="pull-right badge '.$translation_missing_badge_type.'">'.$mails['empty_values'].' '.$this->trans('missing translation(s)', array(), 'Admin.International.Notification').'</span>
            </h4>
            <div name="mails_div" id="'.$id_html.'" class="panel-group">';

        if (!empty($mails['files'])) {
            $topic_already_displayed = array();
            foreach ($mails['files'] as $mail_name => $mail_files) {			
                $str_return .= '<div class="panel translations-email-panel">';
                $str_return .= '<a href="#'.$id_html.'-'.$mail_name.'" class="panel-title" data-toggle="collapse" data-parent="#'.$id_html.'" >'.$mail_name.' <i class="icon-caret-down"></i> </a>';
                $str_return .= '<div id="'.$id_html.'-'.$mail_name.'" class="email-collapse panel-collapse collapse">';
                if (array_key_exists('html', $mail_files) || array_key_exists('txt', $mail_files)) {		
                    if (array_key_exists($mail_name, $all_subject_mail)) {
                        foreach ($all_subject_mail[$mail_name] as $subject_mail) {
                            $subject_key = 'subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']';
							$mails['subject']['trad'] = $this->getSubjectMailTrans($subject_mail, $name_of_module); // Added  16.02.2018
                            if (in_array($subject_key, $topic_already_displayed)) {
                                continue;
                            }
                            $topic_already_displayed[] = $subject_key;
                            $value_subject_mail = isset($mails['subject']) ? $mails['subject'] : ''; // Added  16.02.2018
                            //$value_subject_mail = isset($mails['subject'][$subject_mail]) ? $mails['subject'][$subject_mail] : ''; // Deleted  16.02.2018
                            $str_return .= '
                            <div class="label-subject row">
                                <label class="control-label col-lg-3">'.$this->trans('Email subject', array(), 'Admin.International.Feature');
                            if (isset($value_subject_mail['use_sprintf']) && $value_subject_mail['use_sprintf']) {
                                $str_return .= '<span class="useSpecialSyntax" title="'.$this->trans('This expression uses a special syntax:', array(), 'Admin.International.Notification').' '.$value_subject_mail['use_sprintf'].'">
                                    <i class="icon-exclamation-triangle"></i>
                                </span>';
                            }
                            $str_return .= '</label><div class="col-lg-9">';
                            if (isset($value_subject_mail['trad']) && $value_subject_mail['trad']) {
                                $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="'.$value_subject_mail['trad'].'" />';
                            } else {
                                $str_return .= '<input class="form-control" type="text" name="subject['.Tools::htmlentitiesUTF8($group_name).']['.Tools::htmlentitiesUTF8($subject_mail).']" value="" />';
                            }
                            $str_return .= '<p class="help-block">'.stripcslashes($subject_mail).'</p>';
                            $str_return .= '</div></div>';
                        }
                    } else {
                        $str_return .= '
                            <hr><div class="alert alert-info">'
                            .$this->trans('No Subject was found for %mail_name% in the database.', array('%mail_name%' => $mail_name), 'Admin.International.Notification')
                            .'</div>';
                    }
                    // tab menu
                    $str_return .= '<hr><ul class="nav nav-pills">
                        <li class="active"><a href="#'.$mail_name.'-html" data-toggle="tab">'.$this->trans('View HTML version', array(), 'Admin.International.Feature').'</a></li>
                        <li><a href="#'.$mail_name.'-editor" data-toggle="tab">'.$this->trans('Edit HTML version', array(), 'Admin.International.Feature').'</a></li>
                        <li><a href="#'.$mail_name.'-text" data-toggle="tab">'.$this->trans('View/Edit TXT version', array(), 'Admin.International.Feature').'</a></li>
                        </ul>';
                    // tab-content
                    $str_return .= '<div class="tab-content">';

                    $base_uri = str_replace(_PS_ROOT_DIR_, __PS_BASE_URI__, $mails['directory']);
                    $base_uri = str_replace('//', '/', $base_uri);
                    $url_mail = $base_uri.$mail_name.'.html';

                    $mail_files_html = empty($mail_files['html']) ? false : $mail_files['html'];
                    $str_return .= '<div class="tab-pane active" id="'.$mail_name.'-html">';
                    $str_return .= $this->displayMailBlockHtml($mail_files_html, $obj_lang->iso_code, $url_mail, $mail_name, $group_name, $name_for_module);
                    $str_return .= '</div>';

                    $mail_files_txt = empty($mail_files['txt']) ? false : $mail_files['txt'];
                    $str_return .= '<div class="tab-pane" id="'.$mail_name.'-text">';
                    $str_return .= $this->displayMailBlockTxt($mail_files_txt, $obj_lang->iso_code, $mail_name, $group_name, $name_for_module);
                    $str_return .= '</div>';

                    $str_return .= '<div class="tab-pane" id="'.$mail_name.'-editor">';
                    $str_return .= $this->displayMailEditor($mail_files_html, $obj_lang->iso_code, $mail_name, $group_name, $name_for_module);
                    $str_return .= '</div>';

                    $str_return .= '</div>';
                    $str_return .= '</div><!--end .panel-collapse -->';
                    $str_return .= '</div><!--end .panel -->';
                }
            }
        } else {
            $str_return .= '<p class="error">
                '.$this->trans('There was a problem getting the mail files.', array(), 'Admin.International.Notification').'<br>
                '.$this->trans('English language files must exist in %folder% folder', array(
                    '%folder%' => '<em>'.preg_replace('@/[a-z]{2}(/?)$@', '/en$1', $mails['directory']).'</em>'
                ), 'Admin.International.Notification').'
            </p>';
        }

        $str_return .= '</div><!-- #'.$id_html.' --></div><!-- end .mails_field -->';
        return $str_return;
    }

    /**
     * This method generate the form for mails translations
     *
     * @param bool $no_display
     *
     * @return array|string
     */
    public function initFormMails($no_display = false)
    {
        $module_mails = array();

        // get all mail subjects, this method parse each files in Prestashop !!
        $subject_mail = array();

        $modules_has_mails = $this->getModulesHasMails(true);

        $files_by_directiories = $this->getFileToParseByTypeTranslation();

        if (!$this->theme_selected || !@filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) {
            $this->copyMailFilesForAllLanguages();
        }

        foreach ($files_by_directiories['php'] as $dir => $files) {
            if (!empty($files)) {
                foreach ($files as $file) {
                    // If file exist and is not in ignore_folder, in the next step we check if a folder or mail
                    if (Tools::file_exists_cache($dir . $file) && !in_array($file, self::$ignore_folder)) {
                        $subject_mail = $this->getSubjectMail($dir, $file, $subject_mail);			
                    }
                }
            }
        }

        // Get path of directory for find a good path of translation file
        if ($this->theme_selected && @filemtime($this->translations_informations[$this->type_selected]['override']['dir'])) {
            $i18n_dir = $this->translations_informations[$this->type_selected]['override']['dir'];
        } else {
            $i18n_dir = $this->translations_informations[$this->type_selected]['dir'];
        }

        $core_mails = $this->getMailFiles($i18n_dir, 'core_mail');

        foreach ($modules_has_mails as $module_name => $module_path) {
			$module_path = rtrim($module_path, '/');
            $module_mails[$module_name] = $this->getMailFiles($module_path.'/mails/'.$this->lang_selected->iso_code.'/', 'module_mail');
            $module_mails[$module_name]['subject']['trad'] = $this->getSubjectMailTrans($module_path.'/mails/'.$this->lang_selected->iso_code.'/', 'lang.php', $subject_mail, $module_name); // Added 			
            $module_mails[$module_name]['display'] = $this->displayMailContent($module_mails[$module_name], $subject_mail, $this->lang_selected, Tools::strtolower($module_name), $module_name, $module_name);
            $module_mails[$module_name]['subject'] = $subject_mail; // Added 
        }

        if ($no_display) {
            $empty = 0;
            $total = 0;
            $total += (int)$core_mails['total_filled'];
            $empty += (int)$core_mails['empty_values'];
            foreach ($module_mails as $mod_infos) {
                $total += (int)$mod_infos['total_filled'];
                $empty += (int)$mod_infos['empty_values'];
            }
            return array('total' => $total, 'empty' => $empty);
        }

        $this->tpl_view_vars = array_merge($this->tpl_view_vars, array(
            'limit_warning' => $this->displayLimitPostWarning($this->total_expression),
            'mod_security_warning' => Tools::apacheModExists('mod_security'),
            'tinyMCE' => $this->getTinyMCEForMails($this->lang_selected->iso_code),
            'mail_content' => $this->displayMailContent($core_mails, $subject_mail, $this->lang_selected, 'core', $this->trans('Core emails', array(), 'Admin.International.Feature')),
            'cancel_url' => $this->context->link->getAdminLink('AdminTranslations'),
            'module_mails' => $module_mails,
            'theme_name' => $this->theme_selected
        ));

        $this->initToolbar();
        $this->base_tpl_view = 'translation_mails.tpl';
        return parent::renderView();
    }

    // Added 
    /**
     * This method is used to write translation for mails.
     * This writes subject translation files
     * (in root/mails/lang_choosen/lang.php or root/_PS_THEMES_DIR_/mails/lang_choosen/lang.php)
     * and mails files.
     */
    protected function submitTranslationsMails()
    {
        $arr_mail_content = array();
        $arr_mail_path = array();

        if (Tools::getValue('core_mail')) {
            $arr_mail_content['core_mail'] = Tools::getValue('core_mail');

            // Get path of directory for find a good path of translation file
            if (!$this->theme_selected) {
                $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['dir'];
            } else {
                $arr_mail_path['core_mail'] = $this->translations_informations[$this->type_selected]['override']['dir'];
            }
        }
        if (Tools::getValue('module_mail')) {
            $arr_mail_content['module_mail'] = Tools::getValue('module_mail');
            // Get path of directory for find a good path of translation file
            if (!$this->theme_selected) {
                $arr_mail_path['module_mail'] = $this->translations_informations['modules']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/';
            } else {
                $arr_mail_path['module_mail'] = $this->translations_informations['modules']['override']['dir'].'{module}/mails/'.$this->lang_selected->iso_code.'/';
            }
        }

        // Save each mail content
        foreach ($arr_mail_content as $group_name => $all_content) {
            foreach ($all_content as $type_content => $mails) {
                if (!in_array($type_content, self::$content_type_accepted)) {
                    throw new PrestaShopException($this->trans('This %type_content% file extension is not accepted.', array('%type_content%' => $type_content), 'Admin.International.Notification'));
                }

                foreach ($mails as $mail_name => $content) {
                    $module_name = false;
                    $module_name_pipe_pos = stripos($mail_name, '|');
                    if ($module_name_pipe_pos) {
                        $module_name = substr($mail_name, 0, $module_name_pipe_pos);
                        if (!Validate::isModuleName($module_name)) {
                            throw new PrestaShopException($this->trans('Invalid module name "%module%"', array('%module%' => Tools::safeOutput($module_name)), 'Admin.International.Notification'));
                        }
                        $mail_name = substr($mail_name, $module_name_pipe_pos + 1);
                        if (!Validate::isTplName($mail_name)) {
                            throw new PrestaShopException($this->trans('Invalid mail name "%mail%"', array('%mail%' => Tools::safeOutput($mail_name)), 'Admin.International.Notification'));
                        }
                    }

                    if ($type_content == 'html') {
                        $content = Tools::htmlentitiesUTF8($content);
                        $content = htmlspecialchars_decode($content);
                        // replace correct end of line
                        $content = str_replace("\r\n", PHP_EOL, $content);

                        // Magic Quotes shall... not.. PASS!
                        if (_PS_MAGIC_QUOTES_GPC_) {
                            $content = stripslashes($content);
                        }
                    }

                    if (Validate::isCleanHTML($content)) {
                        $path = $arr_mail_path[$group_name];
                        if ($module_name) {
                            $path = str_replace('{module}', $module_name, $path);
                        }
                        if (!file_exists($path) && !mkdir($path, 0777, true)) {
                            throw new PrestaShopException($this->trans('Directory "%folder%" cannot be created', array('%folder%' => dirname($path)), 'Admin.International.Notification'));
                        }

                        if ($type_content == 'tpl') {
                            preg_match('/{\s*[^$]+/s', $content, $matches);
                            if (!empty($matches)) {
                                throw new PrestaShopException($this->trans('Your email translations contain some invalid HTML and cannot be saved. Please check your content.', array(), 'Admin.International.Notification'));
                            }
                        }

                        file_put_contents($path.$mail_name.'.'.$type_content, $content);
                    } else {
                        throw new PrestaShopException($this->trans('Your HTML email templates cannot contain JavaScript code.', array(), 'Admin.International.Notification'));
                    }
                }
            }
        }

        // Update subjects
        $array_subjects = array();
        if (($subjects = Tools::getValue('subject')) && is_array($subjects)) {
            $array_subjects['core_and_modules'] = array('translations' => array(), 'path' => $arr_mail_path['core_mail'].'lang.php');
            foreach ($subjects as $subject_translation) {
                $array_subjects['core_and_modules']['translations'] = array_merge($array_subjects['core_and_modules']['translations'], $subject_translation);
            }
        }
        if (!empty($array_subjects)) {
            foreach ($array_subjects as $infos) {
                $this->writeSubjectTranslationFile($infos['translations'], $infos['path']);
                $this->writeSubjectTranslationFile($infos['translations'], _PS_THEME_DIR_.'mails/'.$this->lang_selected->iso_code.'/lang.php'); // Added  17.09.2018
            }
        }

        if (Tools::isSubmit('submitTranslationsMailsAndStay')) {
            $this->redirect(true);
        } else {
            $this->redirect();
        }
    }

    /**
     * Get list of subjects of mails
     *
     * Added 
     * @param Language    $subject_mail
     * @param string      $moduel_name
     *
     * @return array with translations
     */

    protected function getSubjectMailTrans($subject_mail, $module_name)
    {
            $dirMail = 'mails/'.$this->lang_selected->iso_code.'/';
            $file = 'lang.php'; 
            // If is file
            if (is_file(_PS_THEME_DIR_.$dirMail.$file) && preg_match('/lang.php/', $file)) {
                $lines = file(_PS_THEME_DIR_.$dirMail.$file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
                foreach ($lines as $line_num => $line) {
                $line_array = explode("'", $line);
                      if ($subject_mail == $line_array[1]) {
                   	        $subject_mail_trans = $line_array[3];
                     }
                }
            }
            else {
                if (is_file(_PS_ROOT_DIR_.'/'.$dirMail.$file) && preg_match('/lang.php/', $file)) {
                     $lines = file(_PS_ROOT_DIR_.'/'.$dirMail.$file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
                     foreach ($lines as $line_num => $line) {
                        $line_array = explode("'", $line);
                        if ($subject_mail == $line_array[1]) {
                   	     $subject_mail_trans = $line_array[3];
                       }
                   }   
                }	
            }
            return $subject_mail_trans;
    }
}

This is a work-around only. We just copy the data to further areas in Prestashop (default, classic, child_themes). So we have the translation variable anywhere. As you can see this is an override.

Kind regards

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...