Use PHP-intl instead of strftime.

This removes the requirement of having locales installed on the server
for all languages.
Also strftime is depreciated in PHP 8.1.

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel 2022-03-22 14:48:02 +01:00
parent 83201ece9c
commit 70830c514d
No known key found for this signature in database
GPG key ID: A061B9DDE0CA0773
13 changed files with 67 additions and 27 deletions

View file

@ -43,6 +43,12 @@ $poll = null;
$message = null;
$editingVoteId = 0;
/* Globals */
/* ------- */
global $smarty;
global $connect;
global $config;
/* Services */
/*----------*/
@ -468,6 +474,5 @@ $smarty->assign('resultPubliclyVisible', true);
$smarty->assign('editedVoteUniqueId', '');
$smarty->assign('default_to_marldown_editor', $config['markdown_editor_by_default']);
$smarty->assign('selectedNewVotes', $selectedNewVotes);
header("X-Robots-Tag: noindex, nofollow, nosnippet, noarchive");
$smarty->display('studs.tpl');

View file

@ -34,12 +34,34 @@ $i18n->get('', 'Something, just to load the dictionary');
$locale = str_replace('_', '-', $i18n->getLoadedLang());
/* Date Format */
$date_format['txt_full'] = __('Date', 'FULL'); //summary in create_date_poll.php and removal date in choix_(date|autre).php
$date_format['txt_short'] = __('Date', 'SHORT'); // radio title
$date_format['txt_day'] = __('Date', 'DAY');
$date_format['txt_date'] = __('Date', 'DATE');
$date_format['txt_month_year'] = __('Date', 'MONTH_YEAR');
$date_format['txt_datetime_short'] = __('Date', 'DATETIME');
//$date_format['txt_full'] = __('Date', 'FULL'); //summary in create_date_poll.php and removal date in choix_(date|autre).php
//$date_format['txt_short'] = __('Date', 'SHORT'); // radio title
//$date_format['txt_day'] = __('Date', 'DAY');
//$date_format['txt_date'] = __('Date', 'DATE');
//$date_format['txt_month_year'] = __('Date', 'MONTH_YEAR');
//$date_format['txt_datetime_short'] = __('Date', 'DATETIME');
$date_format['txt_full'] = 'eeee d MMMM y'; //summary in create_date_poll.php and removal date in choix_(date|autre).php
$date_format['txt_short'] = 'E d MMMM y'; // radio title
$date_format['txt_day'] = 'E d';
$date_format['txt_date'] = ''; // Defaults to IntlDateFormatter::SHORT
$date_format['txt_month_year'] = 'MMMM y';
$date_format['txt_datetime_short'] = 'dd-MM-y HH:mm';
function formatDate(string $format, $date) {
global $locale;
$formatter = new IntlDateFormatter($locale, IntlDateFormatter::SHORT, IntlDateFormatter::NONE);
if ($format !== '') {
$formatter->setPattern($format);
}
if (is_numeric($date)) {
$date = (new DateTime())->setTimestamp($date);
} elseif (gettype($date) === 'string') {
$date = new DateTime($date);
}
return datefmt_format($formatter, $date);
}
if (PHP_OS_FAMILY === 'Windows') { //%e can't be used on Windows platform, use %#d instead
foreach ($date_format as $k => $v) {
$date_format[$k] = preg_replace('#(?<!%)((?:%%)*)%e#', '\1%#d', $v); //replace %e by %#d for windows

View file

@ -18,6 +18,10 @@
*/
use Framadate\Utils;
global $locale;
global $ALLOWED_LANGUAGES;
global $date_format;
require_once __DIR__ . '/../../vendor/smarty/smarty/libs/Smarty.class.php';
$smarty = new \Smarty();
$smarty->setTemplateDir(ROOT_DIR . '/tpl/');
@ -119,6 +123,10 @@ function smarty_modifier_locale_2_lang(string $locale): string
return $locale;
}
function smarty_modifier_intl_date_format($date, string $pattern): string {
return formatDate($pattern, $date);
}
function path_for_datepicker_locale(string $lang): string
{
return __DIR__ . '/../../js/locales/bootstrap-datepicker.' . $lang . '.js';

View file

@ -63,6 +63,7 @@
"php": ">=7.3.0",
"ext-pdo": "*",
"ext-json": "*",
"ext-intl": "*",
"smarty/smarty": "^4.0",
"o80/i18n": "dev-develop",
"phpmailer/phpmailer": "~6.2",

View file

@ -141,7 +141,7 @@ if (empty($form->title) || empty($form->admin_name) || ($config['use_smtp'] && e
}
$summary .= '</ol>';
$end_date_str = utf8_encode(strftime($date_format['txt_date'], $pollService->maxExpiryDate()->getTimestamp())); //textual date
$end_date_str = utf8_encode(formatDate($date_format['txt_date'], $pollService->maxExpiryDate()->getTimestamp())); //textual date
$_SESSION['form'] = serialize($form);

View file

@ -160,7 +160,7 @@ switch ($step) {
$summary = '<ul>';
$choices = $form->getChoices();
foreach ($choices as $choice) {
$summary .= '<li>' . strftime($date_format['txt_full'], $choice->getName());
$summary .= '<li>' . formatDate($date_format['txt_full'], $choice->getName());
$first = true;
foreach ($choice->getSlots() as $slots) {
$summary .= $first ? ': ' : ', ';
@ -171,7 +171,7 @@ switch ($step) {
}
$summary .= '</ul>';
$end_date_str = utf8_encode(strftime($date_format['txt_date'], $pollService->maxExpiryDate()->getTimestamp())); // textual date
$end_date_str = utf8_encode(formatDate($date_format['txt_date'], $pollService->maxExpiryDate()->getTimestamp())); // textual date
$_SESSION['form'] = serialize($form);

View file

@ -38,6 +38,10 @@ $logService = new LogService();
$pollService = new PollService($logService);
$securityService = new SecurityService();
/* Globals */
global $smarty;
global $date_format;
/* PAGE */
/* ---- */
@ -77,7 +81,7 @@ if ($poll->format === 'D') {
$titles_line = ',';
$moments_line = ',';
foreach ($slots as $slot) {
$title = Utils::csvEscape(strftime($date_format['txt_date'], $slot->title));
$title = Utils::csvEscape(formatDate($date_format['txt_date'], $slot->title));
$moments = explode(',', $slot->moments);
$titles_line .= str_repeat($title . ',', count($moments));

View file

@ -39,7 +39,7 @@
<div id="days_container">
{foreach $choices as $i=>$choice}
{if $choice->getName()}
{$day_value = $choice->getName()|date_format:$date_format['txt_date']}
{$day_value = $choice->getName()|intl_date_format:$date_format['txt_date']}
{else}
{$day_value = ''}
{/if}

View file

@ -3,7 +3,7 @@
{foreach $polls as $poll}
<li>
<a href="{poll_url id=$poll->admin_id admin=true}">{$poll->title|html}</a>
({__('Generic', 'Creation date:')} {$poll->creation_date|date_format:$date_format['txt_full']})
({__('Generic', 'Creation date:')} {$poll->creation_date|intl_date_format:$date_format['txt_full']})
</li>
{/foreach}
</ul>
@ -14,4 +14,4 @@
{capture name="email_url"}<a href="mailto:{$smarty.const.ADRESSEMAILADMIN}">{$smarty.const.ADRESSEMAILADMIN}</a>{/capture}
{__f('FindPolls',"If you weren't the source of this action and if you think this is an abuse of the service, please notify the administrator on %s.", $smarty.capture.email_url)}
</i>
</p>
</p>

View file

@ -7,7 +7,7 @@
{if isset($admin) && !$expired}
<button type="submit" name="delete_comment" value="{$comment->id|html}" class="btn btn-link" title="{__('Comments', 'Remove the comment')}"><span class="glyphicon glyphicon-remove text-danger"></span><span class="sr-only">{__('Generic', 'Remove')}</span></button>
{/if}
<span class="comment_date">{$comment->date|date_format:$date_format['txt_datetime_short']}</span>
<span class="comment_date">{$comment->date|intl_date_format:$date_format['txt_datetime_short']}</span>
<b>{$comment->name|html}</b>&nbsp;
<span>{$comment->comment|escape|nl2br}</span>
</div>

View file

@ -116,12 +116,12 @@
</div>
<div id="expiration-form" class="form-group col-md-4">
<label class="control-label">{__('PollInfo', 'Expiration date')}</label>
<p>{$poll->end_date|date_format:$date_format['txt_date']|html} <button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the expiration date')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p>
<p>{$poll->end_date|intl_date_format:$date_format['txt_date']|html} <button class="btn btn-link btn-sm btn-edit" title="{__('PollInfo', 'Edit the expiration date')}"><span class="glyphicon glyphicon-pencil"></span><span class="sr-only">{__('Generic', 'Edit')}</span></button></p>
<div class="hidden js-expiration">
<label class="sr-only" for="newexpirationdate">{__('PollInfo', 'Expiration date')}</label>
<div class="input-group">
<input type="text" class="form-control" id="newexpirationdate" name="expiration_date" size="40" value="{$poll->end_date|date_format:$date_format['txt_date']|html}" />
<input type="text" class="form-control" id="newexpirationdate" name="expiration_date" size="40" value="{$poll->end_date|intl_date_format:$date_format['txt_date']|html}" />
<span class="input-group-btn">
<button type="submit" class="btn btn-success" name="update_poll_info" value="expiration_date" title="{__('PollInfo', 'Save the new expiration date')}"><span class="glyphicon glyphicon-ok"></span><span class="sr-only">{__('Generic', 'Save')}</span></button>
<button class="btn btn-link btn-cancel" title="{__('PollInfo', 'Cancel the expiration date edit')}"><span class="glyphicon glyphicon-remove"></span><span class="sr-only">{__('Generic', 'Cancel')}</span></button>

View file

@ -29,7 +29,7 @@
<a href="{poll_url id=$admin_poll_id admin=true action='delete_column' action_value=$slot->day|cat:'@'|cat:$moment}"
data-remove-confirmation="{__('adminstuds', 'Confirm removal of the column.')}"
class="btn btn-link btn-sm remove-column"
title="{__('adminstuds', 'Remove the column')} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
title="{__('adminstuds', 'Remove the column')} {$slot->day|intl_date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-remove text-danger"></i><span class="sr-only">{__('Generic', 'Remove')}</span>
</a>
</td>
@ -49,7 +49,7 @@
{$count_same = 0}
{$previous = 0}
{foreach $slots as $id=>$slot}
{$display = $slot->day|date_format:$date_format.txt_month_year|html}
{$display = $slot->day|intl_date_format:$date_format.txt_month_year|html}
{if $previous !== 0 && $previous != $display}
<th colspan="{$count_same}" class="bg-primary month" id="M{$id}">{$previous}</th>
{$count_same = 0}
@ -72,7 +72,7 @@
<tr>
<th role="presentation"></th>
{foreach $slots as $id=>$slot}
<th colspan="{$slot->moments|count}" class="bg-primary day" id="D{$id}">{$slot->day|date_format:$date_format.txt_day|html}</th>
<th colspan="{$slot->moments|count}" class="bg-primary day" id="D{$id}">{$slot->day|intl_date_format:$date_format.txt_day|html}</th>
{for $foo=0 to ($slot->moments|count)-1}
{append var='headersD' value=$id}
{/for}
@ -88,7 +88,7 @@
<th colspan="1" class="bg-info" id="H{$headersDCount}">{$moment|html}</th>
{append var='headersH' value=$headersDCount}
{$headersDCount = $headersDCount+1}
{$slots_raw[] = $slot->day|date_format:$date_format.txt_full|cat:' - '|cat:$moment}
{$slots_raw[] = $slot->day|intl_date_format:$date_format.txt_full|cat:' - '|cat:$moment}
{/foreach}
{/foreach}
<th></th>
@ -245,7 +245,7 @@
<input type="radio" id="y-choice-{$i}" name="choices[{$i}]" value="2"
{(!isset($selectedNewVotes[$i]) || ("2" !== $selectedNewVotes[$i])) ? "" : " checked"}
/>
<label class="btn btn-default btn-xs" for="y-choice-{$i}" title="{__('Poll results', 'Vote yes for')|html} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<label class="btn btn-default btn-xs" for="y-choice-{$i}" title="{__('Poll results', 'Vote yes for')|html} {$slot->day|intl_date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-ok"></i><span class="sr-only">{__('Generic', 'Yes')}</span>
</label>
</li>
@ -253,7 +253,7 @@
<input type="radio" id="i-choice-{$i}" name="choices[{$i}]" value="1"
{(!isset($selectedNewVotes[$i]) || ("1" !== $selectedNewVotes[$i])) ? "" : " checked"}
/>
<label class="btn btn-default btn-xs" for="i-choice-{$i}" title="{__('Poll results', 'Vote ifneedbe for')|html} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<label class="btn btn-default btn-xs" for="i-choice-{$i}" title="{__('Poll results', 'Vote ifneedbe for')|html} {$slot->day|intl_date_format:$date_format.txt_short|html} - {$moment|html}">
(<i class="glyphicon glyphicon-ok"></i>)<span class="sr-only">{__('Generic', 'Ifneedbe')}</span>
</label>
</li>
@ -263,7 +263,7 @@
<input type="radio" id="n-choice-{$i}" name="choices[{$i}]" value="0"
{(!isset($selectedNewVotes[$i]) || ("0" !== $selectedNewVotes[$i])) ? "" : " checked"}
/>
<label class="btn btn-default btn-xs {(!isset($selectedNewVotes[$i]) || ("0" !== $selectedNewVotes[$i])) ? "startunchecked" : ""}" for="n-choice-{$i}" title="{__('Poll results', 'Vote no for')|html} {$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}">
<label class="btn btn-default btn-xs {(!isset($selectedNewVotes[$i]) || ("0" !== $selectedNewVotes[$i])) ? "startunchecked" : ""}" for="n-choice-{$i}" title="{__('Poll results', 'Vote no for')|html} {$slot->day|intl_date_format:$date_format.txt_short|html} - {$moment|html}">
<i class="glyphicon glyphicon-ban-circle"></i><span class="sr-only">{__('Generic', 'No')}</span>
</label>
</li>
@ -346,7 +346,7 @@
var cols = [
{foreach $slots as $slot}
{foreach $slot->moments as $moment}
$('<div/>').html('{$slot->day|date_format:$date_format.txt_short|html} - {$moment|html}').text(),
$('<div/>').html('{$slot->day|intl_date_format:$date_format.txt_short|html} - {$moment|html}').text(),
{/foreach}
{/foreach}
];
@ -407,7 +407,7 @@
{foreach $slot->moments as $moment}
{if $best_choices['y'][$i] == $max}
{assign var="space" value="`$slot->day|date_format:'d-m-Y'|html`|`$moment`"}
<li><strong>{$slot->day|date_format:$date_format.txt_full|html} - {$moment|html}</strong>
<li><strong>{$slot->day|intl_date_format:$date_format.txt_full|html} - {$moment|html}</strong>
<a href="{poll_url id=$poll_id action='get_ical_file' action_value=($space)}" class="btn btn-default btn-sm" title="{__('studs', 'Download as ical/ics file')}">
<span class="fa fa-calendar text-muted"></span>
<span class="sr-only">{__('studs', 'Download as ical/ics file')}</span>

View file

@ -41,7 +41,7 @@
{if $expired}
<div class="alert alert-danger">
<p>{__('studs', 'The poll is expired, it will be deleted soon.')}</p>
<p>{__('studs', 'Deletion date:')} {$deletion_date|date_format:$date_format['txt_short']|html}</p>
<p>{__('studs', 'Deletion date:')} {$deletion_date|intl_date_format:$date_format['txt_short']|html}</p>
</div>
{else}
{if $admin}