diff --git a/.gitignore b/.gitignore index 633484b68..b1fe992b7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ # Customization Files /Web/custom-favicon.png /Web/img/custom-logo.png +lang/*/*-custom.tpl # Upload Directories /uploads/* diff --git a/Pages/Admin/ManageEmailTemplatesPage.php b/Pages/Admin/ManageEmailTemplatesPage.php index c9e07a47b..9605f08ac 100644 --- a/Pages/Admin/ManageEmailTemplatesPage.php +++ b/Pages/Admin/ManageEmailTemplatesPage.php @@ -44,6 +44,8 @@ public function SetSaveResult($saveResult); * @return string */ public function GetUpdatedTemplateName(); + + public function GetUpdatedLanguage(): string; } class ManageEmailTemplatesPage extends ActionPage implements IManageEmailTemplatesPage @@ -75,6 +77,11 @@ public function ProcessPageLoad() $this->Display('Admin/Configuration/manage_email_templates.tpl'); } + public function GetUpdatedLanguage(): string + { + return $this->GetForm(FormKeys::EMAIL_TEMPLATE_LANGUAGE); + } + public function GetLanguage() { return $this->GetQuerystring(QueryStringKeys::LANGUAGE); diff --git a/Pages/HelpPage.php b/Pages/HelpPage.php index 89d967579..d6783b4d4 100644 --- a/Pages/HelpPage.php +++ b/Pages/HelpPage.php @@ -18,20 +18,5 @@ public function PageLoad() $this->Set('ServerTimezone', date_default_timezone_get()); $this->DisplayLocalized('support-and-credits.tpl'); - - // $helpType = $this->GetQuerystring('ht'); -// -// if ($helpType == 'about') -// { -// -// } -// else if ($helpType == 'admin') -// { -// $this->DisplayLocalized('help-admin.tpl'); -// } -// else -// { -// $this->DisplayLocalized('help.tpl'); -// } } } diff --git a/Pages/Page.php b/Pages/Page.php index 1b975d9c5..11eb6b0e8 100644 --- a/Pages/Page.php +++ b/Pages/Page.php @@ -395,13 +395,10 @@ protected function DisplayCsv($templateName, $fileName) /** * @param string $templateName - * @param null $languageCode uses current language is nothing is passed in */ - protected function DisplayLocalized($templateName, $languageCode = null) + protected function DisplayLocalized($templateName) { - if (empty($languageCode)) { - $languageCode = $this->GetVar('CurrentLanguage'); - } + $languageCode = $this->GetVar('CurrentLanguage'); $localizedPath = ROOT_DIR . 'lang/' . $languageCode; $defaultPath = ROOT_DIR . 'lang/en_us/'; diff --git a/Presenters/Admin/ManageEmailTemplatesPresenter.php b/Presenters/Admin/ManageEmailTemplatesPresenter.php index 5a09b8e28..b5a44afbd 100644 --- a/Presenters/Admin/ManageEmailTemplatesPresenter.php +++ b/Presenters/Admin/ManageEmailTemplatesPresenter.php @@ -117,7 +117,7 @@ public function UpdateEmailTemplate() try { Log::Debug('Updating email template. Template=%s', $templateName); - $templatePath = Paths::EmailTemplates($this->GetSelectedLanguage()); + $templatePath = Paths::EmailTemplates($this->page->GetUpdatedLanguage()); $saveResult = $this->filesystem->Save($templatePath, str_replace('.tpl', '-custom.tpl', $templateName), $this->page->GetTemplateContents()); $this->filesystem->FlushSmartyCache(); diff --git a/config/config.dist.php b/config/config.dist.php index 08f2c2102..4b13f843a 100644 --- a/config/config.dist.php +++ b/config/config.dist.php @@ -18,6 +18,7 @@ $conf['settings']['default.page.size'] = '50'; // number of records per page $conf['settings']['enable.email'] = 'true'; // global configuration to enable if any emails will be sent $conf['settings']['default.language'] = 'en_us'; // find your language in the lang directory +$conf['settings']['enforce.custom.mail.template'] = 'false'; // Fallback to default.language for missing custom templates, bu only when custom template is available for default.language $conf['settings']['script.url'] = ''; // public URL to the Web directory of this instance. this is the URL that appears when you are logging in. leave http: or https: off to auto-detect $conf['settings']['image.upload.directory'] = 'Web/uploads/images'; // full or relative path to where images will be stored $conf['settings']['image.upload.url'] = 'uploads/images'; // full or relative path to show uploaded images from diff --git a/lang/du_nl/AccountCreation-custom.tpl b/lang/du_nl/AccountCreation-custom.tpl deleted file mode 100644 index 0e237d69c..000000000 --- a/lang/du_nl/AccountCreation-custom.tpl +++ /dev/null @@ -1,11 +0,0 @@ -

