invoices: unified money, number and date formats and fully respect configured language (#1814)
This commit is contained in:
144
src/Utils/LocaleFormats.php
Normal file
144
src/Utils/LocaleFormats.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Utils;
|
||||
|
||||
use App\Configuration\LanguageFormattings;
|
||||
use App\Constants;
|
||||
|
||||
/**
|
||||
* Use this class, when you want information about formats for a locale.
|
||||
*/
|
||||
class LocaleFormats
|
||||
{
|
||||
/**
|
||||
* @var LanguageFormattings
|
||||
*/
|
||||
private $formats;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $locale = Constants::DEFAULT_LOCALE;
|
||||
|
||||
public function __construct(LanguageFormattings $formats, string $locale)
|
||||
{
|
||||
$this->formats = $formats;
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all available locale/language codes.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAvailableLanguages(): array
|
||||
{
|
||||
return $this->formats->getAvailableLanguages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current locale used by the user in this request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale(): string
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the form component to handle date values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTypeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTypeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the Javascript component to handle date values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDatePickerFormat(): string
|
||||
{
|
||||
return $this->formats->getDatePickerFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the form component to handle datetime values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimeTypeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimeTypeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the Javascript component to handle datetime values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimePickerFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimePickerFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific date format, which should be used in combination with the twig filter "|date".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat(): string
|
||||
{
|
||||
return $this->formats->getDateFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific time format, which should be used in combination with the twig filter "|time".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeFormat(): string
|
||||
{
|
||||
return $this->formats->getTimeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific datetime format, which should be used in combination with the twig filter "|date".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format used in the "|duration" twig filter to display a Timesheet duration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDurationFormat(): string
|
||||
{
|
||||
return $this->formats->getDurationFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this locale uses the 24 hour format.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTwentyFourHours(): bool
|
||||
{
|
||||
return $this->formats->isTwentyFourHours($this->getLocale());
|
||||
}
|
||||
}
|
||||
151
src/Utils/LocaleHelper.php
Normal file
151
src/Utils/LocaleHelper.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Utils;
|
||||
|
||||
use NumberFormatter;
|
||||
use Symfony\Component\Intl\Countries;
|
||||
use Symfony\Component\Intl\Currencies;
|
||||
use Symfony\Component\Intl\Languages;
|
||||
|
||||
final class LocaleHelper
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $locale;
|
||||
/**
|
||||
* @var NumberFormatter
|
||||
*/
|
||||
private $numberFormatter;
|
||||
/**
|
||||
* @var NumberFormatter
|
||||
*/
|
||||
private $moneyFormatter;
|
||||
/**
|
||||
* @var NumberFormatter
|
||||
*/
|
||||
private $moneyFormatterNoCurrency;
|
||||
|
||||
public function __construct(string $locale)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms seconds into a decimal formatted duration string.
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return string
|
||||
*/
|
||||
public function durationDecimal(int $seconds)
|
||||
{
|
||||
return $this->getNumberFormatter()->format(number_format($seconds / 3600, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|float $amount
|
||||
* @return bool|false|string
|
||||
*/
|
||||
public function amount($amount)
|
||||
{
|
||||
return $this->getNumberFormatter()->format($amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $currency
|
||||
* @return string
|
||||
*/
|
||||
public function currency($currency)
|
||||
{
|
||||
try {
|
||||
return Currencies::getSymbol(strtoupper($currency), $this->locale);
|
||||
} catch (\Exception $ex) {
|
||||
}
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $language
|
||||
* @return string
|
||||
*/
|
||||
public function language(string $language)
|
||||
{
|
||||
try {
|
||||
return Languages::getName(strtolower($language), $this->locale);
|
||||
} catch (\Exception $ex) {
|
||||
}
|
||||
|
||||
return $language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $country
|
||||
* @return string
|
||||
*/
|
||||
public function country(string $country)
|
||||
{
|
||||
try {
|
||||
return Countries::getName(strtoupper($country), $this->locale);
|
||||
} catch (\Exception $ex) {
|
||||
}
|
||||
|
||||
return $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|float $amount
|
||||
* @param string|null $currency
|
||||
* @param bool $withCurrency
|
||||
* @return string
|
||||
*/
|
||||
public function money($amount, ?string $currency = null, bool $withCurrency = true)
|
||||
{
|
||||
if (null === $currency) {
|
||||
$withCurrency = false;
|
||||
}
|
||||
|
||||
return $this->getMoneyFormatter($withCurrency)->formatCurrency($amount, $currency);
|
||||
}
|
||||
|
||||
private function getNumberFormatter(): NumberFormatter
|
||||
{
|
||||
if (null === $this->numberFormatter) {
|
||||
$this->numberFormatter = new NumberFormatter($this->locale, NumberFormatter::DECIMAL);
|
||||
}
|
||||
|
||||
return $this->numberFormatter;
|
||||
}
|
||||
|
||||
private function getMoneyFormatter(bool $withCurrency = true): NumberFormatter
|
||||
{
|
||||
if (null === $this->moneyFormatter) {
|
||||
$this->moneyFormatter = new NumberFormatter($this->locale, NumberFormatter::CURRENCY);
|
||||
}
|
||||
|
||||
if ($withCurrency) {
|
||||
return $this->moneyFormatter;
|
||||
}
|
||||
|
||||
if (null === $this->moneyFormatterNoCurrency) {
|
||||
// if anyone knows a better way of achieving this, please let me know!
|
||||
$this->moneyFormatterNoCurrency = new NumberFormatter($this->locale, NumberFormatter::CURRENCY);
|
||||
$pattern = $this->moneyFormatterNoCurrency->getPattern();
|
||||
$pattern = str_replace('¤ ', '¤', $pattern);
|
||||
$pattern = str_replace(' ¤', '¤', $pattern);
|
||||
$this->moneyFormatterNoCurrency->setPattern($pattern);
|
||||
$this->moneyFormatterNoCurrency->setSymbol(NumberFormatter::CURRENCY_SYMBOL, '');
|
||||
$this->moneyFormatterNoCurrency->setSymbol(NumberFormatter::CURRENCY_CODE, '');
|
||||
$this->moneyFormatterNoCurrency->setSymbol(NumberFormatter::INTL_CURRENCY_SYMBOL, '');
|
||||
}
|
||||
|
||||
return $this->moneyFormatterNoCurrency;
|
||||
}
|
||||
}
|
||||
@@ -16,133 +16,15 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
||||
/**
|
||||
* Use this class, when you want information about formats for the "current request locale".
|
||||
*/
|
||||
final class LocaleSettings
|
||||
final class LocaleSettings extends LocaleFormats
|
||||
{
|
||||
/**
|
||||
* @var LanguageFormattings
|
||||
*/
|
||||
private $formats;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $locale = Constants::DEFAULT_LOCALE;
|
||||
|
||||
public function __construct(RequestStack $requestStack, LanguageFormattings $formats)
|
||||
{
|
||||
$locale = Constants::DEFAULT_LOCALE;
|
||||
// request is null in a console command
|
||||
if (null !== $requestStack->getMasterRequest()) {
|
||||
$this->locale = $requestStack->getMasterRequest()->getLocale();
|
||||
$locale = $requestStack->getMasterRequest()->getLocale();
|
||||
}
|
||||
$this->formats = $formats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all available locale/language codes.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getAvailableLanguages(): array
|
||||
{
|
||||
return $this->formats->getAvailableLanguages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current locale used by the user in this request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocale(): string
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the form component to handle date values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTypeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTypeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the Javascript component to handle date values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDatePickerFormat(): string
|
||||
{
|
||||
return $this->formats->getDatePickerFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the form component to handle datetime values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimeTypeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimeTypeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format which is used by the Javascript component to handle datetime values.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimePickerFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimePickerFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific date format, which should be used in combination with the twig filter "|date".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateFormat(): string
|
||||
{
|
||||
return $this->formats->getDateFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific time format, which should be used in combination with the twig filter "|time".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTimeFormat(): string
|
||||
{
|
||||
return $this->formats->getTimeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the locale specific datetime format, which should be used in combination with the twig filter "|date".
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDateTimeFormat(): string
|
||||
{
|
||||
return $this->formats->getDateTimeFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the format used in the "|duration" twig filter to display a Timesheet duration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDurationFormat(): string
|
||||
{
|
||||
return $this->formats->getDurationFormat($this->getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this locale uses the 24 hour format.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTwentyFourHours(): bool
|
||||
{
|
||||
return $this->formats->isTwentyFourHours($this->getLocale());
|
||||
parent::__construct($formats, $locale);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user