Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mail translations #423

Merged
merged 12 commits into from
Oct 10, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# Customization Files
/Web/custom-favicon.png
/Web/img/custom-logo.png
lang/*/*-custom.tpl

# Upload Directories
/uploads/*
Expand Down
7 changes: 7 additions & 0 deletions Pages/Admin/ManageEmailTemplatesPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public function SetSaveResult($saveResult);
* @return string
*/
public function GetUpdatedTemplateName();

public function GetUpdatedLanguage(): string;
}

class ManageEmailTemplatesPage extends ActionPage implements IManageEmailTemplatesPage
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 0 additions & 15 deletions Pages/HelpPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
// }
}
}
7 changes: 2 additions & 5 deletions Pages/Page.php
Original file line number Diff line number Diff line change
Expand Up @@ -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/';

Expand Down
2 changes: 1 addition & 1 deletion Presenters/Admin/ManageEmailTemplatesPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions config/config.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 0 additions & 11 deletions lang/du_nl/AccountCreation-custom.tpl

This file was deleted.

11 changes: 0 additions & 11 deletions lang/en_us/AccountCreation-custom.tpl

This file was deleted.

11 changes: 0 additions & 11 deletions lang/es/AccountCreation-custom.tpl

This file was deleted.

11 changes: 0 additions & 11 deletions lang/fr_fr/AccountCreation-custom.tpl

This file was deleted.

18 changes: 0 additions & 18 deletions lang/pt_br/AccountCreation-custom.tpl

This file was deleted.

53 changes: 24 additions & 29 deletions lib/Common/SmartyPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
1 change: 1 addition & 0 deletions lib/Config/ConfigKeys.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
7 changes: 5 additions & 2 deletions lib/Email/EmailMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ abstract class EmailMessage implements IEmailMessage
/**
* @var SmartyPage
*/
private $email;
protected $email;
/**
* @var string|null
*/
Expand All @@ -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)) {
Expand All @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/Email/Messages/ReportEmailMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
6 changes: 3 additions & 3 deletions lib/Email/Messages/ReservationShareEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions lib/Server/FormKeys.php
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
9 changes: 8 additions & 1 deletion tests/Presenters/Admin/ManageEmailTemplatesPresenterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand All @@ -91,6 +92,7 @@ class FakeManageEmailTemplatesPage extends ManageEmailTemplatesPage
public $_BoundTemplateContents;
public $_TemplateContents;
public $_Language;
public $_UpdatedLanguage;
public $_SaveResult = true;

public function BindTemplateNames($templates)
Expand Down Expand Up @@ -123,6 +125,11 @@ public function GetLanguage()
return $this->_Language;
}

public function GetUpdatedLanguage(): string
{
return $this->_UpdatedLanguage;
}

public function SetSaveResult($saveResult)
{
$this->_SaveResult = $saveResult;
Expand Down
30 changes: 15 additions & 15 deletions tpl/Admin/Configuration/manage_email_templates.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@

</div>

<div class="form-group col-sm-4 col-6">
<select id="languageOpts" title="{translate key=Language}" class="form-select">
{foreach from=$Languages item=language}
<option value="{$language->LanguageCode}" {if $Language==$language->LanguageCode}selected="selected"
{/if}>{$language->DisplayName}</option>
{/foreach}
</select>
</div>
<form role="form" id="updateEmailForm" ajaxAction="{EmailTemplatesActions::Update}" method="post">
<div class="form-group col-sm-4 col-xs-6">
<select id="languageOpts" {formname key=EMAIL_TEMPLATE_LANGUAGE} title="{translate key=Language}" class="form-select">
{foreach from=$Languages item=language}
<option value="{$language->LanguageCode}" {if $Language==$language->LanguageCode} selected="selected"
{/if}>{$language->DisplayName}</option>
{/foreach}
</select>
</div>

<div id="editEmailSection" class="d-none">
<div class="mb-2">
<form role="form" id="updateEmailForm" ajaxAction="{EmailTemplatesActions::Update}" method="post">
<div class="form-group">
<div id="editEmailSection" class="d-none">
<div class="mb-2">
<div class="form-group">
<textarea id="templateContents" {formname key=EMAIL_CONTENTS}
title="{translate key=EmailTemplate}" class="form-control mb-2" rows="20"
style="width:100%"></textarea>
Expand All @@ -41,10 +41,10 @@
value="{translate key=ReloadOriginalContents}" />
</div>

<input type="hidden" id="templatePath" {formname key=EMAIL_TEMPLATE_NAME} />
{csrf_token}
</form>
<input type="hidden" id="templatePath" {formname key=EMAIL_TEMPLATE_NAME} />
{csrf_token}
</div>
</form>

<div id="updateSuccess" class="alert alert-success" style="display:none;">
<i class="bi bi-check-circle me-1"></i> {translate key=UpdateEmailTemplateSuccess}
Expand Down
Loading