{$To},

- -

Een nieuwe gebruiker is geregistreerd met de volgende informatie:
-Email: {$EmailAddress}
-Naam: {$FullName}
-Telefoonnummer: {$Phone}
-Organisatie: {$Organization}
-Positie: {$Position}

-{if !empty($CreatedBy)} - Gemaakt door: {$CreatedBy} -{/if} diff --git a/lang/en_us/AccountCreation-custom.tpl b/lang/en_us/AccountCreation-custom.tpl deleted file mode 100644 index d814a8a22..000000000 --- a/lang/en_us/AccountCreation-custom.tpl +++ /dev/null @@ -1,11 +0,0 @@ -

{$To},

- -

A new user has registered with the following information:
-Email: {$EmailAddress}
-Name: {$FullName}
-Phone: {$Phone}
-Organization: {$Organization}
-Position: {$Position}

-{if !empty($CreatedBy)} - Created by: {$CreatedBy} -{/if} \ No newline at end of file diff --git a/lang/es/AccountCreation-custom.tpl b/lang/es/AccountCreation-custom.tpl deleted file mode 100644 index 19c5317f6..000000000 --- a/lang/es/AccountCreation-custom.tpl +++ /dev/null @@ -1,11 +0,0 @@ -

{$To},

- -

Se ha registrado un nuevo usuario con la siguiente información:
-Correo electrónico: {$EmailAddress}
-Nombre: {$FullName}
-Teléfono: {$Phone}
-Organización: {$Organization}
-Cargo: {$Position}

-{if !empty($CreatedBy)} - Creado por: {$CreatedBy} -{/if} \ No newline at end of file diff --git a/lang/fr_fr/AccountCreation-custom.tpl b/lang/fr_fr/AccountCreation-custom.tpl deleted file mode 100644 index 3920effd2..000000000 --- a/lang/fr_fr/AccountCreation-custom.tpl +++ /dev/null @@ -1,11 +0,0 @@ -

{$To},

- -

Un nouvel utilisateur s'est enregistré avec les informations suivantes:
-Email: {$EmailAddress}
-Nom: {$FullName}
-Téléphone: {$Phone}
-Organisation: {$Organization}
-Position: {$Position}

-{if !empty($CreatedBy)} - Créé par: {$CreatedBy} -{/if} \ No newline at end of file diff --git a/lang/pt_br/AccountCreation-custom.tpl b/lang/pt_br/AccountCreation-custom.tpl deleted file mode 100644 index 20fb80b9b..000000000 --- a/lang/pt_br/AccountCreation-custom.tpl +++ /dev/null @@ -1,18 +0,0 @@ -

- {$To}, -
-

- -

- Um novo usuário se registrou com as seguintes informações: -
- E-mail: {$EmailAddress} -
- Nome: {$FullName} -
- Organização: {$Organization} - {if !empty($CreatedBy)} -
- Criada por: {$CreatedBy} - {/if} -

