diff --git a/Localization/Defaults/Definitions/de_DE.json b/Localization/Defaults/Definitions/de_DE.json index 848814e66..7586d8ed1 100644 --- a/Localization/Defaults/Definitions/de_DE.json +++ b/Localization/Defaults/Definitions/de_DE.json @@ -4,7 +4,7 @@ "currency": { "code": "EUR", "position": 0, - "format": "%s1 %s2" + "format": "1" }, "thousand": ".", "decimal": ",", @@ -51,8 +51,6 @@ "glass": "Metric cup" }, "datetime": { - "delim_date": ".", - "delim_time": ":", "very_short": "d.m", "short": "m.y", "medium": "Y.m.d", diff --git a/Localization/Defaults/Definitions/en_US.json b/Localization/Defaults/Definitions/en_US.json index aa87072ea..9b00c924e 100644 --- a/Localization/Defaults/Definitions/en_US.json +++ b/Localization/Defaults/Definitions/en_US.json @@ -4,7 +4,7 @@ "currency": { "code": "USD", "position": 0, - "format": "%s1 %s2" + "format": "1" }, "thousand": ",", "decimal": ".", @@ -51,12 +51,17 @@ "glass": "Metric cup" }, "datetime": { - "delim_date": ".", - "delim_time": ":", "very_short": "d.m", "short": "m.y", "medium": "Y.m.d", "long": "Y.m.d h:i", "very_long": "Y.m.d h:i:s" + }, + "precision": { + "very_short": 0, + "short": 1, + "medium": 2, + "long": 3, + "very_long": 5 } } \ No newline at end of file diff --git a/Localization/Defaults/Definitions/it_IT.json b/Localization/Defaults/Definitions/it_IT.json index aa87072ea..683c35d2a 100644 --- a/Localization/Defaults/Definitions/it_IT.json +++ b/Localization/Defaults/Definitions/it_IT.json @@ -4,7 +4,7 @@ "currency": { "code": "USD", "position": 0, - "format": "%s1 %s2" + "format": "1" }, "thousand": ",", "decimal": ".", @@ -51,8 +51,6 @@ "glass": "Metric cup" }, "datetime": { - "delim_date": ".", - "delim_time": ":", "very_short": "d.m", "short": "m.y", "medium": "Y.m.d", diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index be284fc66..b1cfd8050 100644 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -146,7 +146,7 @@ final class L11nManager /** * Get translation. * - * @param string $code Country code + * @param string $code Language code * @param string $module Module name * @param string $theme Theme * @param mixed $translation Text @@ -183,7 +183,7 @@ final class L11nManager /** * Get translation html escaped. * - * @param string $code Country code + * @param string $code Language code * @param string $module Module name * @param string $theme Theme * @param mixed $translation Text @@ -196,4 +196,92 @@ final class L11nManager { return \htmlspecialchars($this->getText($code, $module, $theme, $translation)); } + + /** + * Print a numeric value + * + * @param Localization $l11n Localization + * @param int|float $numeric Numeric value to print + * @param null|string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getNumeric(Localization $l11n, $numeric, string $format = null) : string + { + return \number_format( + $numeric, + $l11n->getPrecision()[$format ?? 'medium'], + $l11n->getDecimal(), + $l11n->getThousands() + ); + } + + /** + * Print a percentage value + * + * @param Localization $l11n Localization + * @param float $percentage Percentage value to print + * @param null|string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getPercentage(Localization $l11n, float $percentage, string $format = null) : string + { + return \number_format( + $percentage, $l11n->getPrecision()[$format ?? 'medium'], + $l11n->getDecimal(), + $l11n->getThousands() + ) . '%'; + } + + /** + * Print a currency + * + * @param Localization $l11n Localization + * @param int|float $currency Currency value to print + * @param null|string $format Format type to use + * @param null|string $symbol Currency name/symbol + * @param int $divide Divide currency by divisor + * + * @return string + * + * @since 1.0.0 + */ + public function getCurrency(Localization $l11n, $currency, string $format = null, string $symbol = null, int $divide = 1) : string + { + $language = $l11n->getLanguage() ?? 'en'; + $symbol ??= $l11n->getCurrency(); + + if ($divide === 1000) { + $symbol = $this->getHtml($language, '0', '0', 'CurrencyK') . $symbol; + } elseif ($divide === 1000000) { + $symbol = $this->getHtml($language, '0', '0', 'CurrencyM') . $symbol; + } elseif ($divide === 1000000000) { + $symbol = $this->getHtml($language, '0', '0', 'CurrencyB') . $symbol; + } + + $money = new Money($currency / $divide, $l11n->getThousands(), $l11n->getDecimal(), $symbol ?? $l11n->getCurrency(), (int) $l11n->getCurrencyFormat()); + + return $money->getCurrency($l11n->getPrecision()[$format ?? 'medium']); + } + + /** + * Print a datetime + * + * @param Localization $l11n Localization + * @param null|\DateTime $datetime DateTime to print + * @param string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getDateTime(Localization $l11n, \DateTime $datetime = null, string $format = null) : string + { + return $datetime === null ? '' : $datetime->format($l11n->getDateTime()[$format ?? 'medium']); + } } diff --git a/Localization/Localization.php b/Localization/Localization.php index 1e8235011..634f1ca93 100644 --- a/Localization/Localization.php +++ b/Localization/Localization.php @@ -66,7 +66,7 @@ class Localization implements \JsonSerializable * @var string * @since 1.0.0 */ - protected string $currencyFormat = '%s1 %s2'; + protected string $currencyFormat = '0'; /** * Number format. @@ -100,6 +100,14 @@ class Localization implements \JsonSerializable */ protected string $temperature = TemperatureType::CELSIUS; + /** + * Precision. + * + * @var array + * @since 1.0.0 + */ + protected array $precision = []; + /** * Time format. * @@ -108,22 +116,6 @@ class Localization implements \JsonSerializable */ protected array $datetime = []; - /** - * Datetime delim. - * - * @var string - * @since 1.0.0 - */ - protected string $dateDelim = '.'; - - /** - * Datetime delim. - * - * @var string - * @since 1.0.0 - */ - protected string $timeDelim = ':'; - /** * Weight. * @@ -224,13 +216,12 @@ class Localization implements \JsonSerializable $l11n->setAngle($json['angle']); $l11n->setTemperature($json['temperature']); $l11n->setDatetime($json['datetime']); - $l11n->setDateDelim($json['datedelim']); - $l11n->setTimeDelim($json['timedelim']); $l11n->setWeight($json['weight']); $l11n->setSpeed($json['speed']); $l11n->setLength($json['length']); $l11n->setArea($json['area']); $l11n->setVolume($json['volume']); + $l11n->setPrecision($json['precision']); return $l11n; } @@ -312,6 +303,7 @@ class Localization implements \JsonSerializable $this->setLength($locale['length'] ?? []); $this->setArea($locale['area'] ?? []); $this->setVolume($locale['volume'] ?? []); + $this->setPrecision($locale['precision'] ?? []); $this->setDatetime($locale['datetime'] ?? []); } @@ -497,58 +489,6 @@ class Localization implements \JsonSerializable $this->datetime = $datetime; } - /** - * Set dateDelim char - * - * @return string - * - * @since 1.0.0 - */ - public function getDateDelim() : string - { - return $this->dateDelim; - } - - /** - * Get dateDelim char - * - * @param string $dateDelim Date delim char - * - * @return void - * - * @since 1.0.0 - */ - public function setDateDelim(string $dateDelim) : void - { - $this->dateDelim = $dateDelim; - } - - /** - * Get timeDelim char - * - * @return string - * - * @since 1.0.0 - */ - public function getTimeDelim() : string - { - return $this->timeDelim; - } - - /** - * Set timeDelim char - * - * @param string $timeDelim Time delim char - * - * @return void - * - * @since 1.0.0 - */ - public function setTimeDelim(string $timeDelim) : void - { - $this->timeDelim = $timeDelim; - } - /** * Set decimal char * @@ -779,6 +719,32 @@ class Localization implements \JsonSerializable return $this->volume; } + /** + * Get precision type + * + * @return array + * + * @since 1.0.0 + */ + public function getPrecision() : array + { + return $this->precision; + } + + /** + * Set precision type + * + * @param array $precision Precision type + * + * @return void + * + * @since 1.0.0 + */ + public function setPrecision(array $precision) : void + { + $this->precision = $precision; + } + /** * Set volume type * @@ -810,13 +776,12 @@ class Localization implements \JsonSerializable 'angle' => $this->angle, 'temperature' => $this->temperature, 'datetime' => $this->datetime, - 'datedelim' => $this->dateDelim, - 'timedelim' => $this->timeDelim, 'weight' => $this->weight, 'speed' => $this->speed, 'length' => $this->length, 'area' => $this->area, 'volume' => $this->volume, + 'precision' => $this->precision, ]; } diff --git a/Localization/Money.php b/Localization/Money.php index 4d6999285..3321d3750 100644 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -178,7 +178,7 @@ final class Money implements \Serializable */ public function getCurrency(int $decimals = 2) : string { - return ($this->position === 0 ? $this->symbol : '') . $this->getAmount($decimals) . ($this->position === 1 ? $this->symbol : ''); + return ($this->position === 0 ? $this->symbol . ' ' : '') . $this->getAmount($decimals) . ($this->position === 1 ? ' ' . $this->symbol : ''); } /** @@ -196,13 +196,17 @@ final class Money implements \Serializable { $value = (string) \round($this->value, -self::MAX_DECIMALS + $decimals); - $left = \substr($value, 0, -self::MAX_DECIMALS); + $left = \substr($value, 0, -self::MAX_DECIMALS); + + /** @var string $left */ + $left = $left === false ? '0' : $left; $right = \substr($value, -self::MAX_DECIMALS); - if ($left === false || $right === false) { + + if ($right === false) { throw new \Exception(); } - return ($decimals > 0) ? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : $left; + return ($decimals > 0) ? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : \str_pad($left, 1, '0'); } /** diff --git a/Views/View.php b/Views/View.php index 2aa70f5f8..09046eab4 100644 --- a/Views/View.php +++ b/Views/View.php @@ -50,10 +50,10 @@ class View extends ViewAbstract /** * Application. * - * @var null|L11nManager + * @var L11nManager * @since 1.0.0 */ - protected ?L11nManager $l11nManager; + protected L11nManager $l11nManager; /** * Request. @@ -90,7 +90,7 @@ class View extends ViewAbstract /** * Constructor. * - * @param L11nManager $l11n Application + * @param L11nManager $l11n Localization manager * @param RequestAbstract $request Request * @param ResponseAbstract $response Request * @@ -98,7 +98,7 @@ class View extends ViewAbstract */ public function __construct(L11nManager $l11n = null, RequestAbstract $request = null, ResponseAbstract $response = null) { - $this->l11nManager = $l11n; + $this->l11nManager = $l11n ?? new L11nManager('Error'); $this->request = $request; $this->response = $response; $this->l11n = $response !== null ? $response->getHeader()->getL11n() : new Localization(); @@ -279,6 +279,68 @@ class View extends ViewAbstract return \htmlspecialchars($this->getText($translation, $module, $theme)); } + /** + * Print a numeric value + * + * @param int|float $numeric Numeric value to print + * @param null|string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getNumeric($numeric, string $format = null) : string + { + return $this->l11nManager->getNumeric($this->l11n, $numeric, $format); + } + + /** + * Print a percentage value + * + * @param float $percentage Percentage value to print + * @param null|string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getPercentage(float $percentage, string $format = null) : string + { + return $this->l11nManager->getPercentage($this->l11n, $percentage, $format); + } + + /** + * Print a currency + * + * @param int|float $currency Currency value to print + * @param null|string $format Format type to use + * @param null|string $symbol Currency name/symbol + * @param int $divide Divide currency by divisor + * + * @return string + * + * @since 1.0.0 + */ + public function getCurrency($currency, string $format = null, string $symbol = null, int $divide = 1) : string + { + return $this->l11nManager->getCurrency($this->l11n, $currency, $format, $symbol, $divide); + } + + /** + * Print a datetime + * + * @param null|\DateTime $datetime DateTime to print + * @param string $format Format type to use + * + * @return string + * + * @since 1.0.0 + */ + public function getDateTime(\DateTime $datetime = null, string $format = null) : string + { + return $this->l11nManager->getDateTime($this->l11n, $datetime, $format); + } + /** * Get request of view * diff --git a/tests/Localization/MoneyTest.php b/tests/Localization/MoneyTest.php index f3fd5e014..9cd2a0fb3 100644 --- a/tests/Localization/MoneyTest.php +++ b/tests/Localization/MoneyTest.php @@ -92,7 +92,7 @@ class MoneyTest extends \PHPUnit\Framework\TestCase public function testMoneyLocalization() : void { $money = new Money(12345678); - self::assertEquals('€9.992,30', $money->setInt(99923000)->setLocalization('.', ',', ISO4217SymbolEnum::_EUR, 0)->getCurrency()); + self::assertEquals('€ 9.992,30', $money->setInt(99923000)->setLocalization('.', ',', ISO4217SymbolEnum::_EUR, 0)->getCurrency()); } /**