diff options
Diffstat (limited to 'vendor/commerceguys/intl/src')
30 files changed, 2925 insertions, 0 deletions
diff --git a/vendor/commerceguys/intl/src/Calculator.php b/vendor/commerceguys/intl/src/Calculator.php new file mode 100644 index 000000000..e00a564c1 --- /dev/null +++ b/vendor/commerceguys/intl/src/Calculator.php @@ -0,0 +1,247 @@ +<?php + +namespace CommerceGuys\Intl; + +/** + * Provides helpers for bcmath-based arithmetic. + * + * The bcmath extension provides support for arbitrary precision arithmetic, + * which does not suffer from the precision loses that make floating point + * arithmetic unsafe for eCommerce. + * + * Important: All numbers must be passed as strings. + */ +final class Calculator +{ + /** + * Adds the second number to the first number. + * + * @param string $first_number The first number. + * @param string $second_number The second number. + * @param int $scale The maximum number of digits after the + * decimal place. Any digit after $scale will + * be truncated. + * + * @return string The result. + */ + public static function add($first_number, $second_number, $scale = 6) + { + self::assertNumberFormat($first_number); + self::assertNumberFormat($second_number); + $result = bcadd($first_number, $second_number, $scale); + + return self::trim($result); + } + + /** + * Subtracts the second number from the first number. + * + * @param string $first_number The first number. + * @param string $second_number The second number. + * @param int $scale The maximum number of digits after the + * decimal place. Any digit after $scale will + * be truncated. + * + * @return string The result. + */ + public static function subtract($first_number, $second_number, $scale = 6) + { + self::assertNumberFormat($first_number); + self::assertNumberFormat($second_number); + $result = bcsub($first_number, $second_number, $scale); + + return self::trim($result); + } + + /** + * Multiplies the first number by the second number. + * + * @param string $first_number The first number. + * @param string $second_number The second number. + * @param int $scale The maximum number of digits after the + * decimal place. Any digit after $scale will + * be truncated. + * + * @return string The result. + */ + public static function multiply($first_number, $second_number, $scale = 6) + { + self::assertNumberFormat($first_number); + self::assertNumberFormat($second_number); + $result = bcmul($first_number, $second_number, $scale); + + return self::trim($result); + } + + /** + * Divides the first number by the second number. + * + * @param string $first_number The first number. + * @param string $second_number The second number. + * @param int $scale The maximum number of digits after the + * decimal place. Any digit after $scale will + * be truncated. + * + * @return string The result. + */ + public static function divide($first_number, $second_number, $scale = 6) + { + self::assertNumberFormat($first_number); + self::assertNumberFormat($second_number); + $result = bcdiv($first_number, $second_number, $scale); + + return self::trim($result); + } + + /** + * Calculates the next highest whole value of a number. + * + * @param string $number The number. + * + * @return string The result. + */ + public static function ceil($number) + { + if (self::compare($number, 0) == 1) { + $result = bcadd($number, '1', 0); + } else { + $result = bcadd($number, '0', 0); + } + + return $result; + } + + /** + * Calculates the next lowest whole value of a number. + * + * @param string $number The number. + * + * @return string The result. + */ + public static function floor($number) + { + if (self::compare($number, 0) == 1) { + $result = bcadd($number, '0', 0); + } else { + $result = bcadd($number, '-1', 0); + } + + return $result; + } + + /** + * Rounds the given number. + * + * Replicates PHP's support for rounding to the nearest even/odd number + * even if that number is decimal ($precision > 0). + * + * @param string $number The number. + * @param int $precision The number of decimals to round to. + * @param int $mode The rounding mode. One of the following constants: + * PHP_ROUND_HALF_UP, PHP_ROUND_HALF_DOWN, + * PHP_ROUND_HALF_EVEN, PHP_ROUND_HALF_ODD. + * + * @return string The rounded number. + * + * @throws \InvalidArgumentException + */ + public static function round($number, $precision = 0, $mode = PHP_ROUND_HALF_UP) + { + self::assertNumberFormat($number); + if (!is_numeric($precision) || $precision < 0) { + throw new \InvalidArgumentException('The provided precision should be a positive number'); + } + + // Round the number in both directions (up/down) before choosing one. + $rounding_increment = bcdiv('1', pow(10, $precision), $precision); + if (self::compare($number, '0') == 1) { + $rounded_up = bcadd($number, $rounding_increment, $precision); + } else { + $rounded_up = bcsub($number, $rounding_increment, $precision); + } + $rounded_down = bcsub($number, 0, $precision); + // The rounding direction is based on the first decimal after $precision. + $number_parts = explode('.', $number); + $decimals = !empty($number_parts[1]) ? $number_parts[1] : '0'; + $relevant_decimal = isset($decimals[$precision]) ? $decimals[$precision] : 0; + if ($relevant_decimal < 5) { + $number = $rounded_down; + } elseif ($relevant_decimal == 5) { + if ($mode == PHP_ROUND_HALF_UP) { + $number = $rounded_up; + } elseif ($mode == PHP_ROUND_HALF_DOWN) { + $number = $rounded_down; + } elseif ($mode == PHP_ROUND_HALF_EVEN) { + $integer = bcmul($rounded_up, pow(10, $precision), 0); + $number = bcmod($integer, '2') == 0 ? $rounded_up : $rounded_down; + } elseif ($mode == PHP_ROUND_HALF_ODD) { + $integer = bcmul($rounded_up, pow(10, $precision), 0); + $number = bcmod($integer, '2') != 0 ? $rounded_up : $rounded_down; + } + } elseif ($relevant_decimal > 5) { + $number = $rounded_up; + } + + return $number; + } + + /** + * Compares the first number to the second number. + * + * @param string $first_number The first number. + * @param string $second_number The second number. + * @param int $scale The maximum number of digits after the + * decimal place. Any digit after $scale will + * be truncated. + * + * @return int 0 if both numbers are equal, 1 if the first one is greater, + * -1 otherwise. + */ + public static function compare($first_number, $second_number, $scale = 6) + { + self::assertNumberFormat($first_number); + self::assertNumberFormat($second_number); + + return bccomp($first_number, $second_number, $scale); + } + + /** + * Trims the given number. + * + * By default bcmath returns numbers with the number of digits according + * to $scale. This means that bcadd('2', '2', 6) will return '4.00000'. + * Trimming the number removes the excess zeroes. + * + * @param string $number The number to trim. + * + * @return string The trimmed number. + */ + public static function trim($number) + { + if (strpos($number, '.') != false) { + // The number is decimal, strip trailing zeroes. + // If no digits remain after the decimal point, strip it as well. + $number = rtrim($number, '0'); + $number = rtrim($number, '.'); + } + + return $number; + } + + /** + * Assert that the given number is a numeric string value. + * + * @param string $number The number to check. + * + * @throws \InvalidArgumentException + */ + public static function assertNumberFormat($number) + { + if (is_float($number)) { + throw new \InvalidArgumentException(sprintf('The provided value "%s" must be a string, not a float.', $number)); + } + if (!is_numeric($number)) { + throw new \InvalidArgumentException(sprintf('The provided value "%s" is not a numeric value.', $number)); + } + } +} diff --git a/vendor/commerceguys/intl/src/Country/Country.php b/vendor/commerceguys/intl/src/Country/Country.php new file mode 100644 index 000000000..7063e7d58 --- /dev/null +++ b/vendor/commerceguys/intl/src/Country/Country.php @@ -0,0 +1,168 @@ +<?php + +namespace CommerceGuys\Intl\Country; + +class Country implements CountryEntityInterface +{ + /** + * The two-letter country code. + * + * @var string + */ + protected $countryCode; + + /** + * The country name. + * + * @var string + */ + protected $name; + + /** + * The three-letter country code. + * + * @var string + */ + protected $threeLetterCode; + + /** + * The numeric country code. + * + * @var string + */ + protected $numericCode; + + /** + * The country currency code. + * + * @var string + */ + protected $currencyCode; + + /** + * The country locale (i.e. "en_US"). + * + * The country name is locale specific. + * + * @var string + */ + protected $locale; + + /** + * Returns the string representation of the Country. + * + * @return string + */ + public function __toString() + { + return $this->getCountryCode(); + } + + /** + * {@inheritdoc} + */ + public function getCountryCode() + { + return $this->countryCode; + } + + /** + * {@inheritdoc} + */ + public function setCountryCode($countryCode) + { + $this->countryCode = $countryCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getThreeLetterCode() + { + return $this->threeLetterCode; + } + + /** + * {@inheritdoc} + */ + public function setThreeLetterCode($threeLetterCode) + { + $this->threeLetterCode = $threeLetterCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNumericCode() + { + return $this->numericCode; + } + + /** + * {@inheritdoc} + */ + public function setNumericCode($numericCode) + { + $this->numericCode = $numericCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCurrencyCode() + { + return $this->currencyCode; + } + + /** + * {@inheritdoc} + */ + public function setCurrencyCode($currencyCode) + { + $this->currencyCode = $currencyCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } +} diff --git a/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php b/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php new file mode 100644 index 000000000..b22bcd42f --- /dev/null +++ b/vendor/commerceguys/intl/src/Country/CountryEntityInterface.php @@ -0,0 +1,51 @@ +<?php + +namespace CommerceGuys\Intl\Country; + +interface CountryEntityInterface extends CountryInterface +{ + /** + * Sets the two-letter country code. + * + * @param string $countryCode The two-letter country code. + * + * @return self + */ + public function setCountryCode($countryCode); + + /** + * Sets the country name. + * + * @param string $name The country name. + * + * @return self + */ + public function setName($name); + + /** + * Sets the three-letter country code. + * + * @param string $threeLetterCode The three-letter country code. + * + * @return self + */ + public function setThreeLetterCode($threeLetterCode); + + /** + * Sets the numeric country code. + * + * @param string $numericCode The numeric country code. + * + * @return self + */ + public function setNumericCode($numericCode); + + /** + * Sets the country currency code. + * + * @param string $currencyCode The currency code. + * + * @return self + */ + public function setCurrencyCode($currencyCode); +} diff --git a/vendor/commerceguys/intl/src/Country/CountryInterface.php b/vendor/commerceguys/intl/src/Country/CountryInterface.php new file mode 100644 index 000000000..f6aaf91b2 --- /dev/null +++ b/vendor/commerceguys/intl/src/Country/CountryInterface.php @@ -0,0 +1,61 @@ +<?php + +namespace CommerceGuys\Intl\Country; + +interface CountryInterface +{ + /** + * Gets the two-letter country code. + * + * @return string + */ + public function getCountryCode(); + + /** + * Gets the country name. + * + * Note that certain locales have incomplete translations, in which + * case the english version of the country name is used instead. + * + * @return string + */ + public function getName(); + + /** + * Gets the three-letter country code. + * + * Note that not every country has a three-letter code. + * CLDR lists "Canary Islands" (IC) and "Ceuta and Melilla" (EA) + * as separate countries, even though they are formally a part of Spain + * and have no three-letter or numeric ISO codes. + * + * @return string|null + */ + public function getThreeLetterCode(); + + /** + * Gets the numeric country code. + * + * The numeric code has three digits, and the first one can be a zero, + * hence the need to pass it around as a string. + * + * Note that not every country has a numeric code. + * CLDR lists "Canary Islands" (IC) and "Ceuta and Melilla" (EA) + * as separate countries, even though they are formally a part of Spain + * and have no three-letter or numeric ISO codes. + * "Ascension Island" (AE) also has no numeric code, even though it has a + * three-letter code. + * + * @return string|null + */ + public function getNumericCode(); + + /** + * Gets the country currency code. + * + * Represents the default currency used in the country, if known. + * + * @return string|null + */ + public function getCurrencyCode(); +} diff --git a/vendor/commerceguys/intl/src/Country/CountryRepository.php b/vendor/commerceguys/intl/src/Country/CountryRepository.php new file mode 100644 index 000000000..fb027dc2f --- /dev/null +++ b/vendor/commerceguys/intl/src/Country/CountryRepository.php @@ -0,0 +1,143 @@ +<?php + +namespace CommerceGuys\Intl\Country; + +use CommerceGuys\Intl\LocaleResolverTrait; +use CommerceGuys\Intl\Exception\UnknownCountryException; + +/** + * Manages countries based on JSON definitions. + */ +class CountryRepository implements CountryRepositoryInterface +{ + use LocaleResolverTrait; + + /** + * Base country definitions. + * + * Contains data common to all locales, such as the country numeric, + * three-letter, currency codes. + * + * @var array + */ + protected $baseDefinitions = []; + + /** + * Per-locale country definitions. + * + * @var array + */ + protected $definitions = []; + + /** + * Creates a CountryRepository instance. + * + * @param string $definitionPath The path to the country definitions. + * Defaults to 'resources/country'. + */ + public function __construct($definitionPath = null) + { + $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/country/'; + } + + /** + * {@inheritdoc} + */ + public function get($countryCode, $locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + if (!isset($definitions[$countryCode])) { + throw new UnknownCountryException($countryCode); + } + + return $this->createCountryFromDefinition($countryCode, $definitions[$countryCode], $locale); + } + + /** + * {@inheritdoc} + */ + public function getAll($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $countries = []; + foreach ($definitions as $countryCode => $definition) { + $countries[$countryCode] = $this->createCountryFromDefinition($countryCode, $definition, $locale); + } + + return $countries; + } + + /** + * {@inheritdoc} + */ + public function getList($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $list = []; + foreach ($definitions as $countryCode => $definition) { + $list[$countryCode] = $definition['name']; + } + + return $list; + } + + /** + * Loads the country definitions for the provided locale. + * + * @param string $locale The desired locale. + * + * @return array + */ + protected function loadDefinitions($locale) + { + if (!isset($this->definitions[$locale])) { + $filename = $this->definitionPath . $locale . '.json'; + $this->definitions[$locale] = json_decode(file_get_contents($filename), true); + + // Make sure the base definitions have been loaded. + if (empty($this->baseDefinitions)) { + $this->baseDefinitions = json_decode(file_get_contents($this->definitionPath . 'base.json'), true); + } + // Merge-in base definitions. + foreach ($this->definitions[$locale] as $countryCode => $definition) { + $this->definitions[$locale][$countryCode] += $this->baseDefinitions[$countryCode]; + } + } + + return $this->definitions[$locale]; + } + + /** + * Creates a country object from the provided definition. + * + * @param string $countryCode The country code. + * @param array $definition The country definition. + * @param string $locale The locale of the country definition. + * + * @return Country + */ + protected function createCountryFromDefinition($countryCode, array $definition, $locale) + { + $country = new Country(); + $setValues = \Closure::bind(function ($countryCode, $definition, $locale) { + $this->countryCode = $countryCode; + $this->name = $definition['name']; + $this->locale = $locale; + if (isset($definition['three_letter_code'])) { + $this->threeLetterCode = $definition['three_letter_code']; + } + if (isset($definition['numeric_code'])) { + $this->numericCode = $definition['numeric_code']; + } + if (isset($definition['currency_code'])) { + $this->currencyCode = $definition['currency_code']; + } + }, $country, '\CommerceGuys\Intl\Country\Country'); + $setValues($countryCode, $definition, $locale); + + return $country; + } +} diff --git a/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php b/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php new file mode 100644 index 000000000..fbcd5551e --- /dev/null +++ b/vendor/commerceguys/intl/src/Country/CountryRepositoryInterface.php @@ -0,0 +1,41 @@ +<?php + +namespace CommerceGuys\Intl\Country; + +/** + * Country repository interface. + */ +interface CountryRepositoryInterface +{ + /** + * Returns a country instance matching the provided country code. + * + * @param string $countryCode The country code. + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return CountryInterface + */ + public function get($countryCode, $locale = null, $fallbackLocale = null); + + /** + * Returns all country instances. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of countries implementing the CountryInterface, + * keyed by country code. + */ + public function getAll($locale = null, $fallbackLocale = null); + + /** + * Returns a list of countries. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of country names, keyed by country code. + */ + public function getList($locale = null, $fallbackLocale = null); +} diff --git a/vendor/commerceguys/intl/src/Currency/Currency.php b/vendor/commerceguys/intl/src/Currency/Currency.php new file mode 100644 index 000000000..6f9256bf0 --- /dev/null +++ b/vendor/commerceguys/intl/src/Currency/Currency.php @@ -0,0 +1,168 @@ +<?php + +namespace CommerceGuys\Intl\Currency; + +class Currency implements CurrencyEntityInterface +{ + /** + * The alphanumeric currency code. + * + * @var string + */ + protected $currencyCode; + + /** + * The currency name. + * + * @var string + */ + protected $name; + + /** + * The numeric currency code. + * + * @var string + */ + protected $numericCode; + + /** + * The currency symbol. + * + * @var string + */ + protected $symbol; + + /** + * The number of fraction digits. + * + * @var int + */ + protected $fractionDigits; + + /** + * The currency locale (i.e. "en_US"). + * + * The currency name and symbol are locale specific. + * + * @var string + */ + protected $locale; + + /** + * Returns the string representation of the currency. + * + * @return string + */ + public function __toString() + { + return $this->getCurrencyCode(); + } + + /** + * {@inheritdoc} + */ + public function getCurrencyCode() + { + return $this->currencyCode; + } + + /** + * {@inheritdoc} + */ + public function setCurrencyCode($currencyCode) + { + $this->currencyCode = $currencyCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNumericCode() + { + return $this->numericCode; + } + + /** + * {@inheritdoc} + */ + public function setNumericCode($numericCode) + { + $this->numericCode = $numericCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getSymbol() + { + return $this->symbol; + } + + /** + * {@inheritdoc} + */ + public function setSymbol($symbol) + { + $this->symbol = $symbol; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getFractionDigits() + { + return $this->fractionDigits; + } + + /** + * {@inheritdoc} + */ + public function setFractionDigits($fractionDigits) + { + $this->fractionDigits = $fractionDigits; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } +} diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php new file mode 100644 index 000000000..85d4ab83d --- /dev/null +++ b/vendor/commerceguys/intl/src/Currency/CurrencyEntityInterface.php @@ -0,0 +1,51 @@ +<?php + +namespace CommerceGuys\Intl\Currency; + +interface CurrencyEntityInterface extends CurrencyInterface +{ + /** + * Sets the alphabetic currency code. + * + * @param string $currencyCode The alphabetic currency code. + * + * @return self + */ + public function setCurrencyCode($currencyCode); + + /** + * Sets the currency name. + * + * @param string $name The currency name. + * + * @return self + */ + public function setName($name); + + /** + * Sets the numeric currency code. + * + * @param string $numericCode The numeric currency code. + * + * @return self + */ + public function setNumericCode($numericCode); + + /** + * Sets the currency symbol. + * + * @param string $symbol The currency symbol. + * + * @return self + */ + public function setSymbol($symbol); + + /** + * Sets the number of fraction digits. + * + * @param int $fractionDigits The number of fraction digits. + * + * @return self + */ + public function setFractionDigits($fractionDigits); +} diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php new file mode 100644 index 000000000..8aa709ca0 --- /dev/null +++ b/vendor/commerceguys/intl/src/Currency/CurrencyInterface.php @@ -0,0 +1,47 @@ +<?php + +namespace CommerceGuys\Intl\Currency; + +interface CurrencyInterface +{ + /** + * Gets the alphabetic currency code. + * + * @return string + */ + public function getCurrencyCode(); + + /** + * Gets the currency name. + * + * @return string + */ + public function getName(); + + /** + * Gets the numeric currency code. + * + * The numeric code has three digits, and the first one can be a zero, + * hence the need to pass it around as a string. + * + * @return string + */ + public function getNumericCode(); + + /** + * Gets the currency symbol. + * + * @return string + */ + public function getSymbol(); + + /** + * Gets the number of fraction digits. + * + * Used when rounding or formatting an amount for display. + * Actual storage precision can be greater. + * + * @return int + */ + public function getFractionDigits(); +} diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php b/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php new file mode 100644 index 000000000..5fdfce216 --- /dev/null +++ b/vendor/commerceguys/intl/src/Currency/CurrencyRepository.php @@ -0,0 +1,144 @@ +<?php + +namespace CommerceGuys\Intl\Currency; + +use CommerceGuys\Intl\LocaleResolverTrait; +use CommerceGuys\Intl\Exception\UnknownCurrencyException; + +/** + * Manages currencies based on JSON definitions. + */ +class CurrencyRepository implements CurrencyRepositoryInterface +{ + use LocaleResolverTrait; + + /** + * Base currency definitions. + * + * Contains data common to all locales, such as the currency numeric + * code, number of fraction digits. + * + * @var array + */ + protected $baseDefinitions = []; + + /** + * Per-locale currency definitions. + * + * @var array + */ + protected $definitions = []; + + /** + * Creates a CurrencyRepository instance. + * + * @param string $definitionPath The path to the currency definitions. + * Defaults to 'resources/currency'. + */ + public function __construct($definitionPath = null) + { + $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/currency/'; + } + + /** + * {@inheritdoc} + */ + public function get($currencyCode, $locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + if (!isset($definitions[$currencyCode])) { + throw new UnknownCurrencyException($currencyCode); + } + + return $this->createCurrencyFromDefinition($currencyCode, $definitions[$currencyCode], $locale); + } + + /** + * {@inheritdoc} + */ + public function getAll($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $currencies = []; + foreach ($definitions as $currencyCode => $definition) { + $currencies[$currencyCode] = $this->createCurrencyFromDefinition($currencyCode, $definition, $locale); + } + + return $currencies; + } + + /** + * {@inheritdoc} + */ + public function getList($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $list = []; + foreach ($definitions as $currencyCode => $definition) { + $list[$currencyCode] = $definition['name']; + } + + return $list; + } + + /** + * Loads the currency definitions for the provided locale. + * + * @param string $locale The desired locale. + * + * @return array + */ + protected function loadDefinitions($locale) + { + if (!isset($this->definitions[$locale])) { + $filename = $this->definitionPath . $locale . '.json'; + $this->definitions[$locale] = json_decode(file_get_contents($filename), true); + + // Make sure the base definitions have been loaded. + if (empty($this->baseDefinitions)) { + $this->baseDefinitions = json_decode(file_get_contents($this->definitionPath . 'base.json'), true); + } + // Merge-in base definitions. + foreach ($this->definitions[$locale] as $currencyCode => $definition) { + $this->definitions[$locale][$currencyCode] += $this->baseDefinitions[$currencyCode]; + } + } + + return $this->definitions[$locale]; + } + + /** + * Creates a currency object from the provided definition. + * + * @param string $currencyCode The currency code. + * @param array $definition The currency definition. + * @param string $locale The locale of the currency definition. + * + * @return Currency + */ + protected function createCurrencyFromDefinition($currencyCode, array $definition, $locale) + { + if (!isset($definition['symbol'])) { + $definition['symbol'] = $currencyCode; + } + if (!isset($definition['fraction_digits'])) { + $definition['fraction_digits'] = 2; + } + + $currency = new Currency(); + $setValues = \Closure::bind(function ($currencyCode, $definition, $locale) { + $this->currencyCode = $currencyCode; + $this->name = $definition['name']; + $this->numericCode = $definition['numeric_code']; + $this->symbol = $definition['symbol']; + $this->fractionDigits = $definition['fraction_digits']; + $this->locale = $locale; + }, $currency, '\CommerceGuys\Intl\Currency\Currency'); + $setValues($currencyCode, $definition, $locale); + + return $currency; + } +} diff --git a/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php b/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php new file mode 100644 index 000000000..f0a091969 --- /dev/null +++ b/vendor/commerceguys/intl/src/Currency/CurrencyRepositoryInterface.php @@ -0,0 +1,41 @@ +<?php + +namespace CommerceGuys\Intl\Currency; + +/** + * Currency repository interface. + */ +interface CurrencyRepositoryInterface +{ + /** + * Returns a currency instance matching the provided currency code. + * + * @param string $currencyCode The currency code. + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return CurrencyInterface + */ + public function get($currencyCode, $locale = null, $fallbackLocale = null); + + /** + * Returns all currency instances. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of currencies implementing the CurrencyInterface, + * keyed by currency code. + */ + public function getAll($locale = null, $fallbackLocale = null); + + /** + * Returns a list of currencies. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of currency names, keyed by currency code. + */ + public function getList($locale = null, $fallbackLocale = null); +} diff --git a/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php b/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php new file mode 100644 index 000000000..a7d17f9ab --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/ExceptionInterface.php @@ -0,0 +1,7 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +interface ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php b/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php new file mode 100644 index 000000000..afbe114a4 --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/InvalidArgumentException.php @@ -0,0 +1,11 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +/** + * This exception is thrown when an invalid argument is passed to a method. + * For example, a float amount instead of the expected string amount. + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php b/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php new file mode 100644 index 000000000..c89845b23 --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/UnknownCountryException.php @@ -0,0 +1,11 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +/** + * This exception is thrown when an unknown country code is passed to the + * CountryRepository. + */ +class UnknownCountryException extends InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php b/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php new file mode 100644 index 000000000..f94c93d8a --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/UnknownCurrencyException.php @@ -0,0 +1,11 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +/** + * This exception is thrown when an unknown currency code is passed to the + * CurrencyRepository. + */ +class UnknownCurrencyException extends InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php b/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php new file mode 100644 index 000000000..922b42185 --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/UnknownLanguageException.php @@ -0,0 +1,11 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +/** + * This exception is thrown when an unknown language code is passed to the + * LanguageRepository. + */ +class UnknownLanguageException extends InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php b/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php new file mode 100644 index 000000000..0deca13e8 --- /dev/null +++ b/vendor/commerceguys/intl/src/Exception/UnknownLocaleException.php @@ -0,0 +1,10 @@ +<?php + +namespace CommerceGuys\Intl\Exception; + +/** + * This exception is thrown when an unknown locale is passed to a repository. + */ +class UnknownLocaleException extends InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php b/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php new file mode 100644 index 000000000..5d36fc89b --- /dev/null +++ b/vendor/commerceguys/intl/src/Formatter/NumberFormatter.php @@ -0,0 +1,421 @@ +<?php + +namespace CommerceGuys\Intl\Formatter; + +use CommerceGuys\Intl\Currency\CurrencyInterface; +use CommerceGuys\Intl\Exception\InvalidArgumentException; +use CommerceGuys\Intl\NumberFormat\NumberFormatInterface; + +/** + * Formats numbers using locale-specific patterns. + */ +class NumberFormatter implements NumberFormatterInterface +{ + /** + * The number format. + * + * @var NumberFormatInterface + */ + protected $numberFormat; + + /** + * The number pattern used to format positive numbers. + * + * @var string + */ + protected $positivePattern; + + /** + * The number pattern used to format negative numbers. + * + * @var string + */ + protected $negativePattern; + + /** + * Whether grouping is used. + * + * @var bool + */ + protected $groupingUsed; + + /** + * The size of the group of digits closest to the decimal point. + * + * @var int + */ + protected $primaryGroupSize; + + /** + * The size of every group of digits after the primary group. + * + * @var int + */ + protected $secondaryGroupSize; + + /** + * The minimum number of fraction digits to show. + * + * @var int + */ + protected $minimumFractionDigits; + + /** + * The maximum number of fraction digits to show. + * + * @var int + */ + protected $maximumFractionDigits; + + /** + * The currency display style. + * + * @var int + */ + protected $currencyDisplay; + + /** + * Localized digits. + * + * @var array + */ + protected $digits = [ + NumberFormatInterface::NUMBERING_SYSTEM_ARABIC => [ + 0 => 'Ù ', 1 => 'Ù¡', 2 => 'Ù¢', 3 => 'Ù£', 4 => 'Ù¤', + 5 => 'Ù¥', 6 => 'Ù¦', 7 => 'Ù§', 8 => 'Ù¨', 9 => 'Ù©', + ], + NumberFormatInterface::NUMBERING_SYSTEM_ARABIC_EXTENDED => [ + 0 => 'Û°', 1 => 'Û±', 2 => 'Û²', 3 => 'Û³', 4 => 'Û´', + 5 => 'Ûµ', 6 => 'Û¶', 7 => 'Û·', 8 => 'Û¸', 9 => 'Û¹', + ], + NumberFormatInterface::NUMBERING_SYSTEM_BENGALI => [ + 0 => '০', 1 => '১', 2 => '২', 3 => '৩', 4 => '৪', + 5 => '৫', 6 => '৬', 7 => 'à§', 8 => '৮', 9 => '৯', + ], + NumberFormatInterface::NUMBERING_SYSTEM_DEVANAGARI => [ + 0 => '०', 1 => '१', 2 => '२', 3 => '३', 4 => '४', + 5 => '५', 6 => '६', 7 => 'à¥', 8 => '८', 9 => '९', + ], + ]; + + /** + * Creaes a NumberFormatter instance. + * + * @param NumberFormatInterface $numberFormat The number format. + * @param int $style The formatting style. + * + * @throws \InvalidArgumentException + * @throws \RuntimeException + */ + public function __construct(NumberFormatInterface $numberFormat, $style = self::DECIMAL) + { + if (!extension_loaded('bcmath')) { + throw new \RuntimeException('The bcmath extension is required by NumberFormatter.'); + } + $availablePatterns = [ + self::DECIMAL => $numberFormat->getDecimalPattern(), + self::PERCENT => $numberFormat->getPercentPattern(), + self::CURRENCY => $numberFormat->getCurrencyPattern(), + self::CURRENCY_ACCOUNTING => $numberFormat->getAccountingCurrencyPattern(), + ]; + if (!array_key_exists($style, $availablePatterns)) { + // Unknown type. + throw new InvalidArgumentException('Unknown format style provided to NumberFormatter::__construct().'); + } + + // Split the selected pattern into positive and negative patterns. + $patterns = explode(';', $availablePatterns[$style]); + if (!isset($patterns[1])) { + // No explicit negative pattern was provided, construct it. + $patterns[1] = '-' . $patterns[0]; + } + + $this->numberFormat = $numberFormat; + $this->positivePattern = $patterns[0]; + $this->negativePattern = $patterns[1]; + $this->groupingUsed = (strpos($this->positivePattern, ',') !== false); + // This pattern has number groups, parse them. + if ($this->groupingUsed) { + preg_match('/#+0/', $this->positivePattern, $primaryGroupMatches); + $this->primaryGroupSize = $this->secondaryGroupSize = strlen($primaryGroupMatches[0]); + $numberGroups = explode(',', $this->positivePattern); + if (count($numberGroups) > 2) { + // This pattern has a distinct secondary group size. + $this->secondaryGroupSize = strlen($numberGroups[1]); + } + } + + // Initialize the fraction digit settings for decimal and percent + // styles only. The currency ones will default to the currency values. + if (in_array($style, [self::DECIMAL, self::PERCENT])) { + $this->minimumFractionDigits = 0; + $this->maximumFractionDigits = 3; + } + $this->currencyDisplay = self::CURRENCY_DISPLAY_SYMBOL; + } + + /** + * {@inheritdoc} + */ + public function format($value) + { + if (!is_numeric($value)) { + $message = sprintf('The provided value "%s" must be a valid number or numeric string.', $value); + throw new InvalidArgumentException($message); + } + + // Ensure that the value is positive and has the right number of digits. + $negative = (bccomp('0', $value, 12) == 1); + $signMultiplier = $negative ? '-1' : '1'; + $value = bcdiv($value, $signMultiplier, $this->maximumFractionDigits); + // Split the number into major and minor digits. + $valueParts = explode('.', $value); + $majorDigits = $valueParts[0]; + // Account for maximumFractionDigits = 0, where the number won't + // have a decimal point, and $valueParts[1] won't be set. + $minorDigits = isset($valueParts[1]) ? $valueParts[1] : ''; + + if ($this->groupingUsed) { + // Reverse the major digits, since they are grouped from the right. + $majorDigits = array_reverse(str_split($majorDigits)); + // Group the major digits. + $groups = []; + $groups[] = array_splice($majorDigits, 0, $this->primaryGroupSize); + while (!empty($majorDigits)) { + $groups[] = array_splice($majorDigits, 0, $this->secondaryGroupSize); + } + // Reverse the groups and the digits inside of them. + $groups = array_reverse($groups); + foreach ($groups as &$group) { + $group = implode(array_reverse($group)); + } + // Reconstruct the major digits. + $majorDigits = implode(',', $groups); + } + + if ($this->minimumFractionDigits < $this->maximumFractionDigits) { + // Strip any trailing zeroes. + $minorDigits = rtrim($minorDigits, '0'); + if (strlen($minorDigits) < $this->minimumFractionDigits) { + // Now there are too few digits, re-add trailing zeroes + // until the desired length is reached. + $neededZeroes = $this->minimumFractionDigits - strlen($minorDigits); + $minorDigits .= str_repeat('0', $neededZeroes); + } + } + + // Assemble the final number and insert it into the pattern. + $value = strlen($minorDigits) ? $majorDigits . '.' . $minorDigits : $majorDigits; + $pattern = $negative ? $this->negativePattern : $this->positivePattern; + $value = preg_replace('/#(?:[\.,]#+)*0(?:[,\.][0#]+)*/', $value, $pattern); + + // Localize the number. + $value = $this->replaceDigits($value); + $value = $this->replaceSymbols($value); + + return $value; + } + + /** + * {@inheritdoc} + */ + public function formatCurrency($value, CurrencyInterface $currency) + { + // Use the currency defaults if the values weren't set by the caller. + $resetMinimumFractionDigits = $resetMaximumFractionDigits = false; + if (!isset($this->minimumFractionDigits)) { + $this->minimumFractionDigits = $currency->getFractionDigits(); + $resetMinimumFractionDigits = true; + } + if (!isset($this->maximumFractionDigits)) { + $this->maximumFractionDigits = $currency->getFractionDigits(); + $resetMaximumFractionDigits = true; + } + + // Format the decimal part of the value first. + $value = $this->format($value); + + // Reset the fraction digit settings, so that they don't affect + // future formattings with different currencies. + if ($resetMinimumFractionDigits) { + $this->minimumFractionDigits = null; + } + if ($resetMaximumFractionDigits) { + $this->maximumFractionDigits = null; + } + + // Determine whether to show the currency symbol or the currency code. + if ($this->currencyDisplay == self::CURRENCY_DISPLAY_SYMBOL) { + $symbol = $currency->getSymbol(); + } else { + $symbol = $currency->getCurrencyCode(); + } + + return str_replace('¤', $symbol, $value); + } + + /** + * {@inheritdoc} + */ + public function parse($value) + { + $replacements = [ + $this->numberFormat->getGroupingSeparator() => '', + // Convert the localized symbols back to their original form. + $this->numberFormat->getDecimalSeparator() => '.', + $this->numberFormat->getPlusSign() => '+', + $this->numberFormat->getMinusSign() => '-', + + // Strip whitespace (spaces and non-breaking spaces). + ' ' => '', + chr(0xC2) . chr(0xA0) => '', + ]; + $numberingSystem = $this->numberFormat->getNumberingSystem(); + if (isset($this->digits[$numberingSystem])) { + // Convert the localized digits back to latin. + $replacements += array_flip($this->digits[$numberingSystem]); + } + + $value = strtr($value, $replacements); + if (substr($value, 0, 1) == '(' && substr($value, -1, 1) == ')') { + // This is an accounting formatted negative number. + $value = '-' . str_replace(['(', ')'], '', $value); + } + + return is_numeric($value) ? $value : false; + } + + /** + * {@inheritdoc} + */ + public function parseCurrency($value, CurrencyInterface $currency) + { + $replacements = [ + // Strip the currency code or symbol. + $currency->getCurrencyCode() => '', + $currency->getSymbol() => '', + ]; + $value = strtr($value, $replacements); + + return $this->parse($value); + } + + /** + * Replaces digits with their localized equivalents. + * + * @param string $value The value being formatted. + * + * @return string + */ + protected function replaceDigits($value) + { + $numberingSystem = $this->numberFormat->getNumberingSystem(); + if (isset($this->digits[$numberingSystem])) { + $value = strtr($value, $this->digits[$numberingSystem]); + } + + return $value; + } + + /** + * Replaces number symbols with their localized equivalents. + * + * @param string $value The value being formatted. + * + * @return string + * + * @see http://cldr.unicode.org/translation/number-symbols + */ + protected function replaceSymbols($value) + { + $replacements = [ + '.' => $this->numberFormat->getDecimalSeparator(), + ',' => $this->numberFormat->getGroupingSeparator(), + '+' => $this->numberFormat->getPlusSign(), + '-' => $this->numberFormat->getMinusSign(), + '%' => $this->numberFormat->getPercentSign(), + ]; + + return strtr($value, $replacements); + } + + /** + * {@inheritdoc} + */ + public function getNumberFormat() + { + return $this->numberFormat; + } + + /** + * {@inheritdoc} + */ + public function getMinimumFractionDigits() + { + return $this->minimumFractionDigits; + } + + /** + * {@inheritdoc} + */ + public function setMinimumFractionDigits($minimumFractionDigits) + { + $this->minimumFractionDigits = $minimumFractionDigits; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getMaximumFractionDigits() + { + return $this->maximumFractionDigits; + } + + /** + * {@inheritdoc} + */ + public function setMaximumFractionDigits($maximumFractionDigits) + { + $this->maximumFractionDigits = $maximumFractionDigits; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function isGroupingUsed() + { + return $this->groupingUsed; + } + + /** + * {@inheritdoc} + */ + public function setGroupingUsed($groupingUsed) + { + $this->groupingUsed = $groupingUsed; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCurrencyDisplay() + { + return $this->currencyDisplay; + } + + /** + * {@inheritdoc} + */ + public function setCurrencyDisplay($currencyDisplay) + { + $this->currencyDisplay = $currencyDisplay; + + return $this; + } +} diff --git a/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php b/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php new file mode 100644 index 000000000..3a510be2a --- /dev/null +++ b/vendor/commerceguys/intl/src/Formatter/NumberFormatterInterface.php @@ -0,0 +1,151 @@ +<?php + +namespace CommerceGuys\Intl\Formatter; + +use CommerceGuys\Intl\Currency\CurrencyInterface; +use CommerceGuys\Intl\NumberFormat\NumberFormatInterface; + +interface NumberFormatterInterface +{ + /* Format style constants */ + const DECIMAL = 1; + const PERCENT = 2; + const CURRENCY = 3; + const CURRENCY_ACCOUNTING = 4; + + /* Currency display style constants */ + const CURRENCY_DISPLAY_SYMBOL = 1; + const CURRENCY_DISPLAY_CODE = 2; + + /** + * Formats a number. + * + * Please note that the provided value should already be rounded. + * This formatter doesn't do any rounding of its own, and will simply + * truncate extra digits. + * + * @param string $value The value to format. + * + * @return string + */ + public function format($value); + + /** + * Formats a currency value. + * + * Please note that the provided value should already be rounded. + * This formatter doesn't do any rounding of its own, and will simply + * truncate extra digits. + * + * @param string $value The value to format. + * @param CurrencyInterface $currency The currency. + * + * @return string + */ + public function formatCurrency($value, CurrencyInterface $currency); + + /** + * Parses a number. + * + * Commonly used in input widgets where the end-user might input + * a value using digits and symbols common to their locale. + * + * @param string $value The value to parse. + * + * @return string|false The parsed numeric value or FALSE on error. + */ + public function parse($value); + + /** + * Parses a formatted currency value. + * + * @param string $value The value to parse. + * @param CurrencyInterface $currency The currency. + * + * @return string|false The parsed numeric value or FALSE on error. + */ + public function parseCurrency($value, CurrencyInterface $currency); + + /** + * Gets the number format. + * + * @return NumberFormatInterface + */ + public function getNumberFormat(); + + /** + * Gets the minimum number of fraction digits. + * + * Defaults to 0 for decimal and percentage styles. + * Defaults to null for currency styles, since the currency number of + * fraction digits is used as the default in that case. + * + * @return int + */ + public function getMinimumFractionDigits(); + + /** + * Sets the minimum number of fraction digits. + * + * @param int $minimumFractionDigits + * + * @return self + */ + public function setMinimumFractionDigits($minimumFractionDigits); + + /** + * Gets the maximum number of fraction digits. + * + * Defaults to 3 for decimal and percentage styles. + * Defaults to null for currency styles, since the currency number of + * fraction digits is used as the default in that case. + * + * @return int + */ + public function getMaximumFractionDigits(); + + /** + * Sets the maximum number of fraction digits. + * + * @param int $maximumFractionDigits + * + * @return self + */ + public function setMaximumFractionDigits($maximumFractionDigits); + + /** + * Returns whether the major digits will be grouped. + * + * @return bool + */ + public function isGroupingUsed(); + + /** + * Sets whether or not major digits should be grouped. + * + * @param bool $groupingUsed + * + * @return self + */ + public function setGroupingUsed($groupingUsed); + + /** + * Gets the currency display style. + * + * Controls whether a currency amount will be shown with the + * currency symbol (CURRENCY_DISPLAY_SYMBOL) or the + * currency code (CURRENCY_DISPLAY_CODE). + * + * @return int + */ + public function getCurrencyDisplay(); + + /** + * Sets the currency display style. + * + * @param int $currencyDisplay One of the CURRENCY_DISPLAY_ constants. + * + * @return self + */ + public function setCurrencyDisplay($currencyDisplay); +} diff --git a/vendor/commerceguys/intl/src/Language/Language.php b/vendor/commerceguys/intl/src/Language/Language.php new file mode 100644 index 000000000..9958d5481 --- /dev/null +++ b/vendor/commerceguys/intl/src/Language/Language.php @@ -0,0 +1,91 @@ +<?php + +namespace CommerceGuys\Intl\Language; + +class Language implements LanguageEntityInterface +{ + /** + * The two-letter language code. + * + * @var string + */ + protected $languageCode; + + /** + * The language name. + * + * @var string + */ + protected $name; + + /** + * The language locale (i.e. "en-US"). + * + * @var string + */ + protected $locale; + + /** + * Returns the string representation of the Language. + * + * @return string + */ + public function __toString() + { + return $this->getLanguageCode(); + } + + /** + * {@inheritdoc} + */ + public function getLanguageCode() + { + return $this->languageCode; + } + + /** + * {@inheritdoc} + */ + public function setLanguageCode($languageCode) + { + $this->languageCode = $languageCode; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritdoc} + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } +} diff --git a/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php b/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php new file mode 100644 index 000000000..e36e0bf77 --- /dev/null +++ b/vendor/commerceguys/intl/src/Language/LanguageEntityInterface.php @@ -0,0 +1,24 @@ +<?php + +namespace CommerceGuys\Intl\Language; + +interface LanguageEntityInterface extends LanguageInterface +{ + /** + * Sets the two-letter language code. + * + * @param string $languageCode The two-letter language code. + * + * @return self + */ + public function setLanguageCode($languageCode); + + /** + * Sets the language name. + * + * @param string $name The language name. + * + * @return self + */ + public function setName($name); +} diff --git a/vendor/commerceguys/intl/src/Language/LanguageInterface.php b/vendor/commerceguys/intl/src/Language/LanguageInterface.php new file mode 100644 index 000000000..14c603dfd --- /dev/null +++ b/vendor/commerceguys/intl/src/Language/LanguageInterface.php @@ -0,0 +1,23 @@ +<?php + +namespace CommerceGuys\Intl\Language; + +interface LanguageInterface +{ + /** + * Gets the two-letter language code. + * + * @return string + */ + public function getLanguageCode(); + + /** + * Gets the language name. + * + * Note that certain locales have incomplete translations, in which + * case the english version of the language name is used instead. + * + * @return string + */ + public function getName(); +} diff --git a/vendor/commerceguys/intl/src/Language/LanguageRepository.php b/vendor/commerceguys/intl/src/Language/LanguageRepository.php new file mode 100644 index 000000000..4fc02f2ff --- /dev/null +++ b/vendor/commerceguys/intl/src/Language/LanguageRepository.php @@ -0,0 +1,115 @@ +<?php + +namespace CommerceGuys\Intl\Language; + +use CommerceGuys\Intl\LocaleResolverTrait; +use CommerceGuys\Intl\Exception\UnknownLanguageException; + +/** + * Manages languages based on JSON definitions. + */ +class LanguageRepository implements LanguageRepositoryInterface +{ + use LocaleResolverTrait; + + /** + * Per-locale language definitions. + * + * @var array + */ + protected $definitions = []; + + /** + * Creates a LanguageRepository instance. + * + * @param string $definitionPath The path to the currency definitions. + * Defaults to 'resources/language'. + */ + public function __construct($definitionPath = null) + { + $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/language/'; + } + + /** + * {@inheritdoc} + */ + public function get($languageCode, $locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + if (!isset($definitions[$languageCode])) { + throw new UnknownLanguageException($languageCode); + } + + return $this->createLanguageFromDefinition($languageCode, $definitions[$languageCode], $locale); + } + + /** + * {@inheritdoc} + */ + public function getAll($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $languages = []; + foreach ($definitions as $languageCode => $definition) { + $languages[$languageCode] = $this->createLanguageFromDefinition($languageCode, $definition, $locale); + } + + return $languages; + } + + /** + * {@inheritdoc} + */ + public function getList($locale = null, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + $definitions = $this->loadDefinitions($locale); + $list = []; + foreach ($definitions as $languageCode => $definition) { + $list[$languageCode] = $definition['name']; + } + + return $list; + } + + /** + * Loads the language definitions for the provided locale. + * + * @param string $locale The desired locale. + * + * @return array + */ + protected function loadDefinitions($locale) + { + if (!isset($this->definitions[$locale])) { + $filename = $this->definitionPath . $locale . '.json'; + $this->definitions[$locale] = json_decode(file_get_contents($filename), true); + } + + return $this->definitions[$locale]; + } + + /** + * Creates a language object from the provided definition. + * + * @param string $languageCode The language code. + * @param array $definition The language definition. + * @param string $locale The locale of the language definition. + * + * @return Language + */ + protected function createLanguageFromDefinition($languageCode, array $definition, $locale) + { + $language = new Language(); + $setValues = \Closure::bind(function ($languageCode, $definition, $locale) { + $this->languageCode = $languageCode; + $this->name = $definition['name']; + $this->locale = $locale; + }, $language, '\CommerceGuys\Intl\Language\Language'); + $setValues($languageCode, $definition, $locale); + + return $language; + } +} diff --git a/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php b/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php new file mode 100644 index 000000000..dd14250e0 --- /dev/null +++ b/vendor/commerceguys/intl/src/Language/LanguageRepositoryInterface.php @@ -0,0 +1,41 @@ +<?php + +namespace CommerceGuys\Intl\Language; + +/** + * Language repository interface. + */ +interface LanguageRepositoryInterface +{ + /** + * Returns a language instance matching the provided language code. + * + * @param string $languageCode The language code. + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return LanguageInterface + */ + public function get($languageCode, $locale = null, $fallbackLocale = null); + + /** + * Returns all language instances. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of languages implementing the LanguageInterface, + * keyed by language code. + */ + public function getAll($locale = null, $fallbackLocale = null); + + /** + * Returns a list of languages. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return array An array of language names, keyed by language code. + */ + public function getList($locale = null, $fallbackLocale = null); +} diff --git a/vendor/commerceguys/intl/src/LocaleResolverTrait.php b/vendor/commerceguys/intl/src/LocaleResolverTrait.php new file mode 100644 index 000000000..797e5abaf --- /dev/null +++ b/vendor/commerceguys/intl/src/LocaleResolverTrait.php @@ -0,0 +1,244 @@ +<?php + +namespace CommerceGuys\Intl; + +use CommerceGuys\Intl\Exception\UnknownLocaleException; + +trait LocaleResolverTrait +{ + /** + * The path where per-locale definitions are stored. + * + * @var string + */ + protected $definitionPath; + + /** + * The default locale. + * + * @var string + */ + protected $defaultLocale = 'en'; + + /** + * The fallback locale. + * + * @var string + */ + protected $fallbackLocale = null; + + /** + * Common locale aliases. + * + * @var array + */ + protected $localeAliases = [ + 'az-AZ' => 'az-Latn-AZ', + 'bs-BA' => 'bs-Latn-BA', + 'ha-GH' => 'ha-Latn-GH', + 'ha-NE' => 'ha-Latn-NE', + 'ha-NG' => 'ha-Latn-NG', + 'in' => 'id', + 'in-ID' => 'id-ID', + 'iw' => 'he', + 'iw-IL' => 'he-IL', + 'kk-KZ' => 'kk-Cyrl-KZ', + 'ks-IN' => 'ks-Arab-IN', + 'ky-KG' => 'ky-Cyrl-KG', + 'mn-MN' => 'mn-Cyrl-MN', + 'mo' => 'ro-MD', + 'ms-BN' => 'ms-Latn-BN', + 'ms-MY' => 'ms-Latn-MY', + 'ms-SG' => 'ms-Latn-SG', + 'no' => 'nb', + 'no-NO' => 'nb-NO', + 'no-NO-NY' => 'nn-NO', + 'pa-IN' => 'pa-Guru-IN', + 'pa-PK' => 'pa-Arab-PK', + 'sh' => 'sr-Latn', + 'sh-BA' => 'sr-Latn-BA', + 'sh-CS' => 'sr-Latn-RS', + 'sh-YU' => 'sr-Latn-RS', + 'shi-MA' => 'shi-Tfng-MA', + 'sr-BA' => 'sr-Cyrl-BA', + 'sr-ME' => 'sr-Latn-ME', + 'sr-RS' => 'sr-Cyrl-RS', + 'sr-XK' => 'sr-Cyrl-XK', + 'tl' => 'fil', + 'tl-PH' => 'fil-PH', + 'tzm-MA' => 'tzm-Latn-MA', + 'ug-CN' => 'ug-Arab-CN', + 'uz-AF' => 'uz-Arab-AF', + 'uz-UZ' => 'uz-Latn-UZ', + 'vai-LR' => 'vai-Vaii-LR', + 'zh-CN' => 'zh-Hans-CN', + 'zh-HK' => 'zh-Hant-HK', + 'zh-MO' => 'zh-Hant-MO', + 'zh-SG' => 'zh-Hans-SG', + 'zh-TW' => 'zh-Hant-TW', + ]; + + /** + * Determines which locale should be used for loading definitions. + * + * If the "bs-Cyrl-BA" locale is requested, with an "en" fallback, + * the system will try to find the definitions for: + * 1) bs-Cyrl-BA + * 2) bs-Cyrl + * 3) bs + * 4) en + * The first locale for which a definition file is found, wins. + * Otherwise, an exception is thrown. + * + * @param string $locale The desired locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return string + * + * @throws UnknownLocaleException + */ + protected function resolveLocale($locale = null, $fallbackLocale = null) + { + $locale = $locale ?: $this->getDefaultLocale(); + $locale = $this->canonicalizeLocale($locale); + $locale = $this->resolveLocaleAlias($locale); + // List all possible variants (i.e. en-US gives "en-US" and "en"). + $localeVariants = $this->getLocaleVariants($locale); + // A fallback locale was provided, add it to the end of the chain. + $fallbackLocale = $fallbackLocale ?: $this->getFallbackLocale(); + if (isset($fallbackLocale)) { + $localeVariants[] = $fallbackLocale; + } + + // Try to resolve a locale by finding a matching definition file. + $resolvedLocale = null; + foreach ($localeVariants as $localeVariant) { + $path = $this->definitionPath . $localeVariant . '.json'; + if (file_exists($path)) { + $resolvedLocale = $localeVariant; + break; + } + } + // No locale could be resolved, stop here. + if (!$resolvedLocale) { + throw new UnknownLocaleException($locale); + } + + return $resolvedLocale; + } + + /** + * Resolves known locale aliases. + * + * For example, "zh-CN" is resolved to "zh-Hans-CN". + * + * @param string $locale The locale. + * + * @return string The locale. + */ + protected function resolveLocaleAlias($locale = null) + { + if ($locale && isset($this->localeAliases[$locale])) { + $locale = $this->localeAliases[$locale]; + } + + return $locale; + } + + /** + * Canonicalize the given locale. + * + * @param string $locale The locale. + * + * @return string The canonicalized locale. + */ + protected function canonicalizeLocale($locale = null) + { + if (is_null($locale)) { + return $locale; + } + + $locale = str_replace('-', '_', strtolower($locale)); + $localeParts = explode('_', $locale); + foreach ($localeParts as $index => $part) { + if ($index === 0) { + // The language code should stay lowercase. + continue; + } + + if (strlen($part) == 4) { + // Script code. + $localeParts[$index] = ucfirst($part); + } else { + // Country or variant code. + $localeParts[$index] = strtoupper($part); + } + } + + return implode('-', $localeParts); + } + + /** + * Gets the default locale. + * + * @return string The default locale. + */ + public function getDefaultLocale() + { + return $this->defaultLocale; + } + + /** + * Sets the default locale. + * + * @return void + */ + public function setDefaultLocale($locale) + { + $this->defaultLocale = $locale; + } + + /** + * Gets the fallback locale. + * + * @return string The fallback locale. + */ + public function getFallbackLocale() + { + return $this->fallbackLocale; + } + + /** + * Sets the fallback locale. + * + * @return void + */ + public function setFallbackLocale($locale) + { + $this->fallbackLocale = $locale; + } + + /** + * Gets all variants of a locale. + * + * For example, "bs-Cyrl-BA" has the following variants: + * 1) bs-Cyrl-BA + * 2) bs-Cyrl + * 3) bs + * + * @param string $locale The locale (i.e. fr-FR). + * + * @return array An array of all variants of a locale. + */ + protected function getLocaleVariants($locale) + { + $localeVariants = []; + $localeParts = explode('-', $locale); + while (!empty($localeParts)) { + $localeVariants[] = implode('-', $localeParts); + array_pop($localeParts); + } + + return $localeVariants; + } +} diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php new file mode 100644 index 000000000..077f6721f --- /dev/null +++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormat.php @@ -0,0 +1,269 @@ +<?php + +namespace CommerceGuys\Intl\NumberFormat; + +class NumberFormat implements NumberFormatEntityInterface +{ + /** + * The locale (i.e. "en_US"). + * + * @var string + */ + protected $locale; + + /** + * The numbering system. + * + * @var string + */ + protected $numberingSystem = []; + + /** + * The decimal separator. + * + * @var string + */ + protected $decimalSeparator = []; + + /** + * The grouping separator. + * + * @var string + */ + protected $groupingSeparator = []; + + /** + * The plus sign. + * + * @var string + */ + protected $plusSign = []; + + /** + * The number symbols. + * + * @var string + */ + protected $minusSign = []; + + /** + * The percent sign. + * + * @var string + */ + protected $percentSign = []; + + /** + * The number pattern used to format decimal numbers. + * + * @var string + */ + protected $decimalPattern; + + /** + * The number pattern used to format percentages. + * + * @var string + */ + protected $percentPattern; + + /** + * The number pattern used to format currency amounts. + * + * @var string + */ + protected $currencyPattern; + + /** + * The number pattern used to format accounting currency amounts. + * + * @var string + */ + protected $accountingCurrencyPattern; + + /** + * {@inheritdoc} + */ + public function getLocale() + { + return $this->locale; + } + + /** + * {@inheritdoc} + */ + public function setLocale($locale) + { + $this->locale = $locale; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNumberingSystem() + { + return $this->numberingSystem; + } + + /** + * {@inheritdoc} + */ + public function setNumberingSystem($numberingSystem) + { + $this->numberingSystem = $numberingSystem; + } + + /** + * {@inheritdoc} + */ + public function getDecimalSeparator() + { + return $this->decimalSeparator; + } + + /** + * {@inheritdoc} + */ + public function setDecimalSeparator($decimalSeparator) + { + $this->decimalSeparator = $decimalSeparator; + } + + /** + * {@inheritdoc} + */ + public function getGroupingSeparator() + { + return $this->groupingSeparator; + } + + /** + * {@inheritdoc} + */ + public function setGroupingSeparator($groupingSeparator) + { + $this->groupingSeparator = $groupingSeparator; + } + + /** + * {@inheritdoc} + */ + public function getPlusSign() + { + return $this->plusSign; + } + + /** + * {@inheritdoc} + */ + public function setPlusSign($plusSign) + { + $this->plusSign = $plusSign; + } + + /** + * {@inheritdoc} + */ + public function getMinusSign() + { + return $this->minusSign; + } + + /** + * {@inheritdoc} + */ + public function setMinusSign($minusSign) + { + $this->minusSign = $minusSign; + } + + /** + * {@inheritdoc} + */ + public function getPercentSign() + { + return $this->percentSign; + } + + /** + * {@inheritdoc} + */ + public function setPercentSign($percentSign) + { + $this->percentSign = $percentSign; + } + + /** + * {@inheritdoc} + */ + public function getDecimalPattern() + { + return $this->decimalPattern; + } + + /** + * {@inheritdoc} + */ + public function setDecimalPattern($decimalPattern) + { + $this->decimalPattern = $decimalPattern; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getPercentPattern() + { + return $this->percentPattern; + } + + /** + * {@inheritdoc} + */ + public function setPercentPattern($percentPattern) + { + $this->percentPattern = $percentPattern; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCurrencyPattern() + { + return $this->currencyPattern; + } + + /** + * {@inheritdoc} + */ + public function setCurrencyPattern($currencyPattern) + { + $this->currencyPattern = $currencyPattern; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getAccountingCurrencyPattern() + { + return $this->accountingCurrencyPattern; + } + + /** + * {@inheritdoc} + */ + public function setAccountingCurrencyPattern($accountingCurrencyPattern) + { + $this->accountingCurrencyPattern = $accountingCurrencyPattern; + + return $this; + } +} diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php new file mode 100644 index 000000000..debafd6ba --- /dev/null +++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatEntityInterface.php @@ -0,0 +1,107 @@ +<?php + +namespace CommerceGuys\Intl\NumberFormat; + +interface NumberFormatEntityInterface extends NumberFormatInterface +{ + /** + * Sets the locale. + * + * @param string $locale The locale (i.e. "en_US"). + * + * @return self + */ + public function setLocale($locale); + + /** + * Sets the numbering system. + * + * @param string $numberingSystem One of the NUMBERING_SYSTEM_ constants. + * + * @return self + */ + public function setNumberingSystem($numberingSystem); + + /** + * Sets the decimal separator. + * + * @param string $decimalSeparator + * + * @return self + */ + public function setDecimalSeparator($decimalSeparator); + + /** + * Sets the grouping separator. + * + * @param string $groupingSeparator + * + * @return self + */ + public function setGroupingSeparator($groupingSeparator); + + /** + * Sets the plus sign. + * + * @param string $plusSign + * + * @return self + */ + public function setPlusSign($plusSign); + + /** + * Sets the minus sign. + * + * @param string $minusSign + * + * @return self + */ + public function setMinusSign($minusSign); + + /** + * Sets the percent sign. + * + * @param string $percentSign + * + * @return self + */ + public function setPercentSign($percentSign); + + /** + * Sets the number pattern used to format decimal numbers. + * + * @param string $decimalPattern The decimal pattern. + * + * @return self + */ + public function setDecimalPattern($decimalPattern); + + /** + * Sets the number pattern used to format percentages. + * + * @param string $percentPattern The percent pattern. + * + * @return self + */ + public function setPercentPattern($percentPattern); + + /** + * Sets the number pattern used to format currency amounts. + * + * @param string $currencyPattern The currency pattern. + * + * @return self + */ + public function setCurrencyPattern($currencyPattern); + + /** + * Sets the number pattern used to format accounting currency amounts. + * + * Most commonly used when formatting amounts on invoices. + * + * @param string $accountingCurrencyPattern The accounting currency pattern. + * + * @return self + */ + public function setAccountingCurrencyPattern($accountingCurrencyPattern); +} diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php new file mode 100644 index 000000000..bb343f366 --- /dev/null +++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatInterface.php @@ -0,0 +1,106 @@ +<?php + +namespace CommerceGuys\Intl\NumberFormat; + +interface NumberFormatInterface +{ + // Arabic-Indic digits. + const NUMBERING_SYSTEM_ARABIC = 'arab'; + // Extended Arabic-Indic digits. + const NUMBERING_SYSTEM_ARABIC_EXTENDED = 'arabext'; + // Bengali digits. + const NUMBERING_SYSTEM_BENGALI = 'beng'; + // Devanagari digits. + const NUMBERING_SYSTEM_DEVANAGARI = 'deva'; + // Latin digits + const NUMBERING_SYSTEM_LATIN = 'latn'; + + /** + * Gets the locale. + * + * @return string + */ + public function getLocale(); + + /** + * Gets the numbering system. + * + * The value is one of the NUMBERING_SYSTEM_ constants. + * + * @return string + */ + public function getNumberingSystem(); + + /** + * Gets the decimal separator. + * + * @return string + */ + public function getDecimalSeparator(); + + /** + * Gets the grouping separator. + * + * @return string + */ + public function getGroupingSeparator(); + + /** + * Gets the plus sign. + * + * @return string + */ + public function getPlusSign(); + + /** + * Gets the minus sign. + * + * @return string + */ + public function getMinusSign(); + + /** + * Gets the percent sign. + * + * @return string + */ + public function getPercentSign(); + + /** + * Gets the number pattern used to format decimal numbers. + * + * @return string + * + * @see http://cldr.unicode.org/translation/number-patterns + */ + public function getDecimalPattern(); + + /** + * Gets the number pattern used to format percentages. + * + * @return string + * + * @see http://cldr.unicode.org/translation/number-patterns + */ + public function getPercentPattern(); + + /** + * Gets the number pattern used to format currency amounts. + * + * @return string + * + * @see http://cldr.unicode.org/translation/number-patterns + */ + public function getCurrencyPattern(); + + /** + * Gets the number pattern used to format accounting currency amounts. + * + * Most commonly used when formatting amounts on invoices. + * + * @return string + * + * @see http://cldr.unicode.org/translation/number-patterns + */ + public function getAccountingCurrencyPattern(); +} diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php new file mode 100644 index 000000000..368eb7e2b --- /dev/null +++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepository.php @@ -0,0 +1,91 @@ +<?php + +namespace CommerceGuys\Intl\NumberFormat; + +use CommerceGuys\Intl\LocaleResolverTrait; + +/** + * Repository for number formats based on JSON definitions. + */ +class NumberFormatRepository implements NumberFormatRepositoryInterface +{ + use LocaleResolverTrait; + + /** + * Number formats. + * + * @var array + */ + protected $numberFormats = []; + + /** + * Creates a NumberFormatRepository instance. + * + * @param string $definitionPath The path to the number format definitions. + * Defaults to 'resources/number_format'. + */ + public function __construct($definitionPath = null) + { + $this->definitionPath = $definitionPath ? $definitionPath : __DIR__ . '/../../resources/number_format/'; + } + + /** + * {@inheritdoc} + */ + public function get($locale, $fallbackLocale = null) + { + $locale = $this->resolveLocale($locale, $fallbackLocale); + if (!isset($this->numberFormats[$locale])) { + $filename = $this->definitionPath . $locale . '.json'; + $definition = json_decode(file_get_contents($filename), true); + $this->numberFormats[$locale] = $this->createNumberFormatFromDefinition($definition, $locale); + } + + return $this->numberFormats[$locale]; + } + + /** + * Creates a number format object from the provided definition. + * + * @param array $definition The number format definition. + * @param string $locale The locale of the number format definition. + * + * @return NumberFormat + */ + protected function createNumberFormatFromDefinition(array $definition, $locale) + { + if (!isset($definition['decimal_separator'])) { + $definition['decimal_separator'] = '.'; + } + if (!isset($definition['grouping_separator'])) { + $definition['grouping_separator'] = ','; + } + if (!isset($definition['plus_sign'])) { + $definition['plus_sign'] = '+'; + } + if (!isset($definition['minus_sign'])) { + $definition['minus_sign'] = '-'; + } + if (!isset($definition['percent_sign'])) { + $definition['percent_sign'] = '%'; + } + + $numberFormat = new NumberFormat(); + $setValues = \Closure::bind(function ($definition, $locale) { + $this->locale = $locale; + $this->numberingSystem = $definition['numbering_system']; + $this->decimalSeparator = $definition['decimal_separator']; + $this->groupingSeparator = $definition['grouping_separator']; + $this->plusSign = $definition['plus_sign']; + $this->minusSign = $definition['minus_sign']; + $this->percentSign = $definition['percent_sign']; + $this->decimalPattern = $definition['decimal_pattern']; + $this->percentPattern = $definition['percent_pattern']; + $this->currencyPattern = $definition['currency_pattern']; + $this->accountingCurrencyPattern = $definition['accounting_currency_pattern']; + }, $numberFormat, '\CommerceGuys\Intl\NumberFormat\NumberFormat'); + $setValues($definition, $locale); + + return $numberFormat; + } +} diff --git a/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php new file mode 100644 index 000000000..ff162b522 --- /dev/null +++ b/vendor/commerceguys/intl/src/NumberFormat/NumberFormatRepositoryInterface.php @@ -0,0 +1,19 @@ +<?php + +namespace CommerceGuys\Intl\NumberFormat; + +/** + * Number format repository interface. + */ +interface NumberFormatRepositoryInterface +{ + /** + * Returns a number format instance for the provided locale. + * + * @param string $locale The locale (i.e. fr-FR). + * @param string $fallbackLocale A fallback locale (i.e "en"). + * + * @return NumberFormatInterface + */ + public function get($locale, $fallbackLocale = null); +} |