diff --git a/lib/Common/SmartyPage.php b/lib/Common/SmartyPage.php index 54703ed69..b8244f77e 100644 --- a/lib/Common/SmartyPage.php +++ b/lib/Common/SmartyPage.php @@ -76,46 +76,41 @@ public function AddTemplateDirectory($templateDirectory) } /** + * Fetches template in a specific language. A custom template file might override the default template. + * In case the template is not available in the target language it will fall back to en_us. * @param string $templateName - * @param null $languageCode uses current language is nothing is passed in - */ - public function DisplayLocalized($templateName, $languageCode = null) - { - if (empty($languageCode)) { - $languageCode = $this->getTemplateVars('CurrentLanguage'); - } - $localizedPath = ROOT_DIR . 'lang/' . $languageCode; - $defaultPath = ROOT_DIR . 'lang/en_us/' . $templateName; - - if (file_exists($localizedPath . '/' . $templateName)) { - $this->AddTemplateDirectory($localizedPath); - } else { - $this->AddTemplateDirectory($defaultPath); - } - - $this->Display($templateName); - } - - /** - * @param string $templateName - * @param null $languageCode uses current language is nothing is passed in + * @param string $languageCode Will be set to template var CurrentLanguage if null + * @param bool $enforceCustomTemplate if true uses custom language from default language + * if custom template of the target language is not available. * @return string */ - public function FetchLocalized($templateName, $languageCode = null) + public function FetchLocalized($templateName, bool $enforceCustomTemplate, string $languageCode = null) { - if (empty($languageCode)) { + if ($languageCode == null) { $languageCode = $this->getTemplateVars('CurrentLanguage'); } - $localizedPath = ROOT_DIR . 'lang/' . $languageCode; - $defaultPath = ROOT_DIR . 'lang/en_us/'; + $langPath = ROOT_DIR . 'lang/'; + $localizedPath = $langPath . $languageCode; $customTemplateName = str_replace('.tpl', '-custom.tpl', $templateName); + $hasCustomTemplate = file_exists($localizedPath . '/' . $customTemplateName); + + if ($enforceCustomTemplate && !$hasCustomTemplate) { + $defaultLanguageCode = Configuration::Instance()->GetKey(ConfigKeys::LANGUAGE); + $defaultLocalizedPath = $langPath . $defaultLanguageCode; + $hasCustomDefaultTemplate = file_exists($defaultLocalizedPath . '/' . $customTemplateName); + if ($languageCode != $defaultLanguageCode && $hasCustomDefaultTemplate) { + $hasCustomTemplate = true; + $localizedPath = $defaultLocalizedPath; + } + } - if (file_exists($localizedPath . '/' . $templateName) || file_exists($localizedPath . '/' . $customTemplateName)) { + if (file_exists($localizedPath . '/' . $templateName) || $hasCustomTemplate) { $path = $localizedPath; $this->AddTemplateDirectory($localizedPath); } else { - $path = $defaultPath; - $this->AddTemplateDirectory($defaultPath); + // Fallback path + $path = ROOT_DIR . 'lang/en_us/'; + $this->AddTemplateDirectory($path); } if (file_exists($path . '/' . $customTemplateName)) { diff --git a/lib/Config/ConfigKeys.php b/lib/Config/ConfigKeys.php index 3d8e7902a..8f3c7800d 100644 --- a/lib/Config/ConfigKeys.php +++ b/lib/Config/ConfigKeys.php @@ -18,6 +18,7 @@ class ConfigKeys public const HOME_URL = 'home.url'; public const INACTIVITY_TIMEOUT = 'inactivity.timeout'; public const LANGUAGE = 'default.language'; + public const ENFORCE_CUSTOM_MAIL_TEMPLATE = 'enforce.custom.mail.template'; public const LOGOUT_URL = 'logout.url'; public const NAME_FORMAT = 'name.format'; public const SCRIPT_URL = 'script.url'; diff --git a/lib/Email/EmailMessage.php b/lib/Email/EmailMessage.php index f0eaa2de5..f74193433 100644 --- a/lib/Email/EmailMessage.php +++ b/lib/Email/EmailMessage.php @@ -5,7 +5,7 @@ abstract class EmailMessage implements IEmailMessage /** * @var SmartyPage */ - private $email; + protected $email; /** * @var string|null */ @@ -15,8 +15,11 @@ abstract class EmailMessage implements IEmailMessage */ private $attachmentFileName; + protected bool $enforceCustomTemplate; + protected function __construct($languageCode = null) { + $this->enforceCustomTemplate = Configuration::Instance()->GetKey(ConfigKeys::ENFORCE_CUSTOM_MAIL_TEMPLATE, new BooleanConverter()); $this->email = new SmartyPage($resources); $resources = Resources::GetInstance(); if (!empty($languageCode)) { @@ -37,7 +40,7 @@ protected function Set($var, $value) protected function FetchTemplate($templateName, $includeHeaders = true) { $header = $includeHeaders ? $this->email->fetch('Email/emailheader.tpl') : ''; - $body = $this->email->FetchLocalized($templateName); + $body = $this->email->FetchLocalized($templateName, $this->enforceCustomTemplate); $footer = $includeHeaders ? $this->email->fetch('Email/emailfooter.tpl') : ''; return $header . $body . $footer; diff --git a/lib/Email/Messages/ReportEmailMessage.php b/lib/Email/Messages/ReportEmailMessage.php index c0cd84ef3..5599848a1 100644 --- a/lib/Email/Messages/ReportEmailMessage.php +++ b/lib/Email/Messages/ReportEmailMessage.php @@ -32,7 +32,7 @@ public function __construct($report, $definition, $toAddress, $reportUser, $sele $this->Set('Definition', $definition); $this->Set('Report', $report); $this->Set('ReportCsvColumnView', new ReportCsvColumnView($selectedColumns)); - $contents = $this->FetchTemplate('Reports/custom-csv.tpl', false); + $contents = $this->email->FetchLocalized('Reports/custom-csv.tpl', false); $name = $report->ReportName(); if (!empty($name)) { diff --git a/lib/Email/Messages/ReservationShareEmail.php b/lib/Email/Messages/ReservationShareEmail.php index bba5460cd..5d6b0adb1 100644 --- a/lib/Email/Messages/ReservationShareEmail.php +++ b/lib/Email/Messages/ReservationShareEmail.php @@ -7,7 +7,7 @@ class ReservationShareEmail extends ReservationEmailMessage /** * @var string */ - private $email; + private $emailToShare; public function __construct(User $reservationOwner, $emailToShare, ReservationSeries $reservationSeries, IAttributeRepository $attributeRepository, IUserRepository $userRepository) { @@ -16,12 +16,12 @@ public function __construct(User $reservationOwner, $emailToShare, ReservationSe $this->reservationOwner = $reservationOwner; $this->reservationSeries = $reservationSeries; $this->timezone = $reservationOwner->Timezone(); - $this->email = $emailToShare; + $this->emailToShare = $emailToShare; } public function To() { - return [new EmailAddress($this->email)]; + return [new EmailAddress($this->emailToShare)]; } public function Subject() diff --git a/lib/Server/FormKeys.php b/lib/Server/FormKeys.php index 631a3d9fb..1dc168259 100644 --- a/lib/Server/FormKeys.php +++ b/lib/Server/FormKeys.php @@ -89,6 +89,7 @@ private function __construct() public const ENABLE_AUTO_RELEASE = 'ENABLE_AUTO_RELEASE'; public const EMAIL_CONTENTS = 'EMAIL_CONTENTS'; public const EMAIL_TEMPLATE_NAME = 'EMAIL_TEMPLATE_NAME'; + public const EMAIL_TEMPLATE_LANGUAGE = 'EMAIL_TEMPLATE_LANGUAGE'; public const FIRST_NAME = 'fname'; public const FAVICON_FILE = 'FAVICON_FILE'; diff --git a/tests/Presenters/Admin/ManageEmailTemplatesPresenterTest.php b/tests/Presenters/Admin/ManageEmailTemplatesPresenterTest.php index f90f5e306..ed428b983 100644 --- a/tests/Presenters/Admin/ManageEmailTemplatesPresenterTest.php +++ b/tests/Presenters/Admin/ManageEmailTemplatesPresenterTest.php @@ -74,11 +74,12 @@ public function testUpdatesEmailTemplate() $this->page->_UpdatedTemplateName = $templateName; $this->page->_TemplateContents = $contents; $this->page->_Language = 'en_us'; + $this->page->_UpdatedLanguage = 'cz'; $this->presenter->UpdateEmailTemplate(); $this->assertEquals($contents, $this->fileSystem->_AddedFileContents); - $this->assertEquals(Paths::EmailTemplates('en_us'), $this->fileSystem->_AddedFilePath); + $this->assertEquals(Paths::EmailTemplates('cz'), $this->fileSystem->_AddedFilePath); $this->assertEquals('template-custom.tpl', $this->fileSystem->_AddedFileName); } } @@ -91,6 +92,7 @@ class FakeManageEmailTemplatesPage extends ManageEmailTemplatesPage public $_BoundTemplateContents; public $_TemplateContents; public $_Language; + public $_UpdatedLanguage; public $_SaveResult = true; public function BindTemplateNames($templates) @@ -123,6 +125,11 @@ public function GetLanguage() return $this->_Language; } + public function GetUpdatedLanguage(): string + { + return $this->_UpdatedLanguage; + } + public function SetSaveResult($saveResult) { $this->_SaveResult = $saveResult; diff --git a/tpl/Admin/Configuration/manage_email_templates.tpl b/tpl/Admin/Configuration/manage_email_templates.tpl index c7db93147..8a888869b 100644 --- a/tpl/Admin/Configuration/manage_email_templates.tpl +++ b/tpl/Admin/Configuration/manage_email_templates.tpl @@ -16,19 +16,19 @@ -
- -
+
+
+ +
-
-
- -
+
+
+
@@ -41,10 +41,10 @@ value="{translate key=ReloadOriginalContents}" />
- - {csrf_token} - + + {csrf_token}
+